Batch-convert subtitle formats with SeConv (Subtitle Edit CLI)
💡 SeConv - Subtitle Edit 5.0's command-line batch converter - converts subtitle files with a single command. The target format is the second positional argument with spaces stripped:
seconv in.srt ScenaristClosedCaptionsDropFrame --fps:29.97 --output-folder:out --overwrite. For 29.97 drop-frame broadcast SCC, always useScenaristClosedCaptionsDropFrame(notScenaristClosedCaptions): one outputs semicolon-separated DF timecodes, the other outputs colon-separated NDF. SRT-to-SCC is lossy: positioning, styling and non-Latin characters are all discarded by the CEA-608 character set.
Key takeaways
- Run
seconv formatsto list every supported format; strip spaces when passing it as the second argument ("Scenarist Closed Captions Drop Frame" becomesScenaristClosedCaptionsDropFrame). Format names are case-insensitive. - Broadcast SCC at 29.97 drop-frame:
seconv *.srt ScenaristClosedCaptionsDropFrame --fps:29.97 --output-folder:out --overwrite - Streaming TTML (SMPTE-TT 2052 / ST 2052-1):
seconv *.srt SMPTE-TT2052 --output-folder:out --overwrite - SRT to SCC is a lossy conversion: positioning, bold/italic styling, and any non-Latin characters are dropped by the CEA-608 character set (Latin-only).
- The
--fpsflag matters for frame-based source formats and for setting the SCC timecode frame rate; it has no effect on purely time-based conversions such as SRT to WebVTT.
What is SeConv and how does the command work?
SeConv is Subtitle Edit 5.0's headless batch converter - the same format engine as the GUI, driven from a terminal. I use it for every seconv batch convert subtitle formats job where I need to process more than one file or integrate a conversion step into a build pipeline, without opening a GUI.
The command takes three parts in order: an input glob pattern, the target format name with spaces stripped, and optional flags. Run seconv formats once to see the full format table, then take the Format Name column and remove all spaces - that string is your second argument.
# See what format, encoding and duration SeConv detects in a file
seconv info episode01.srt
# SRT to WebVTT (web players, YouTube upload, HTML5 <track> element)
seconv episode01.srt WebVTT --output-folder:out --overwrite
# Batch: every .srt in the current directory to WebVTT
seconv *.srt WebVTT --output-folder:out --overwrite
- info [file]: reports the detected format, character encoding, event count and total duration without writing any output - run this first on an unfamiliar file before committing to a conversion path.
- --output-folder:out: writes converted files to the specified folder; SeConv creates the folder if it does not exist.
- --overwrite: replaces existing output files without prompting; omit this flag if you want SeConv to skip files that already exist at the destination.
Which format name do I use for each deliverable?
The table below covers the format names I reach for in broadcast and streaming work. Every name here is taken directly from the seconv formats output, with spaces stripped:
| Delivery target | Format name (second argument) | Extension | Lossy? |
|---|---|---|---|
| Web video, YouTube upload, HTML5 track | WebVTT | .vtt | No |
| US broadcast 29.97 drop-frame (CEA-608) | ScenaristClosedCaptionsDropFrame | .scc | Yes |
| US broadcast non-drop-frame (CEA-608) | ScenaristClosedCaptions | .scc | Yes |
| Streaming TTML / SMPTE-TT (ST 2052-1) | SMPTE-TT2052 | .xml | Minimal |
| ASS for further styling or ffmpeg burn-in | AdvancedSubStationAlpha | .ass | Adds defaults |
| SRT re-encode to UTF-8 (normalize encoding) | SubRip | .srt | No |
The drop-frame distinction between the two SCC formats is not cosmetic. ScenaristClosedCaptionsDropFrame writes timecodes with semicolons as the frame separator (01;00;00;00 indicates DF), while ScenaristClosedCaptions writes colons (01:00:00:00 indicates NDF). US broadcast at 29.97 fps uses drop-frame timecode; delivering an NDF SCC on 29.97 footage will cause captions to drift by approximately 3.6 seconds per hour of programme.
How do I batch-convert a whole folder of SRT files to broadcast SCC?
The glob pattern is the first argument - SeConv expands it and processes all matching files in one pass, with no shell loop required. I use this every time I need to convert a full series of episode SRTs to broadcast SCC before delivery.
# All .srt files in the current folder to drop-frame SCC
seconv *.srt ScenaristClosedCaptionsDropFrame --fps:29.97 --output-folder:broadcast --overwrite
# All .srt files from a specific source folder
seconv *.srt ScenaristClosedCaptionsDropFrame --fps:29.97 --input-folder:C:subssource --output-folder:C:subsroadcast --overwrite
# QC-decode one output file with caption-inspector to confirm the text survived
docker run --rm -v C:subsroadcast:/data nebulabroadcast/caption-inspector -o /data /data/episode01.scc
- --input-folder:path: resolves relative glob patterns against this folder, useful when running the command from a different working directory.
- caption-inspector: the decode check I never skip after an SCC batch. It writes a
.608plain-text decode alongside the source file so I can confirm the dialogue text survived the CEA-608 character-set mapping before the files leave my machine.
What does the --fps flag actually change in the output?
The --fps flag has two separate roles depending on the source and target format, and it matters to understand which role applies to your conversion.
For frame-based source formats - those that store timecodes as frame counts rather than HH:MM:SS.mmm timestamps, like MicroDVD .sub - --fps tells SeConv the frame rate of the original so it can convert frame counts to real timestamps correctly. Get this wrong and every event in the output will be offset.
For time-based sources going to SCC, --fps sets the frame rate written into the SCC timecodes. This is where it matters in broadcast delivery work.
# Frame-based source: MicroDVD .sub at 25 fps to SRT
seconv movie.sub SubRip --fps:25 --output-folder:out --overwrite
# Time-based SRT to SCC at 29.97 drop-frame
seconv episode.srt ScenaristClosedCaptionsDropFrame --fps:29.97 --output-folder:out --overwrite
# List the format and any detected frame rate before converting
seconv info movie.sub
For purely time-based conversions - SRT to WebVTT, SRT to SMPTE-TT, SRT to ASS - the --fps flag is irrelevant because all three formats store timestamps in HH:MM:SS.mmm notation already.
Which conversions are safe to round-trip, and which are lossy?
Not all conversions preserve everything. Here is how I think about the common paths in practice:
| Conversion | Round-trip safe? | What is lost or changed |
|---|---|---|
| SRT to WebVTT | Yes | Comma in milliseconds becomes a dot per W3C WebVTT spec; no text or timing loss |
| WebVTT to SRT | Mostly | Cue settings (line:, position:, align:) and ::cue CSS styling are stripped |
| SRT to ASS | Yes | SeConv adds a default [V4+ Styles] block; original dialogue preserved |
| ASS to SRT | Lossy | Color, position, font and karaoke timing data stripped |
| SRT to SMPTE-TT | Yes | XML wrapper added; timing preserved exactly |
| SMPTE-TT to SRT | Minor loss | Inline XML styling stripped |
| SRT to SCC (608) | Lossy | Positioning, bold/italic styling, and non-Latin characters all dropped; CEA-608 is Latin character set only |
| SCC to SRT | Lossy | Row/column positioning and roll-up stream metadata stripped |
The SRT-to-SCC path is the one I treat with the most caution. The CEA-608 character set is limited to Latin-1 plus a small set of extended characters defined in the CTA-608 standard - any character outside that set, such as typographic quotes, extended punctuation, or any CJK text, will be substituted or dropped silently. A caption-inspector decode of the output is the only reliable way to confirm what actually survived the mapping.
What you can do in SeConv yourself, and when broadcast delivery needs more than a format swap
SeConv handles the mechanical conversion well. Format-to-format jobs such as SRT to WebVTT, SRT to SMPTE-TT, and SRT to ASS are a single command and I run them in batch every week without manual review. The command-line interface means they compose cleanly into a larger pipeline.
The SRT-to-SCC path is where I slow down. Beyond the character-set risk described above, broadcast clients often require specific caption placement (roll-up vs pop-on, row assignments, channel attribution) that a format conversion alone cannot configure - those settings must be authored into the source before conversion. And if the source SRT was built without caption discipline - CPS too high, lines too long, events shorter than the minimum duration - the SCC will fail QC regardless of what SeConv produces.
If you are delivering closed captions for a US broadcast or SVOD platform - where FCC standards mandate accuracy, synchronicity, completeness and correct placement - and you do not have a QC step that catches CEA-608 encoding errors before the files leave your machine, that is the point where a practitioner who runs this workflow daily saves you a retake fee. The caption QC service covers the decode check, CPS and line-length review, and a final placement pass before delivery.
FAQ
How do I find the exact format name for a seconv conversion?
Run seconv formats in a terminal. It prints a numbered table of every supported format. Take the Format Name column, strip all spaces, and use that string as the second argument. Format names are case-insensitive, so webvtt and WebVTT both work.
Do I need --fps for SRT-to-WebVTT or SRT-to-SMPTE-TT conversions?
No. SRT, WebVTT, ASS and SMPTE-TT all store timestamps in HH:MM:SS.mmm notation, so no frame-rate conversion is needed. The --fps flag only matters when the source uses frame counts (MicroDVD .sub) or when writing SCC timecodes from a time-based source.
Can seconv convert an SCC file back to SRT?
Yes: seconv in.scc SubRip --output-folder:out --overwrite. The decoded dialogue text and timing come through, but caption positioning (row, column, roll-up stream) is stripped in the round-trip. Check the event count with seconv info out/in.srt after conversion.
Why are there two SCC format names - with and without "Drop Frame"?
"Scenarist Closed Captions" (ScenaristClosedCaptions) outputs NDF timecodes with colons (01:00:00:00). "Scenarist Closed Captions Drop Frame" (ScenaristClosedCaptionsDropFrame) outputs DF timecodes with semicolons (01;00;00;00). US broadcast at 29.97 fps is drop-frame; a NDF SCC on a 29.97 programme will drift by approximately 3.6 seconds per hour of content.
Does seconv support converting image-based subtitles (PGS .sup, VobSub .sub) to SRT?
Yes, with an OCR engine. Add --ocr-engine:tesseract (or nocr, binaryocr, llamacpp) and optionally --ocr-language:eng. Run seconv list-ocr-engines to see which engines are installed on your machine. OCR accuracy varies; always review the output text before delivery.
Official Sources
- Subtitle Edit - GitHub (niksedk) - SeConv 5.0 CLI interface, format list and option reference; format names and flag syntax verified against the installed binary. Verified Oct 2026.
- W3C WebVTT Level 1 Specification - File structure, dot-notation timestamp format, STYLE block rules; confirms the comma-to-dot change in SRT-to-WebVTT conversion. Verified Oct 2026.
Written by Dao Huy (Lucas), Vietnamese translator & localization specialist (EN · ZH · FR → Vietnamese). See translation services →
