From f14246f6a4bd0305846f326fd61dab7d6cb81826 Mon Sep 17 00:00:00 2001 From: JesseBot Date: Mon, 4 Dec 2023 13:37:25 +0100 Subject: [PATCH 01/15] Update setup.py - add ffmpeg-python to required modules --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index ca2ed5b..85c838f 100644 --- a/setup.py +++ b/setup.py @@ -8,6 +8,7 @@ author="Miguel Piedrafita", install_requires=[ 'openai-whisper', + 'ffmpeg-python' ], description="Automatically generate and embed subtitles into your videos", entry_points={ From 1e9d7f680b348205b4e919c292eec930bc531fb0 Mon Sep 17 00:00:00 2001 From: soraproducer Date: Mon, 18 Mar 2024 22:34:43 -0700 Subject: [PATCH 02/15] Add new arg output_txt --- auto_subtitle/cli.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 21cdc16..6ef7393 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -18,6 +18,8 @@ def main(): default=".", help="directory to save the outputs") parser.add_argument("--output_srt", type=str2bool, default=False, help="whether to output the .srt file along with the video files") + parser.add_argument("--output_txt", type=str2bool, default=False, + help="whether to save the subtitles in a txt file") parser.add_argument("--srt_only", type=str2bool, default=False, help="only generate the .srt file and not create overlayed video") parser.add_argument("--verbose", type=str2bool, default=False, @@ -32,6 +34,7 @@ def main(): model_name: str = args.pop("model") output_dir: str = args.pop("output_dir") output_srt: bool = args.pop("output_srt") + output_txt: bool = args.pop("output_txt") srt_only: bool = args.pop("srt_only") language: str = args.pop("language") @@ -48,7 +51,7 @@ def main(): model = whisper.load_model(model_name) audios = get_audio(args.pop("video")) subtitles = get_subtitles( - audios, output_srt or srt_only, output_dir, lambda audio_path: model.transcribe(audio_path, **args) + audios, output_srt or srt_only, output_txt, output_dir, lambda audio_path: model.transcribe(audio_path, **args) ) if srt_only: @@ -88,7 +91,7 @@ def get_audio(paths): return audio_paths -def get_subtitles(audio_paths: list, output_srt: bool, output_dir: str, transcribe: callable): +def get_subtitles(audio_paths: list, output_srt: bool, output_txt: bool, output_dir: str, transcribe: callable): subtitles_path = {} for path, audio_path in audio_paths.items(): @@ -108,6 +111,13 @@ def get_subtitles(audio_paths: list, output_srt: bool, output_dir: str, transcri subtitles_path[path] = srt_path + if output_txt: + text_path = os.path.join(output_dir, f"{filename(path)}.txt") + with open(text_path, "w", encoding="utf-8") as text_file: + for segment in result["segments"]: + print(segment["text"], file=text_file) + print(f"Saving subtitles to text file: {text_path}") + return subtitles_path From f91096d3ade2fb18f866ab7133e97558028e794c Mon Sep 17 00:00:00 2001 From: Mashinow <90961989+Mashinow@users.noreply.github.com> Date: Mon, 20 May 2024 10:59:31 +0300 Subject: [PATCH 03/15] Fix ffmpeg subtitle overlay --- auto_subtitle/cli.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 21cdc16..aa9f3b5 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -55,17 +55,14 @@ def main(): return for path, srt_path in subtitles.items(): - out_path = os.path.join(output_dir, f"{filename(path)}.mp4") - - print(f"Adding subtitles to {filename(path)}...") - - video = ffmpeg.input(path) - audio = video.audio - - ffmpeg.concat( - video.filter('subtitles', srt_path, force_style="OutlineColour=&H40000000,BorderStyle=3"), audio, v=1, a=1 - ).output(out_path).run(quiet=True, overwrite_output=True) - + out_path = os.path.join(output_dir, f"{os.path.splitext(os.path.basename(path))[0]}.mp4") + print(f"Adding subtitles to {os.path.basename(path)}...") + stream = ffmpeg.input(path) + audio = stream.audio + video = stream.video.filter('subtitles', filename=srt_path, + force_style='OutlineColour=&H40000000,BorderStyle=3') + stream = ffmpeg.output(audio, video, out_path, vcodec='libx264', acodec='copy') + ffmpeg.run(stream) print(f"Saved subtitled video to {os.path.abspath(out_path)}.") From 67485acaced28565305cabd31c53beb69d69a99b Mon Sep 17 00:00:00 2001 From: davejab <13712138+davejab@users.noreply.github.com> Date: Fri, 7 Jun 2024 20:40:38 +0100 Subject: [PATCH 04/15] add word timestamps flag --- auto_subtitle/cli.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 21cdc16..9a6399c 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -28,6 +28,8 @@ def main(): parser.add_argument("--language", type=str, default="auto", choices=["auto","af","am","ar","as","az","ba","be","bg","bn","bo","br","bs","ca","cs","cy","da","de","el","en","es","et","eu","fa","fi","fo","fr","gl","gu","ha","haw","he","hi","hr","ht","hu","hy","id","is","it","ja","jw","ka","kk","km","kn","ko","la","lb","ln","lo","lt","lv","mg","mi","mk","ml","mn","mr","ms","mt","my","ne","nl","nn","no","oc","pa","pl","ps","pt","ro","ru","sa","sd","si","sk","sl","sn","so","sq","sr","su","sv","sw","ta","te","tg","th","tk","tl","tr","tt","uk","ur","uz","vi","yi","yo","zh"], help="What is the origin language of the video? If unset, it is detected automatically.") + parser.add_argument("--word_timestamps", type=str2bool, default=False, help="(experimental) extract word-level timestamps and refine the results based on them") + args = parser.parse_args().__dict__ model_name: str = args.pop("model") output_dir: str = args.pop("output_dir") From 448bfb1b8c9f5084530f9b387c9d87ec1ace89b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:34:48 +0300 Subject: [PATCH 05/15] VTT Output support added --- auto_subtitle/cli.py | 17 +++++++++++----- auto_subtitle/utils.py | 46 ++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 21cdc16..b2ecb88 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -18,6 +18,8 @@ def main(): default=".", help="directory to save the outputs") parser.add_argument("--output_srt", type=str2bool, default=False, help="whether to output the .srt file along with the video files") + parser.add_argument("--subtitle_format", type=str, default="srt", choices=["srt","vtt"], + help="subtitle file format type") parser.add_argument("--srt_only", type=str2bool, default=False, help="only generate the .srt file and not create overlayed video") parser.add_argument("--verbose", type=str2bool, default=False, @@ -32,6 +34,7 @@ def main(): model_name: str = args.pop("model") output_dir: str = args.pop("output_dir") output_srt: bool = args.pop("output_srt") + subtitle_format: str = args.pop("subtitle_format") srt_only: bool = args.pop("srt_only") language: str = args.pop("language") @@ -48,7 +51,7 @@ def main(): model = whisper.load_model(model_name) audios = get_audio(args.pop("video")) subtitles = get_subtitles( - audios, output_srt or srt_only, output_dir, lambda audio_path: model.transcribe(audio_path, **args) + audios, output_srt or srt_only, subtitle_format, output_dir, lambda audio_path: model.transcribe(audio_path, **args) ) if srt_only: @@ -88,12 +91,16 @@ def get_audio(paths): return audio_paths -def get_subtitles(audio_paths: list, output_srt: bool, output_dir: str, transcribe: callable): +def get_subtitles(audio_paths: list, output_srt: bool,subtitle_format: str, output_dir: str, transcribe: callable): subtitles_path = {} for path, audio_path in audio_paths.items(): srt_path = output_dir if output_srt else tempfile.gettempdir() - srt_path = os.path.join(srt_path, f"{filename(path)}.srt") + + if(subtitle_format=="srt"): + srt_path = os.path.join(srt_path, f"{filename(path)}.srt") + else: # vtt + srt_path = os.path.join(srt_path, f"{filename(path)}.vtt") print( f"Generating subtitles for {filename(path)}... This might take a while." @@ -104,7 +111,7 @@ def get_subtitles(audio_paths: list, output_srt: bool, output_dir: str, transcri warnings.filterwarnings("default") with open(srt_path, "w", encoding="utf-8") as srt: - write_srt(result["segments"], file=srt) + write_srt(result["segments"], file=srt,subtitle_format=subtitle_format) subtitles_path[path] = srt_path @@ -112,4 +119,4 @@ def get_subtitles(audio_paths: list, output_srt: bool, output_dir: str, transcri if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/auto_subtitle/utils.py b/auto_subtitle/utils.py index fb4e11a..7dfc16b 100644 --- a/auto_subtitle/utils.py +++ b/auto_subtitle/utils.py @@ -13,7 +13,7 @@ def str2bool(string): f"Expected one of {set(str2val.keys())}, got {string}") -def format_timestamp(seconds: float, always_include_hours: bool = False): +def format_timestamp(seconds: float, always_include_hours: bool = False,subtitle_format: str = "srt"): assert seconds >= 0, "non-negative timestamp expected" milliseconds = round(seconds * 1000.0) @@ -27,20 +27,40 @@ def format_timestamp(seconds: float, always_include_hours: bool = False): milliseconds -= seconds * 1_000 hours_marker = f"{hours:02d}:" if always_include_hours or hours > 0 else "" - return f"{hours_marker}{minutes:02d}:{seconds:02d},{milliseconds:03d}" + #return f"{hours_marker}{minutes:02d}:{seconds:02d},{milliseconds:03d}" + if subtitle_format == "srt": + output=f"{hours_marker}{minutes:02d}:{seconds:02d},{milliseconds:03d}" + else: + output= f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}" + + return output + + +def write_srt(transcript: Iterator[dict], file: TextIO,subtitle_format: str = "srt"): + + if subtitle_format == "vtt": + print("WEBVTT\n", file=file) + for i, segment in enumerate(transcript, start=1): + print( + f"{format_timestamp(segment['start'], always_include_hours=True,subtitle_format=subtitle_format)} --> " + f"{format_timestamp(segment['end'], always_include_hours=True,subtitle_format=subtitle_format)}\n" + f"{segment['text'].strip().replace('-->', '->')}\n", + file=file, + flush=True, + ) -def write_srt(transcript: Iterator[dict], file: TextIO): - for i, segment in enumerate(transcript, start=1): - print( - f"{i}\n" - f"{format_timestamp(segment['start'], always_include_hours=True)} --> " - f"{format_timestamp(segment['end'], always_include_hours=True)}\n" - f"{segment['text'].strip().replace('-->', '->')}\n", - file=file, - flush=True, - ) + else: #srt + for i, segment in enumerate(transcript, start=1): + print( + f"{i}\n" + f"{format_timestamp(segment['start'], always_include_hours=True,subtitle_format=subtitle_format)} --> " + f"{format_timestamp(segment['end'], always_include_hours=True,subtitle_format=subtitle_format)}\n" + f"{segment['text'].strip().replace('-->', '->')}\n", + file=file, + flush=True, + ) def filename(path): - return os.path.splitext(os.path.basename(path))[0] + return os.path.splitext(os.path.basename(path))[0] \ No newline at end of file From c13fbf30322aa1f8d0a6e8fe8aa12cf091efbdb8 Mon Sep 17 00:00:00 2001 From: Hayden Cook Date: Mon, 24 Jun 2024 08:46:23 -0600 Subject: [PATCH 06/15] Added an option to add soft subs to the video in a .mkv container. --- .gitignore | 3 ++- auto_subtitle/cli.py | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) mode change 100644 => 100755 auto_subtitle/cli.py diff --git a/.gitignore b/.gitignore index 6162863..e7e375e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ dist .DS_Store *.egg-info -auto_subtitle/__pycache__ \ No newline at end of file +auto_subtitle/__pycache__ +build diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py old mode 100644 new mode 100755 index 21cdc16..4055f61 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -16,6 +16,10 @@ def main(): choices=whisper.available_models(), help="name of the Whisper model to use") parser.add_argument("--output_dir", "-o", type=str, default=".", help="directory to save the outputs") + parser.add_argument("--output_mkv", type=str2bool, default=False, + help="whether to output the new subtitled video as an .mkv container (True) or an .mp4 container (False)") + parser.add_argument("--output_mkv", type=str2bool, default=False, + help="whether to output the new subtitled video as an .mkv container (True) or an .mp4 container (False)") parser.add_argument("--output_srt", type=str2bool, default=False, help="whether to output the .srt file along with the video files") parser.add_argument("--srt_only", type=str2bool, default=False, @@ -34,6 +38,7 @@ def main(): output_srt: bool = args.pop("output_srt") srt_only: bool = args.pop("srt_only") language: str = args.pop("language") + output_mkv: bool = args.pop("output_mkv") os.makedirs(output_dir, exist_ok=True) @@ -54,17 +59,22 @@ def main(): if srt_only: return + ext = "mkv" if output_mkv else "mp4" for path, srt_path in subtitles.items(): - out_path = os.path.join(output_dir, f"{filename(path)}.mp4") + out_path = os.path.join(output_dir, f"{filename(path)}.{ext}") print(f"Adding subtitles to {filename(path)}...") video = ffmpeg.input(path) audio = video.audio - ffmpeg.concat( - video.filter('subtitles', srt_path, force_style="OutlineColour=&H40000000,BorderStyle=3"), audio, v=1, a=1 - ).output(out_path).run(quiet=True, overwrite_output=True) + if output_mkv: + srt = ffmpeg.input(srt_path) + ffmpeg.output(srt, video, out_path, vcodec='copy', scodec='copy').run(quiet=False, overwrite_output=True) + else: + ffmpeg.concat( + video.filter('subtitles', srt_path, force_style="OutlineColour=&H40000000,BorderStyle=3"), audio, v=1, a=1 + ).output(out_path).run(quiet=False, overwrite_output=True) print(f"Saved subtitled video to {os.path.abspath(out_path)}.") From b0067f90e4f6db58f9a346ac9e911227dcc9962c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:16:54 +0300 Subject: [PATCH 07/15] numpy version limit --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 85c838f..60d8fac 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,8 @@ author="Miguel Piedrafita", install_requires=[ 'openai-whisper', - 'ffmpeg-python' + 'ffmpeg-python', + 'numpy<=2.0.0' ], description="Automatically generate and embed subtitles into your videos", entry_points={ From ce9dca6760b670c3e32f1792d5ec7cb6be5aa1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:47:14 +0300 Subject: [PATCH 08/15] numpy version limit fix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 60d8fac..9493b92 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ install_requires=[ 'openai-whisper', 'ffmpeg-python', - 'numpy<=2.0.0' + 'numpy<2.0.0' ], description="Automatically generate and embed subtitles into your videos", entry_points={ From 1071b533d51b6dab6da147452b56b656863a9a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:59:40 +0300 Subject: [PATCH 09/15] mkv-option-fix build folder removed from gitignore mkv-option-fix --- .gitignore | 1 - auto_subtitle/cli.py | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index e7e375e..1faac5f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ dist .DS_Store *.egg-info auto_subtitle/__pycache__ -build diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 704d528..aa21370 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -18,8 +18,6 @@ def main(): default=".", help="directory to save the outputs") parser.add_argument("--output_mkv", type=str2bool, default=False, help="whether to output the new subtitled video as an .mkv container (True) or an .mp4 container (False)") - parser.add_argument("--output_mkv", type=str2bool, default=False, - help="whether to output the new subtitled video as an .mkv container (True) or an .mp4 container (False)") parser.add_argument("--output_srt", type=str2bool, default=False, help="whether to output the .srt file along with the video files") parser.add_argument("--subtitle_format", type=str, default="srt", choices=["srt","vtt"], @@ -63,21 +61,20 @@ def main(): return ext = "mkv" if output_mkv else "mp4" - for path, srt_path in subtitles.items(): + for path, srt_path in subtitles.items(): out_path = os.path.join(output_dir, f"{os.path.splitext(os.path.basename(path))[0]}.{ext}") print(f"Adding subtitles to {os.path.basename(path)}...") stream = ffmpeg.input(path) - video = stream.video.filter('subtitles', filename=srt_path,force_style='OutlineColour=&H40000000,BorderStyle=3') audio = stream.audio + videoWithSub = stream.video.filter('subtitles', filename=srt_path,force_style='OutlineColour=&H40000000,BorderStyle=3') if output_mkv: - srt = ffmpeg.input(srt_path) - stream = ffmpeg.output(srt, video, out_path, vcodec='copy', scodec='copy') + stream = ffmpeg.output(ffmpeg.input(srt_path), stream, out_path, vcodec='copy', scodec='copy') else: - stream = ffmpeg.output(audio, video, out_path, vcodec='libx264', acodec='copy') + stream = ffmpeg.output(audio, videoWithSub, out_path, vcodec='libx264', acodec='copy') ffmpeg.run(stream) print(f"Saved subtitled video to {os.path.abspath(out_path)}.") From 48404e9e6abdc5ecefcce40b82dc0cfd7b4b6a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:17:38 +0300 Subject: [PATCH 10/15] --verbose option added --- auto_subtitle/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index aa21370..6130031 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -40,6 +40,7 @@ def main(): srt_only: bool = args.pop("srt_only") language: str = args.pop("language") output_mkv: bool = args.pop("output_mkv") + verbose: bool = args.pop("verbose") os.makedirs(output_dir, exist_ok=True) @@ -76,7 +77,7 @@ def main(): else: stream = ffmpeg.output(audio, videoWithSub, out_path, vcodec='libx264', acodec='copy') - ffmpeg.run(stream) + ffmpeg.run(stream, quiet= not verbose, overwrite_output=True) print(f"Saved subtitled video to {os.path.abspath(out_path)}.") From 9bfcddf56cce94e21db121f55f463b54c53e2679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:56:38 +0300 Subject: [PATCH 11/15] Whisper verbose fix --- auto_subtitle/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index eb8241e..67a6e2c 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -58,7 +58,7 @@ def main(): model = whisper.load_model(model_name) audios = get_audio(args.pop("video")) subtitles = get_subtitles( - audios, output_srt or srt_only, subtitle_format,output_txt, output_dir, lambda audio_path: model.transcribe(audio_path, **args) + audios, output_srt or srt_only, subtitle_format,output_txt, output_dir, lambda audio_path: model.transcribe(audio_path, **args,verbose=verbose) ) if srt_only: From 6ace7cbe85a8e6f82387af48f95297047407cf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:49:20 +0300 Subject: [PATCH 12/15] verbose argument fix --- auto_subtitle/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 429ddc6..6085a4a 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -28,7 +28,6 @@ def main(): help="only generate the .srt file and not create overlayed video") parser.add_argument("--verbose", type=str2bool, default=False, help="whether to print out the progress and debug messages") - parser.add_argument("--task", type=str, default="transcribe", choices=[ "transcribe", "translate"], help="whether to perform X->X speech recognition ('transcribe') or X->English translation ('translate')") parser.add_argument("--language", type=str, default="auto", choices=["auto","af","am","ar","as","az","ba","be","bg","bn","bo","br","bs","ca","cs","cy","da","de","el","en","es","et","eu","fa","fi","fo","fr","gl","gu","ha","haw","he","hi","hr","ht","hu","hy","id","is","it","ja","jw","ka","kk","km","kn","ko","la","lb","ln","lo","lt","lv","mg","mi","mk","ml","mn","mr","ms","mt","my","ne","nl","nn","no","oc","pa","pl","ps","pt","ro","ru","sa","sd","si","sk","sl","sn","so","sq","sr","su","sv","sw","ta","te","tg","th","tk","tl","tr","tt","uk","ur","uz","vi","yi","yo","zh"], @@ -43,9 +42,10 @@ def main(): subtitle_format: str = args.pop("subtitle_format") output_txt: bool = args.pop("output_txt") srt_only: bool = args.pop("srt_only") + verbose: bool = args["verbose"] language: str = args.pop("language") output_mkv: bool = args.pop("output_mkv") - verbose: bool = args.pop("verbose") + os.makedirs(output_dir, exist_ok=True) @@ -60,7 +60,7 @@ def main(): model = whisper.load_model(model_name) audios = get_audio(args.pop("video")) subtitles = get_subtitles( - audios, output_srt or srt_only, subtitle_format,output_txt, output_dir, lambda audio_path: model.transcribe(audio_path, **args,verbose=verbose) + audios, output_srt or srt_only, subtitle_format,output_txt, output_dir, lambda audio_path: model.transcribe(audio_path, **args) ) if srt_only: From d531f5a906e3c67b98704aae2be8fb1c5edaadfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:59:26 +0300 Subject: [PATCH 13/15] Update README.md URLs changed New name and description added --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1d21530..24ce2b0 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,16 @@ # Automatic subtitles in your videos +This is a fork of [auto_subtitle](https://github.com/m1guelpf/auto-subtitle) developed by [m1guelpf](https://github.com/m1guelpf). The main difference in `AutoSubZ` is the addition of several features, such as .vtt and .txt output, along with fixes for various bugs. + + + This repository uses `ffmpeg` and [OpenAI's Whisper](https://openai.com/blog/whisper) to automatically generate and overlay subtitles on any video. ## Installation -To get started, you'll need Python 3.7 or newer. Install the binary by running the following command: +To get started, you'll need Python 3.8 or newer. Install the binary by running the following command: - pip install git+https://github.com/m1guelpf/auto-subtitle.git + pip install git+https://github.com/zaltinsoy/AutoSubZ.git You'll also need to install [`ffmpeg`](https://ffmpeg.org/), which is available from most package managers: @@ -17,8 +21,9 @@ sudo apt update && sudo apt install ffmpeg # on MacOS using Homebrew (https://brew.sh/) brew install ffmpeg -# on Windows using Chocolatey (https://chocolatey.org/) -choco install ffmpeg +# on Windows using Winget +winget install -e --id Gyan.FFmpeg + ``` ## Usage From bc38a06187d4a33b8d3669bd6ab15a79b9576fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:10:09 +0300 Subject: [PATCH 14/15] Update requirements.txt --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 73bca28..e829d2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ openai-whisper +ffmpeg-python +numpy<2.0.0 \ No newline at end of file From a36c9778eb24275d01ff5c3e6ae76a0ea4c27006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zafer=20Alt=C4=B1nsoy?= <81522783+zaltinsoy@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:40:50 +0300 Subject: [PATCH 15/15] Make boolean flags store_true Squashed commit of the following: commit fe4f5424dc1605674f0f3d1c057fe9b70b3f1e5a Author: Darren Jeacocke Date: Wed Mar 29 22:14:13 2023 +1000 Remove unused str2bool function commit 4ee986eee4b0a49515381bb0a6725b3c0d54b84d Author: Darren Jeacocke Date: Wed Mar 29 21:56:13 2023 +1000 Make boolean flags store_true --- auto_subtitle/cli.py | 32 ++++++++++++++++++-------------- auto_subtitle/utils.py | 11 ----------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/auto_subtitle/cli.py b/auto_subtitle/cli.py index 6085a4a..ef6196c 100644 --- a/auto_subtitle/cli.py +++ b/auto_subtitle/cli.py @@ -4,7 +4,7 @@ import argparse import warnings import tempfile -from .utils import filename, str2bool, write_srt +from .utils import filename, write_srt def main(): @@ -16,24 +16,28 @@ def main(): choices=whisper.available_models(), help="name of the Whisper model to use") parser.add_argument("--output_dir", "-o", type=str, default=".", help="directory to save the outputs") - parser.add_argument("--output_mkv", type=str2bool, default=False, - help="whether to output the new subtitled video as an .mkv container (True) or an .mp4 container (False)") - parser.add_argument("--output_srt", type=str2bool, default=False, - help="whether to output the .srt file along with the video files") parser.add_argument("--subtitle_format", type=str, default="srt", choices=["srt","vtt"], help="subtitle file format type") - parser.add_argument("--output_txt", type=str2bool, default=False, - help="whether to save the subtitles in a txt file") - parser.add_argument("--srt_only", type=str2bool, default=False, + parser.add_argument("--output_mkv", action="store_true", + help="whether to output the new subtitled video as an .mkv container rather than .mp4 container") + parser.add_argument("--output_srt", action="store_true", + help="output the .srt file along with the video files") + parser.add_argument("--output_txt", action="store_true", + help="whether to also save the subtitles as a .txt file") + parser.add_argument("--srt_only", action="store_true", help="only generate the .srt file and not create overlayed video") - parser.add_argument("--verbose", type=str2bool, default=False, - help="whether to print out the progress and debug messages") + parser.add_argument("--verbose", action="store_true", + help="print out the progress and debug messages") + parser.add_argument("--task", type=str, default="transcribe", choices=[ "transcribe", "translate"], help="whether to perform X->X speech recognition ('transcribe') or X->English translation ('translate')") - parser.add_argument("--language", type=str, default="auto", choices=["auto","af","am","ar","as","az","ba","be","bg","bn","bo","br","bs","ca","cs","cy","da","de","el","en","es","et","eu","fa","fi","fo","fr","gl","gu","ha","haw","he","hi","hr","ht","hu","hy","id","is","it","ja","jw","ka","kk","km","kn","ko","la","lb","ln","lo","lt","lv","mg","mi","mk","ml","mn","mr","ms","mt","my","ne","nl","nn","no","oc","pa","pl","ps","pt","ro","ru","sa","sd","si","sk","sl","sn","so","sq","sr","su","sv","sw","ta","te","tg","th","tk","tl","tr","tt","uk","ur","uz","vi","yi","yo","zh"], - help="What is the origin language of the video? If unset, it is detected automatically.") - - parser.add_argument("--word_timestamps", type=str2bool, default=False, help="(experimental) extract word-level timestamps and refine the results based on them") + parser.add_argument("--language", type=str, default="auto", choices=["auto","af","am","ar","as","az","ba","be","bg","bn","bo","br","bs","ca","cs","cy","da","de","el","en", + "es","et","eu","fa","fi","fo","fr","gl","gu","ha","haw","he","hi","hr","ht","hu","hy","id","is","it","ja","jw","ka","kk","km","kn","ko","la","lb","ln", + "lo","lt","lv","mg","mi","mk","ml","mn","mr","ms","mt","my","ne","nl","nn","no","oc","pa","pl","ps","pt","ro","ru","sa","sd","si","sk","sl","sn","so", + "sq","sr","su","sv","sw","ta","te","tg","th","tk","tl","tr","tt","uk","ur","uz","vi","yi","yo","zh"], + help="What is the origin language of the video? If unset, it is detected automatically.") + parser.add_argument("--word_timestamps", action="store_true", default=False, + help="(experimental) extract word-level timestamps and refine the results based on them") args = parser.parse_args().__dict__ model_name: str = args.pop("model") diff --git a/auto_subtitle/utils.py b/auto_subtitle/utils.py index 7dfc16b..7c483be 100644 --- a/auto_subtitle/utils.py +++ b/auto_subtitle/utils.py @@ -2,17 +2,6 @@ from typing import Iterator, TextIO -def str2bool(string): - string = string.lower() - str2val = {"true": True, "false": False} - - if string in str2val: - return str2val[string] - else: - raise ValueError( - f"Expected one of {set(str2val.keys())}, got {string}") - - def format_timestamp(seconds: float, always_include_hours: bool = False,subtitle_format: str = "srt"): assert seconds >= 0, "non-negative timestamp expected" milliseconds = round(seconds * 1000.0)