TTML 字幕格式
這種格式能表達什麼
- 文字樣式
- 字型、顏色、描邊、陰影
- 畫面定位
- 是
- 卡拉 OK 計時
- 否
- 字幕段落內換行
- 是
- 時間軸
- 每條字幕都有開始與結束時間
- 時間精確度
- 1 毫秒
- 時間以影格編號儲存
- 否
- 由右至左的文字
- 是
範例
一份典型的 TTML 檔,以及從中讀出的內容
檔案
<?xml version="1.0" encoding="UTF-8"?>
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:tts="http://www.w3.org/ns/ttml#styling" xml:lang="en">
<head>
<styling>
<style xml:id="s1" tts:color="#FFFF00" tts:fontWeight="bold"/>
</styling>
<layout>
<region xml:id="bottom" tts:origin="10% 80%" tts:extent="80% 20%"/>
</layout>
</head>
<body>
<div>
<p begin="00:00:01.000" end="00:00:03.500" region="bottom" style="s1">Hello <span tts:fontStyle="italic">there</span>.</p>
<p begin="00:00:03.500" end="00:00:06.000" region="bottom">How are you?<br/>Fine, thanks.</p>
</div>
</body>
</tt>
從中讀出了什麼
2 cues, 3 lines of text
00:00:01.000 → 00:00:03.500
Hello there. [italic ×1]
[region="bottom" style="s1"]
00:00:03.500 → 00:00:06.000
How are you?
Fine, thanks.
[region="bottom"]
Outside the cues:
prolog an XML declaration and the namespace bindings, kept as they came in
styling 1 × <style> — "s1", the colour and weight a paragraph points at by name
layout 1 × <region> — "bottom", the origin and extent a paragraph points at by name
resolved the head is kept as it was written and is not applied here — a paragraph's style="s1" region="bottom" stays an attribute, not a colour or a screen position右欄不是轉換產物,而是本站從左欄檔案裡讀出的內容:cue 的時間與正文、段落內的強調,以及頭部保留了什麼。
一份格式凌亂的 TTML 檔,仍然讀得出什麼
檔案
<?xml version="1.0" encoding="UTF-8"?>
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:tts="http://www.w3.org/ns/ttml#styling">
<body>
<div begin="00:00:01.000" end="00:00:05.000">
<p>Inherits its timing from the div, which we do not resolve.</p>
<p begin="00:00:06.000" end="00:00:07.000">This one has its own timing.</p>
</div>
<!-- <p begin="00:00:08.000" end="00:00:09.000">commented out</p> -->
<div>
<p begin="00:00:10.000"/>
<p begin="00:00:11.000" end="00:00:12.000">Last one.</p>
</div>
</body>
</tt>
從中讀出了什麼
3 cues, 2 lines of text
00:00:06.000 → 00:00:07.000
This one has its own timing.
00:00:10.000 → 00:00:12.000
(no text)
00:00:11.000 → 00:00:12.000
Last one.
Outside the cues:
prolog an XML declaration and the namespace bindings, kept as they came in
head none — no <styling> and no <layout>, and no paragraph points at one either
comments the commented-out <p> stays a comment, in the place it was written
divs the timings on an enclosing <div> are not pushed down onto the paragraphs inside it
Reported while reading — repaired or skipped, never silently:
1 × paragraphs with no readable begin time of their own (they were skipped — see the note about timing inherited from an enclosing div)
1 × paragraphs with neither an end time nor a duration of their own (their end times were generated)繼承時間、被註解掉的段落、沒有正文的 `<p>`、沒有結束時間的 cue 都在這一份裡。解析不拋例外:讀不出來的如實回報,能讀出的照常讀出。
把 TTML (Timed Text) 轉成其他格式
每一個都完全在你的瀏覽器裡執行。標籤標明了那個方向要付出什麼代價,打開之前就能看到。
轉換為此格式
- SubRip (SRT) → TTML (Timed Text)
- WebVTT (VTT) → TTML (Timed Text)
- Advanced SubStation Alpha (ASS) → TTML (Timed Text)
- SubStation Alpha (SSA) → TTML (Timed Text)
- YouTube SBV → TTML (Timed Text)
- SAMI (SMI) → TTML (Timed Text)
- LRC Lyrics → TTML (Timed Text)
- MicroDVD → TTML (Timed Text)
- SubtitleMatrix JSON → TTML (Timed Text)
- Plain Text (TXT) → TTML (Timed Text)
- CSV Spreadsheet → TTML (Timed Text)
TTML(Timed Text Markup Language)是廣播與串流那套 XML 字幕:Netflix、EBU-TT-D、IMSC 都建在它上面。一條字幕是一個 `<p>`,起止時間寫在 `begin` / `end` 上;整份檔案是一個 XML 文件,`<p>` 外面還有 `<tt>`、`<body>`、`<div>` 這幾層。
它比大多數格式多一層「頭部」。`<styling>` 定義具名樣式(`tts:color`、`tts:fontFamily`),`<layout>` 定義具名區域(`tts:origin`、`tts:extent`),而 `<p style="s1" region="bottom">` 只是按名字引用它們。改一處頭部就能改全片,這也是轉成 cue 模型時丟得最多的部分。
時間有四種寫法:時鐘 `00:00:04.126`、位移 `1.5s` / `250ms`、影格 `00:00:01:12`、影格位移 `36f`。後兩種要影格率,影格率從 `<tt>` 的 `ttp:frameRate` 與 `ttp:frameRateMultiplier` 讀;讀不到就不猜 30 fps,而是把那條記成「時間讀不出來」。本站按 cue 解析,`tickRate`、`subFrameRate` 與 `ttp:timeBase` 屬於文件頭部,不做 tick 重算。所有轉換都在瀏覽器裡完成,不上傳、不註冊,也可以批次處理。
常見問題
TTML 的 `<p begin="…" end="…">` 之外還有什麼?
還有 XML 宣告與命名空間綁定、`<head>` 裡的 `<styling>` 與 `<layout>` 兩張表、可能存在的 `<metadata>`,以及 `<body>` / `<div>` 這層結構。`<p>` 透過 `style` 與 `region` 按名字引用頭部裡的定義。
TTML 的 `tickRate` 與 `subFrameRate` 是做什麼的?
它們是 TTML 規範裡按 tick 計時的參數:`tickRate` 表示每秒有多少個 tick,`subFrameRate` 把一個影格再細分。它們屬於文件頭部的時間基準設定;本站讀 cue 時用的是時鐘、位移與 `frameRate`,不按 tick 重算時間軸。
TTML 的 `ttp:timeBase` 取 `media` 還是 `smpte` 有差別嗎?
有。`media` 是相對媒體時間的時鐘基準,`smpte` 是時間碼基準(可以帶丟格約定),同一條時間串在兩種基準下的含義不同。本站按時鐘、位移、影格三種寫法解析 cue,並且不解析父層 `<div>` 上的時間繼承。
TTML 支援逐字卡拉 OK 計時嗎?
不支援。一條 `<p>` 只有開始與結束,沒有記錄音節逐個亮起的欄位;所以從 ASS 轉成 TTML 時,卡拉 OK 計時會進入損失清單。
TTML 的樣式與區域在檔案裡怎麼組織?
`<styling>` 裡是一張具名樣式表,`<layout>` 裡是一張具名區域表,`<p>` 用 `style="s1"` 與 `region="bottom"` 引用。定義與使用分開,所以參照本身在轉成 cue 模型時會消失,定義也一起丟。