Last active
August 1, 2026 15:43
-
-
Save etodd/0bca3def141dfc6883feecb14f6393e1 to your computer and use it in GitHub Desktop.
YouTube VTT cleaning script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Forked and improved version of https://github.com/anandiamy/Batch-Single-Clean-Youtube-Vtt/blob/main/single_clean.py | |
| # Remove duplicated lines from a .vtt file generated by youtube-dl when | |
| # downloading auto-subs from a Youtube video using the --write-auto-sub option | |
| # This script only prints the lines so save the edited subs as: | |
| # | |
| # python this_script.py original_sub.vtt new_sub.vtt | |
| import re | |
| import sys | |
| import html | |
| # a subtitle is a timestamp line followed by one or more lines of text | |
| # Find a line starting with a time stamp: 00:13:23 ... | |
| TIMESTAMP_PATTERN = re.compile(r'^\d\d:\d\d:\d\d', re.M) | |
| # Matches inline YouTube timestamps like: | |
| # <00:00:01.680> | |
| INLINE_TIMESTAMP_PATTERN = re.compile(r'<\d\d:\d\d:\d\d\.\d{3}>') | |
| # Matches caption formatting tags like: | |
| # <c> and </c> | |
| CAPTION_TAG_PATTERN = re.compile(r'</?c>') | |
| def clean_vtt_line(line): | |
| """Remove YouTube inline timestamps and caption formatting tags.""" | |
| line = INLINE_TIMESTAMP_PATTERN.sub('', line) | |
| line = CAPTION_TAG_PATTERN.sub('', line) | |
| line = html.unescape(line) | |
| return line | |
| def print_subtitle(output_file, timestamp, text, previous_text): | |
| deduped = [line for line in text if line == '\n' or line not in previous_text] | |
| if len([line for line in deduped if line.strip()]) == 0: | |
| return | |
| output_file.write(timestamp) | |
| for t in deduped: | |
| output_file.write(t) | |
| def clean_vtt_content(input_file, output_file): | |
| with open(input_file, 'r', encoding='utf-8') as f: | |
| subtitle_timestamp = '' | |
| subtitle_text = [] | |
| last_subtitle_text = [] | |
| for line in f: | |
| line = clean_vtt_line(line) | |
| if re.findall(TIMESTAMP_PATTERN, line): | |
| print_subtitle(output_file, subtitle_timestamp, subtitle_text, last_subtitle_text) | |
| last_subtitle_text = subtitle_text | |
| subtitle_timestamp = line | |
| subtitle_text = [] | |
| continue | |
| subtitle_text.append(line) | |
| print_subtitle(output_file, subtitle_timestamp, subtitle_text, last_subtitle_text) | |
| if __name__ == "__main__": | |
| try: | |
| input_file = sys.argv[1] | |
| output_file = sys.argv[2] | |
| with open(output_file, 'w', encoding='utf-8') as out_f: | |
| clean_vtt_content(input_file, out_f) | |
| print(f"File successfully cleaned and saved to {output_file}") | |
| except FileNotFoundError: | |
| print("Error: Input file not found") | |
| except Exception as e: | |
| print(f"An error occurred: {str(e)}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment