From 60ef9c0db8da38675ace1deefffa528d6b7c3afc Mon Sep 17 00:00:00 2001 From: Jacob Schmieder <64411886+Jaikinator@users.noreply.github.com> Date: Tue, 20 Dec 2022 13:54:29 +0100 Subject: [PATCH] Add files via upload --- autotranscript/__init__.py | 4 + autotranscript/__main__.py | 126 ++++++++++++++++++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 207 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 3877 bytes autotranscript/version.py | 69 ++++++++++ environment.yml | 96 +++++++++++++ requirements.txt | 3 + setup.py | 38 ++++++ transcribe.py | 4 + 9 files changed, 340 insertions(+) create mode 100644 autotranscript/__init__.py create mode 100644 autotranscript/__main__.py create mode 100644 autotranscript/__pycache__/__init__.cpython-39.pyc create mode 100644 autotranscript/__pycache__/__main__.cpython-39.pyc create mode 100644 autotranscript/version.py create mode 100644 environment.yml create mode 100644 requirements.txt create mode 100644 setup.py create mode 100644 transcribe.py diff --git a/autotranscript/__init__.py b/autotranscript/__init__.py new file mode 100644 index 0000000..13f245b --- /dev/null +++ b/autotranscript/__init__.py @@ -0,0 +1,4 @@ +from autotranscript.__main__ import * +from autotranscript.version import get_version as _get_version + +__version__ = _get_version() \ No newline at end of file diff --git a/autotranscript/__main__.py b/autotranscript/__main__.py new file mode 100644 index 0000000..ec06c3c --- /dev/null +++ b/autotranscript/__main__.py @@ -0,0 +1,126 @@ + +import whisper +from time import time +import os +from moviepy.editor import * +from typing import Union + +class Transcribe: + def __init__(self, audiofile : Union[bool, str, list] = None, model : str = "medium", language :str = "German"): + """ + Class to autotranscript audio and video files with the Whisper model + :param audiofile: audio file or list of audio files + :param model: model to use for transcription + :param language: language of the audio file + """ + + self.audiofile = audiofile + + self.language = language + + """ + Create folder structure + """ + + self.currentpath,\ + self.audiopath,\ + self.transcriptionpath,\ + self.audiofiles = self.create_folder_structure() # create folder structure + + print("loading model") + self.model = whisper.load_model(model) # load model + print("model loaded") + + def create_folder_structure(self): + """ + Create folder structure for audio and transcription files + + :return: currentpath, audiopath, transcriptionpath, audiofiles + """ + currentpath = os.getcwd() # get current path + + if not os.path.exists(os.path.join(currentpath, 'audiofiles')): + print('Creating audiofiles folder') + os.makedirs(os.path.join(currentpath, 'audiofiles')) + if not os.path.exists(os.path.join(currentpath, 'transcription')): + print('Creating transcription folder') + os.makedirs(os.path.join(currentpath, 'transcription')) + + audiopath = os.path.join(currentpath, 'audiofiles') # path to audio files + transcriptionpath = os.path.join(currentpath, 'transcription') # path to transcription files + + audiofiles = os.listdir(audiopath) # list of audio files + + return currentpath, audiopath, transcriptionpath, audiofiles + + def video_to_audio(self,file, remove_video=True): + clip = VideoFileClip(file) + clip.audio.write_audiofile(os.path.join(file[:-4] + '.mp3')) + if remove_video: + os.remove(file) + print(f'Video {file} removed') + return os.path.join(file[:-4] + '.mp3') + + + def transcribe(self): + + if self.audiofile is not None: + if self.audiofile in self.audiofiles: + audiofile = os.path.join(self.audiopath, self.audiofile) + else: + raise ValueError('Audio file not found') + + if audiofile.endswith('.mp4'): + print('Converting video to audio') + audiofile = self.video_to_audio(audiofile) + + print(f'Start transcribing Audio file: {audiofile}') + _stime = time() + result = self.model.transcribe(audiofile, verbose=True, language= self.language) + + print(f'Transcription finished in {time() - _stime} seconds') + + txtfilename = str(audiofile.split('/')[-1][:-4]) + '.txt' + + savepath = os.path.join(self.transcriptionpath, txtfilename) + + with open(savepath, 'w') as f: + f.write(result["text"]) + elif self.audiofile is None or isinstance(self.audiofile, list): + print('No audio file specified or list of audio files') + print(f"{len(self.audiofiles)} audio files found in {self.audiopath}") + print("Start transcribing all audio files") + i = 0 + for audiofile in self.audiofiles: + + audiofile = os.path.join(self.audiopath, audiofile) + + if audiofile.endswith('.mp4'): + audiofile = self.video_to_audio(audiofile) + + print(f'Start transcribing Audio file: {audiofile}') + _stime = time() + result = self.model.transcribe(audiofile, verbose=True, language=self.language) + print(f'Transcription finished in {time() - _stime} seconds') + + txtfilename = str(audiofile.split('/')[-1][:-4]) + '.txt' + + savepath = os.path.join(self.transcriptionpath, txtfilename) + + with open(savepath, 'w') as f: + f.write(result["text"]) + + i += 1 + print(f'{i} of {len(self.audiofiles)} files transcribed') + + else: + raise ValueError('Audio file not found') + + print('Transcription finished') + + def __call__(self): + return self.transcribe() + def __repr__(self): + return f"Transcribe(audiofile={self.audiofile}, model={self.model}, language={self.language})" + def __str__(self): + return f"Transcribe(audiofile={self.audiofile}, model={self.model}, language={self.language})" diff --git a/autotranscript/__pycache__/__init__.cpython-39.pyc b/autotranscript/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04235a59ba7faa9afadc9a70dcffc98425d2d511 GIT binary patch literal 207 zcmYe~<>g`kf~*w_ldXXCV-N=!FabFZKwK;WBvKes7;_jxAT%S8W(sD|WPS;hVbEl} z#i-?{$#jdWq$n}3IJqb@DK$zM!Pbk9&rQtCi;rK)P{aaM4<>$D>1X8Urs`)UCg&&V z2UI3!Bo^fc6y;~7CYKcJhi7CK7o-;HBMi}xkI&4@EQycTE2zB1VUwGmQks)$#|Sj8 J801b4MgTh4HDv$* literal 0 HcmV?d00001 diff --git a/autotranscript/__pycache__/__main__.cpython-39.pyc b/autotranscript/__pycache__/__main__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d64ee0a076cccf9df024581a10a7941259f67616 GIT binary patch literal 3877 zcmd59O>ZMfwW`0|>Dc-HAcGj1IpJZH%nFuWq8+qLhFwn9NR!?)eLHG2JObaRe;v0U zZ4mM|oXmeFOg@Are+GaNMiUZXZzQx!14_#^BQRjiOw41PTZz@R1Dldh2(y{^iREi4sxIrQ{C0Q=K4&eAsS&3`sbK7=N}0KiE=8G)O&xXCSUbLZ6D zBhcH-`m?ETvV$6{G4}-tT(-?Tw)}zyORUZsu;Q^5whH|+TVw0c*VzW!gubEq+9|wa z5v8&%;uGE~oGxc^zgsw;aM6v@S7xyk^;w*q#tAR%ZpL_0xJi^g>qpOc+XC*UAC8gj zBWUt5fB_wlkPJ+KFd7+S@`VLsoMUf8b5xDdD-fn~M@s`^j2IrQ8Mwww5Sx|%%k!t- zQ4&e%tISsw$G+yyk5cBJ$Bbt_GAjLxSe^OmjQgLT#j?kRuQ{(M9rhv-bxT}CIGm8d zv7ZS)iKX(h)45f76IT;FEa@UkeaZb(K%KJIQ=r$INK?Tb`qL5Kf_#?G!22tlypd!P zi_>T2C3#(6>Ej}2t>&^=0wIfK0L5-w@JR9SG)ov4p;V&ZR(-*X<#t~Po~mA?&L*1F z!}SF=^^#ZVSr&Fr#HlK37p3$94=)Y%{Q}*lX%&{_$!W;~u4q195wQj1H}4*tWnF&I ziQ3u8!IR7OStPnoMAqSLB@ZSVIY18D2VvNa;xr8RdzXb9hH)CJFvN#Rq(ofDaF(3^ zIMl+Q;nF(IH;*gr?@uw>6i-h+v_c1(w#2`{K#>t0lOa{4V~k7GI3m0j8! zoN^ZTz%CatOpTEMhNZ1`9z*X-_abQ z70!-K*b5p9eB|G$jxMZEPB-1c$YkL>e4N$p|L_&4A02#&Dqa4 z_|0(}!~gWd$X0`{TBe1CAt$JpJE0Dtfz<}0HzZrE z=)F*7CH?n-phRgC5U>x<>CrWs@6CyJ@%(~=x`2j0t_AwUfK)*`kU#rW{1Zpe=s6Mh zmC-RrkSaQmDmnxlh^DTBYR$a@ht*saVKh70oto4eU}Wail?=K z1svIGePFZ3mGQ^BLucTOHU=hJ*#q@c@;TsI@Vhc8N!Q*X^6w7`)xTc?yryXjUj?s* zv0PJ|I8$3!#h2*nX+Q?=}7M@ysGXW;>}`JJiJ>y!@{rm;NZ%#TwaoL2I7mNNN<9=ryhek<;R-2)fuxhm)d)PnrE z%J*B7+e>btU}?vvF_5^u6v=ny$^}_IOy73z7T%*InLjNsQNBiyTUdMK8)f>KJ(#n6 z=k^yhcglRP1MgyN(P6ppK8un*|G5yEC|nM&#xhKY8}U83QGlltT|X3_s&aT)!I+Th z3S0J)Sn23qSXqy!g{?zc;l(merGkQi7ZzrP!c2JDbj!Sep(Jpi>Vdi%gPiOqDp&>y zV{A*KE)QH8opYUV=xIUY8?jB?2Lc~KlfM8!3=gV|EyIQ0r5j)jdmJx#WoW=miNDNtBVdfZ$=fukvfVc|i|nz4R@<9Zl=*^iQPM_{2)SSMMQ zh#w&KLj+if=(?oz0kk#oV+21zaEM?gC_U1Z3>LBY42cDgOYiQvJKmD}z6*9KaIaYt z@V9m1Q|OGr3RDL%?_KUg^`yW99d+4*=%u;RD7W2HxF3{{`6=3v#8MuMY!`lY