.ytt format:a working reference
A reference for YouTube's timed-text format — the XML behind styled captions, saved as .ytt and known inside YouTube as format 3 or SRV3. Everything below is what the format accepts in practice, including the values that look reasonable and get silently dropped.
The shape of a file
<timedtext format="3">
<head>
<pen id="1" b="1" fc="#FEFEFE" fo="254" et="4" ec="#000000"/>
<wp id="0" ap="7" ah="50" av="90"/>
<ws id="0" ju="2"/>
</head>
<body>
<p t="1000" d="1600" wp="0" ws="0" p="1">Today we fix that.</p>
</body>
</timedtext>
The head declares reusable styles: pen for text, wp for where the caption window sits, ws for how the text is aligned inside it. The body is the list of caption lines, each pointing at the styles it uses by id.
<pen> — the text style
| Attribute | Values | Meaning |
|---|---|---|
fs | 0–7 | Font: 0 default sans, 1 Courier New, 2 Times New Roman, 3 Lucida Console, 5 Comic Sans MS, 6 Monotype Corsiva, 7 Carrois Gothic SC. 4 is undefined. |
sz | integer | Size. 100 is YouTube's default; the scale is non-linear (see below). |
b, i, u | "1" | Bold, italic, underline. Written only when true. |
fc | #RRGGBB | Text colour. Pure #FFFFFF is commonly written as #FEFEFE. |
fo | 0–254 | Text opacity. 255 is stripped — fully opaque is 254. |
bc, bo | #RRGGBB, 0–254 | Background box colour and its opacity. bo="0" removes the box. |
et | 1–4 | Edge: 1 hard shadow, 2 bevel, 3 glow, 4 soft shadow. There is no outline type — a dark glow is used as one. |
ec | #RRGGBB | Edge colour. Defaults to #222222 at the text's opacity. |
of | 0–2 | Offset: 0 subscript, 1 normal, 2 superscript. |
rb | 0–5 | Ruby annotation (furigana): 0 none, 1 base, 2 parenthesis, 4 text before, 5 text after. |
The size formula
The value in sz is not the size you mean. It moves four times faster than the real scale:
sz = (1 + (scale − 1) × 4) × 100
scale = 1 + (sz / 100 − 1) / 4
So sz="100" is 100%, sz="200" is 125%, and sz="50" is about 87%. YouTube's default caption size is roughly 4.6–4.8% of the frame height, which is the size sz="100" renders at.
<wp> — the window position
| Attribute | Values | Meaning |
|---|---|---|
ap | 0–8 | Anchor point: 0 top-left, 1 top-centre, 2 top-right, 3 middle-left, 4 centre, 5 middle-right, 6 bottom-left, 7 bottom-centre, 8 bottom-right. |
ah | 0–100 | Horizontal position. |
av | 0–100 | Vertical position. |
Positions are not raw percentages of the frame. YouTube maps them into a safe area:
screen% = value × 0.96 + 2
av="0" lands at 2% from the top and av="100" at 98%. A converter going the other way uses value = (screen% − 2) / 0.96.
<ws> — the window style
| Attribute | Values | Meaning |
|---|---|---|
ju | 0–2 | Justification: 0 left, 1 right, 2 centre. |
pd | 0–3 | Print direction; 0 is horizontal left-to-right. |
sd | 0–1 | Scroll direction, for vertical text. |
<p> and <s> — lines and segments
| Attribute | Values | Meaning |
|---|---|---|
p.t | ≥ 1 ms | Start time. Some Android players ignore a line that starts at 0. |
p.d | > 0 ms | Duration. |
p.wp, p.ws | id | Window position and window style to use. |
p.p | id | Pen for the whole line. |
s.p | id | Pen for one segment inside the line. |
s.t | ≥ 0 ms | Segment start, relative to the line — this is how word-by-word timing works. |
The quirks that cost an afternoon
- Only one edge per pen. An outline and a shadow on the same text means writing the line twice, with two pens, one on top of the other.
- Thicker outlines are stacked copies. Repeat the same glow-edged line a few times; do not enlarge the font of the copies underneath, or the layers drift apart horizontally.
- Opacity 255 disappears. Use 254.
- Zero-width padding. Lines that mix several styled segments need zero-width spaces around them, or some mobile players collapse the styling into the line's own pen.
- No animation. Zoom and roll-up are series of caption entries, a few dozen milliseconds apart.
- Viewer settings win. Anyone who changed their caption appearance in the player sees their settings, not your pens.
Where this information comes from
The format is not documented publicly by YouTube. The reference behaviour comes from YTSubConverter, the open-source converter whose source is the de-facto specification, checked against real caption tracks downloaded from YouTube and against what the players actually render. Rainbow Captions writes the same format — you can build tracks by hand from the tables above, or let the app handle the layering, the guards and the per-word timing.
Rainbow Captions handles the pens, the layered outlines, the guard characters and the per-word timing, in 170 languages. Free to download, first 10 languages free.
Download for Mac