Convert and Edit Subtitles SRT, VTT and ASS with Python
Subtitles exist in multiple formats: SRT (most common), WebVTT (for web), ASS/SSA (styled), and LRC (song lyrics). Python lets you convert, edit, and re-sync them.
Installation
pip install srt webvtt-py pysrt
Read and Parse SRT Files
import srt
from datetime import timedelta
def read_srt(srt_path):
with open(srt_path, encoding='utf-8') as f:
subtitles = list(srt.parse(f.read()))
for sub in subtitles[:5]:
start = str(sub.start).split('.')[0]
end = str(sub.end).split('.')[0]
print(f"[{sub.index}] {start} --> {end}")
print(f" {sub.content}\n")
return subtitles
subs = read_srt("movie.srt")
print(f"Total subtitles: {len(subs)}")
Convert SRT to WebVTT
import srt
def srt_to_vtt(input_srt, output_vtt):
with open(input_srt, encoding='utf-8') as f:
subtitles = list(srt.parse(f.read()))
def fmt(td):
total = int(td.total_seconds())
h, r = divmod(total, 3600)
m, s = divmod(r, 60)
ms = td.microseconds // 1000
return f"{h:02}:{m:02}:{s:02}.{ms:03}"
lines = ["WEBVTT", ""]
for sub in subtitles:
lines += [str(sub.index), f"{fmt(sub.start)} --> {fmt(sub.end)}", sub.content, ""]
with open(output_vtt, 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
print(f"VTT created: {output_vtt} ({len(subtitles)} entries)")
srt_to_vtt("movie.srt", "movie.vtt")
Convert WebVTT to SRT
import webvtt
import srt
from datetime import timedelta
def vtt_to_srt(input_vtt, output_srt):
subtitles = []
for i, caption in enumerate(webvtt.read(input_vtt), 1):
def parse_time(s):
parts = s.replace(',','.').split(':')
h, m = int(parts[0]), int(parts[1])
s_ms = parts[2].split('.')
secs = int(s_ms[0])
ms = int(s_ms[1]) if len(s_ms) > 1 else 0
return timedelta(hours=h, minutes=m, seconds=secs, milliseconds=ms)
subtitles.append(srt.Subtitle(
index=i,
start=parse_time(caption.start),
end=parse_time(caption.end),
content=caption.text
))
with open(output_srt, 'w', encoding='utf-8') as f:
f.write(srt.compose(subtitles))
print(f"SRT created: {output_srt} ({len(subtitles)} entries)")
vtt_to_srt("video.vtt", "video.srt")
Re-sync Subtitles (Shift Timing)
import srt
from datetime import timedelta
def shift_srt(input_file, output_file, offset_seconds):
with open(input_file, encoding='utf-8') as f:
subs = list(srt.parse(f.read()))
delta = timedelta(seconds=offset_seconds)
for sub in subs:
sub.start = max(timedelta(0), sub.start + delta)
sub.end = max(timedelta(0), sub.end + delta)
with open(output_file, 'w', encoding='utf-8') as f:
f.write(srt.compose(subs))
print(f"Shifted {offset_seconds:+.1f}s -> {output_file}")
shift_srt("movie.srt", "movie_synced.srt", -2.5) # 2.5s earlier
shift_srt("movie.srt", "movie_synced.srt", +5.0) # 5s later
Strip HTML Tags from Subtitles
import srt
import re
def clean_srt(input_file, output_file):
with open(input_file, encoding='utf-8') as f:
subs = list(srt.parse(f.read()))
for sub in subs:
# Remove HTML tags: <i>, <b>, <font color="...">, etc.
sub.content = re.sub(r'<[^>]+>', '', sub.content)
sub.content = re.sub(r'\s+', ' ', sub.content).strip()
with open(output_file, 'w', encoding='utf-8') as f:
f.write(srt.compose(subs))
print(f"Cleaned SRT: {output_file} ({len(subs)} subtitles)")
clean_srt("with_tags.srt", "clean.srt")
Extract Plain Text (For Translation)
import srt
def srt_to_text(input_srt, output_txt):
with open(input_srt, encoding='utf-8') as f:
subs = list(srt.parse(f.read()))
lines = [sub.content.replace('\n', ' ') for sub in subs]
with open(output_txt, 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
print(f"Text extracted: {output_txt} ({len(lines)} lines)")
srt_to_text("movie.srt", "transcript.txt")
Additional Resource
For converting video files between MP4, MKV, AVI and other formats without any coding, use KaijuConverter — free and no registration required.
Related conversions
Frequent conversions across the catalogue: