💡 TL;DR: When a client asks for a "CEA-708 caption file," deliver SMPTE-TT (ST 2052-1) XML, not an MCC produced by Subtitle Edit or SeConv. The open-source MCC encoder writes a 708 service layer that caption-inspector cannot decode, while SMPTE-TT XML carries structured timing and positioning data that broadcast QC tools actually accept. One command:
seconv input.srt SMPTE-TT2052 --output-folder out --fps 29.97 --overwrite.
Key takeaways
- SeConv format name:
SMPTE-TT2052(no spaces) produces a compliant ST 2052-1 XML file;MacCaption1.0produces .mcc but the 708 service layer is broken in the open-source build. - QC check:
docker run --rm -v <dir>:/data nebulabroadcast/caption-inspector -o /data /data/<file>- if the -S1.708 output is empty on an MCC, the 708 service is not broadcast-safe. - SMPTE-TT XML: uses the SMPTE namespace (
xmlns:smpte="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt"), drop-frame 29.97 declared viattp:frameRateMultiplier="1000 1001", and frame-accurate timing in<p begin="HH:MM:SS:FF">. - Native 708 MCC: if the deliverable truly requires a native 708-service MCC, you need commercial software (Telestream MacCaption) - no free tool produces it reliably.
- 608 cannot carry CJK: SCC and the 608 compatibility layer of MCC/708 are Latin-only; other languages go as subtitle tracks, not embedded captions.
Why does a "708 caption" request lead to confusion, and what is wrong with open-source MCC?
CEA-708 (now CTA-708) is the digital closed-caption standard used in US broadcast since the ATSC transition. When a client asks for "708 captions," they want a file whose timing and text data can be decoded by a 708-capable receiver: a broadcast QC station, a streaming ingest validator, or caption-inspector. The common assumption is that any .mcc file delivers this. That assumption trips people up.
I ran into this the first time a client's QC vendor rejected an MCC I had converted with Subtitle Edit. The file opened fine in Subtitle Edit and played back in a soft player, but caption-inspector returned an empty 708 decode.
The reason: Subtitle Edit produces a syntactically valid .mcc file with all the required headers, but the internal byte stream that is supposed to carry a native 708 service (window definitions, pen attributes, set-pen-location commands) is not populated correctly. What it does write is the 608 compatibility bytes - which is why the text plays back - but not the 708 window service itself. So the 708 decode is empty even though the 608 decode is clean. Delivering SMPTE-TT XML sidesteps this entirely: its timing and positioning live in structured, readable XML that every modern validator can parse without relying on the 708 service encoding.
What does a SMPTE-TT (ST 2052-1) file actually declare?
SMPTE ST 2052-1 is a profile of TTML (W3C Timed Text Markup Language) with added SMPTE namespaces for caption metadata. Here is the structure that SeConv produces from an SRT input:
<?xml version="1.0" encoding="utf-8"?>
<tt xml:lang="en"
xmlns="http://www.w3.org/ns/ttml"
xmlns:tts="http://www.w3.org/ns/ttml#styling"
xmlns:ttm="http://www.w3.org/ns/ttml#metadata"
xmlns:ttp="http://www.w3.org/ns/ttml#parameter"
ttp:timeBase="media"
ttp:frameRate="29"
ttp:frameRateMultiplier="1000 1001"
xmlns:smpte="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt"
xmlns:m608="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt#cea608">
<head>
<metadata>
<ttm:title>My Show - Episode 1</ttm:title>
<smpte:information
origin="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt#cea608"
mode="Preserved"
m608:channel="CC1"
m608:programName="Demo"
m608:captionService="F1C1CC" />
</metadata>
<styling>
<style xml:id="basic"
tts:color="white"
tts:fontFamily="Arial"
tts:backgroundColor="transparent"
tts:fontSize="21" />
</styling>
<layout>
<region xml:id="bottom"
tts:origin="10% 55%"
tts:extent="80% 80%"
tts:displayAlign="after" />
<region xml:id="top"
tts:origin="10% 10%"
tts:extent="80% 80%"
tts:displayAlign="before" />
</layout>
</head>
<body>
<div>
<p begin="00:00:01:00" end="00:00:04:00"
tts:textAlign="center" region="bottom" style="basic">
Hello, this is a test caption.
</p>
<p begin="00:00:05:00" end="00:00:08:14"
tts:textAlign="center" region="bottom" style="basic">
Second caption line here.
</p>
</div>
</body>
</tt>
Key fields to understand:
ttp:frameRate="29" ttp:frameRateMultiplier="1000 1001": declares 29.97 drop-frame. The multiplier 1000/1001 is the standard TTML way to express the 0.1% pulldown. Timecodes in the body use HH:MM:SS:FF format against that rate.xmlns:smpteandxmlns:m608: these SMPTE namespaces declare ST 2052-1 compliance and the 608 metadata channel. A broadcast validator checks for these namespaces.m608:channel="CC1": caption channel 1, the standard location for English closed captions in the US.tts:origin / tts:extenton each region: percentage-based positioning; 10% 55% keeps captions in the lower third.- Frame-accurate
begin/end: no ambiguity about drop vs non-drop because the frame rate is declared once in the header, not per cue.
How do I convert with SeConv and verify the result?
SeConv is the command-line batch-converter included with Subtitle Edit. The format name is SMPTE-TT2052 (no spaces, as listed by seconv formats):
# Single file - SRT to SMPTE-TT at 29.97 drop-frame
seconv input.srt SMPTE-TT2052 --output-folder out/ --fps 29.97 --overwrite
# Batch - all SRTs in the current folder
seconv "*.srt" SMPTE-TT2052 --output-folder out/ --fps 29.97 --overwrite
SMPTE-TT2052: the exact format name; runseconv formatsto see the full list.--fps 29.97: tells SeConv to interpret and write timecodes at 29.97. Without this flag it defaults to 24fps; a 29.97 project with a 24fps SMPTE-TT file will drift immediately at the receiving end.--overwrite: replaces an existing .xml in the output folder; omit on a first run to avoid accidents.- Output is
input.xmlin the output folder. The SMPTE namespaces and frame-rate declaration are written automatically.
For QC I run caption-inspector on the source SCC (if the workflow started from an SCC) to verify the 608 decode, then deliver the SMPTE-TT XML for the 708 deliverable:
# QC-decode a reference SCC or MCC
docker run --rm -v C:/captions:/data nebulabroadcast/caption-inspector -o /data /data/my-show-ep1.scc
caption-inspector writes three files into the mapped folder:
my-show-ep1-C1.608: plain-text decode of the CEA-608 stream, channel CC1. I read this to verify dialogue, line breaks, and placement.my-show-ep1-S1.708: decode of the CEA-708 service 1. If I run this on a Subtitle Edit-produced MCC and the 708 output is empty, that confirms the broken 708 service layer.my-show-ep1.ccd: Closed Caption Descriptor - machine-readable packet count and error summary.
When is a native 708 MCC actually required, and what then?
Most broadcast and streaming clients that say "708 captions" are actually checking for SMPTE-TT (or they accept SCC + SMPTE-TT alongside it). A small number of facilities - particularly those using older cable TV playout systems or MacCaption-based post-production pipelines - explicitly require a native 708-service MCC. In that case, the honest answer is that you need commercial software.
Telestream MacCaption is the industry standard for native 708 MCC production. Broadcast facilities and post houses typically have a license. If you are doing occasional broadcast work and cannot justify the license cost, the practical path is: deliver SMPTE-TT XML as the baseline and flag the MCC requirement so the client can route it to their facility for the MacCaption mux step. I handle this about once a year on legacy cable TV delivery jobs.
What can I do myself, and when is a specialist worth it?
With Subtitle Edit, SeConv, and caption-inspector (Docker), you can handle the full workflow for most streaming and internet delivery: SRT to SMPTE-TT XML, a QC decode pass on the source SCC, and spot-check of the dialogue. That is the free-tool path for English closed captions and English SDH.
A professional captioner adds: reading-speed (CPS) compliance per the Netflix Timed Text Style Guide or BBC subtitling guidelines, SDH formatting (sound cues, speaker IDs, music notation), accurate synchronization to the final audio mix, and the ability to coordinate with a broadcast facility for MCC delivery where required. For ADA/CVAA compliance - required for US broadcast and certain online video under federal law - an independently QC'd deliverable from a captioner who knows the FCC quality benchmarks is the standard the client is looking for.
If you need English closed captions or SDH with SMPTE-TT delivery, my caption QC service covers the full pipeline: timed transcript, Subtitle Edit CPS check, SeConv SMPTE-TT export, caption-inspector QC pass, and broadcast-ready XML.
FAQ
Can I use the SMPTE-TT XML file directly in a broadcast playout system?
It depends on the system. Most modern broadcast validators and streaming ingest platforms (Amazon, Apple, Netflix) accept SMPTE-TT / TTML as a delivery format. Older playout hardware that expects embedded captions in an MXF or a physical SCC file may not parse TTML directly - in that case the SMPTE-TT is a deliverable for QC and the facility handles the final mux. Check the specific facility spec before delivery.
Does caption-inspector work on SMPTE-TT XML files, or only on SCC and MCC?
caption-inspector is designed to decode CEA-608 and CEA-708 from binary caption streams: SCC, MCC, and embedded-caption video (MPEG-2 TS, MP4). It does not parse SMPTE-TT XML directly. To QC a SMPTE-TT file I validate the XML structure and play it back in VLC; for a full 608/708 decode QC I run caption-inspector on the source SCC.
What is the difference between the 608 compatibility layer and a native 708 service?
The 608 compatibility layer is a copy of the CEA-608 caption data embedded inside the 708 packet structure so that older 608-only decoders can display the captions. Every properly encoded 708 file carries this layer. A native 708 service goes further: it adds 708-specific window definitions, pen attributes, and positioning that a 708-capable receiver can use. Subtitle Edit's MCC export writes the 608 layer (which is why text plays back) but not a working native 708 window service.
Is there a free tool that produces a broadcast-safe native 708 MCC?
Not reliably, as of my testing. caption-inspector can convert SCC to MCC, but the result carries only the 608 compatibility layer, same as Subtitle Edit. The only tools I know that produce a proper native 708-service MCC are Telestream MacCaption and a few other commercial caption authoring systems used by broadcast post-production facilities.
Does the --fps flag in SeConv affect the timecodes in the SMPTE-TT XML?
Yes. SeConv uses --fps to both read the input timecodes and write the ttp:frameRate and ttp:frameRateMultiplier values in the output XML. If your source SRT uses millisecond timing (as all SRTs do) and your project is 29.97, --fps 29.97 converts millisecond values to the nearest 29.97 frame boundary. At 24fps the values come out wrong for a 29.97 project, which shows up as a constant offset error at the receiving end.
Official Sources
- Subtitle Edit by Nikolaj Lynge Olsen (nikse.dk) - SeConv format names and SMPTE-TT2052 export. Verified Oct 2026.
- caption-inspector by Comcast (GitHub) - Docker QC decode tool, output files (-C1.608, -S1.708, .ccd). Verified Oct 2026.
- W3C Timed Text Markup Language 2 (TTML2) - TTML base specification underlying SMPTE-TT ST 2052-1. Verified Oct 2026.
- FCC Closed Captioning on Television - US broadcast caption delivery requirements. Verified Oct 2026.

Écrit par Đào Huy (Lucas), traducteur vietnamien et spécialiste de la localisation (anglais, chinois et français vers le vietnamien). See translation services →
