用 Praat TextGrid 往返完成 ToBI 韻律標註
在 Potato 2.13.1 中以點層標註 ToBI 聲調和停頓指數:從你的 Praat TextGrid 開始,匯出 Praat 能直接讀回的 TextGrid。
手頭有錄音和 Praat TextGrid 的語音學家和韻律研究者,可以按照本教程在 Potato 2.13.1 中做 ToBI 標註,並以 TextGrid 的形式取回標籤。ToBI(Tones and Break Indices)是一套轉寫語調和韻律短語劃分的規範。Silverman et al. (1992) 針對美國英語提出了 ToBI。本頁的任務顯示錄音的波形,波形下方有四個層(tier)。聲調層和停頓指數(break index)層存放時間點,詞層存放區間,雜項層標記不流利現象和噪聲。點層是 Potato 2.13.1 新增的,匯入器和 textgrid 匯出器都能讀寫 Praat 點層。多名標註者可以在同一臺伺服器上標註相同的語句,每名標註者的結果各自匯出為一個 TextGrid。
ToBI 的四個層
一份 ToBI 轉寫把音訊、F0 記錄和四個層配在一起。Beckman, Hirschberg, and Shattuck-Hufnagel (2005) 列出的最初的主流美國英語系統(MAE_ToBI)的各層如下:
- 聲調(Tones)。 音高重音、短語重音和邊界調,各自位於一個時間點。
- 詞(Words)。 正字法轉寫,並在時間上標出每個詞的結尾。
- 停頓指數(Break indices)。 0 到 4 之間的一個數字,表示每個詞之後的音渡(juncture)程度。
- 雜項(Misc)。 不流利現象、備註和其他事件。
在 Praat TextGrid 中,聲調和停頓指數通常是點層(TextTier),詞和雜項是區間層。下面配置中的標籤清單遵循同一章中的 MAE_ToBI 表格:
| 標籤類型 | 標籤 |
|---|---|
| 音高重音 | H*, L*, L+H*, L*+H, H+!H*,以及降階的 !H*, L+!H*, L*+!H |
| 短語重音 | L-, H-, !H-(位於每個停頓指數 3 或 4 處) |
| 邊界調 | L%, H%(位於每個停頓指數 4 處),以及地位邊緣的起始調 %H |
| 不確定 | *?, -?, %? 表示是否出現了聲調,X*?, X-?, X%? 表示出現的是哪個聲調 |
| 停頓指數 | 0, 1, 2, 3, 4,用 - 表示不確定(3-, 4-),用 p 表示猶豫(1p, 2p, 3p) |
分層檢視與缺失的 F0 軌跡
Potato 的 tiered_annotation 方案繪製整段錄音的波形、當前視窗的放大波形,以及每個層一行。在點層上,標註者單擊即以當前標籤放置一個點,拖動即可移動點。要給一個點換標籤,標註者先選中這個點,再點選另一個標籤按鈕;按 Delete 鍵刪除選中的點。在區間層上,標註者單擊並拖動。
Potato 2.13.1 的分層檢視中沒有 F0 軌跡,也沒有語譜圖。標註者要對照 F0 曲線判斷音高重音。請在 Praat 中開啟同一個 WAV 檔案來檢視音高軌跡。每個層也只提供配置中列出的標籤,沒有輸入標籤的文本框。因此詞來自 TextGrid,而不是由標註者輸入。
準備 TextGrid
把每個語句的一個 TextGrid 和一個 WAV 檔案放進同一個資料夾,檔名彼此對應,例如 utt01.TextGrid 和 utt01.wav。把各層命名為 tones、words、breaks 和 misc,其中 tones 和 breaks 為點層。強制對齊工具可以生成詞層,Montreal Forced Aligner 預設寫出長格式的 TextGrid。在 Praat 中用 Insert point tier 和 Insert interval tier 命令給對齊工具的輸出補上缺少的三個層。匯入前刪除對齊工具輸出的音素層,因為下面的配置只列出四個 ToBI 層。已有標籤的層會作為預標註進入 Potato。因此,另一名標註者完成的初標會以預標註的形式進來。
匯入 TextGrid
匯入命令把資料夾轉換成一個 Potato 項目,每個 TextGrid 對應一個條目:
potato import -i textgrids -o tobi_project我們的測試資料夾裡有三個語句,一個已標註,兩個只有詞。匯入器的報告如下:
Imported 3 item(s), 1 question(s), 0 answer(s) from 0 annotator(s), and 3 model suggestion(s) on 3 item(s) from Praat TextGrid files (with their audio) as tiered annotations.
wrote tobi_project/data/textgrids.jsonl
wrote tobi_project/media/utt01.wav
wrote tobi_project/media/utt02.wav
wrote tobi_project/media/utt03.wav
wrote tobi_project/config.yaml
wrote tobi_project/README.md每個 TextGrid 層都成為名為 tiers 的那個 tiered_annotation 方案中的一個層,每個點層仍是點層。不同取值不超過 30 個的層,會把這些取值作為該層的標籤。在我們的資料夾裡,聲調層只得到已標註語句用到的五個聲調,停頓層得到 0、1、3 和 4。不同取值更多的層只得到一個以層名命名的標籤,並把每個區間的文本儲存在片段的 value 欄位中。任何真實語料庫的詞層都屬於這種層。每個匯入的點和區間都是預標註。每名標註者把匯入的標籤當作起點,Potato 只在該標註者儲存時才儲存這些標籤。
在波形上方顯示詞
詞層的每個區間都顯示標籤 words,詞本身保留在 value 欄位中。匯入器把每個條目的文本設為 TextGrid 的檔名。在 tobi_project 中執行下面的指令碼,把這段文本替換為該語句按順序排列的詞:
import json
path = "data/textgrids.jsonl"
items = [json.loads(line) for line in open(path)]
for item in items:
words = item["predictions"]["tiers"]["annotations"].get("words", [])
item["text"] = " ".join(w["value"] for w in sorted(words, key=lambda w: w["start_time"]))
with open(path, "w") as f:
f.writelines(json.dumps(item) + "\n" for item in items)之後,Potato 會在第一個語句的各層上方顯示“Marianna made the marmalade before the guests arrived at noon”。
配置
下面的配置替換生成的 config.yaml。新配置保留生成的資料和預標註設定,並給每個層配上完整的標籤清單:
annotation_task_name: ToBI labeling
task_dir: .
port: 8000
data_files:
- data/textgrids.jsonl
item_properties:
id_key: id
text_key: text
output_annotation_dir: annotation_output/
user_config:
allow_all_users: true
users: []
pre_annotation:
enabled: true
field: predictions
allow_modification: true
annotation_schemes:
- annotation_type: tiered_annotation
name: tiers
description: Label tones and break indices; correct the word boundaries if needed.
source_field: audio_url
media_type: audio
tiers:
- name: tones
point: true
labels: ["H*", "!H*", "L*", "L+H*", "L+!H*", "L*+H", "L*+!H", "H+!H*",
"L-", "H-", "!H-", "L-L%", "L-H%", "H-L%", "H-H%", "!H-L%", "%H",
"*?", "X*?", "-?", "X-?", "%?", "X%?", "%r"]
- name: words
labels: [words]
- name: breaks
point: true
labels: ["0", "1", "2", "3", "4", "3-", "4-", "1p", "2p", "3p"]
- name: misc
labels: [disfl, laugh, breath, cough, noise, interrupt]這份配置做了以下選擇:
- 完整的標籤列表。 匯入器只列出檔案中出現過的標籤,而標註者無法放置配置中沒有的聲調。
- 合併的邊緣調。 MAE_ToBI 讓停頓指數 4 處的短語重音和邊界調取該停頓的時間。因此一個標為 L-L% 的點同時標記短語重音和邊界調。出於同樣的原因,單獨的 L% 和 H% 沒有列入。
- 層名和順序。 層名與 TextGrid 的層一致時,預標註會落在正確的行上。匯出按配置中的順序寫出各層。
- 固定的雜項列表。 Potato 的層不接受手動輸入的標籤。因此雜項層提供六個事件標籤,自由文本的備註留在 Praat 中。
- 聲調層上的
%r。 MAE_ToBI 在聲調層上標記語調重啟(contour restart),在雜項層上標記不流利現象本身。 words是詞層唯一的標籤。 這個標籤與匯入器寫入的一致。因此詞層用於移動詞邊界,在詞層上新畫的區間匯出時文本為words。
驗證器對照 Potato 自己的鍵列表檢查每個鍵,對這份配置和匯入器生成的配置都輸出了 OK — no issues found.:
python -m potato.validate_cli config.yaml --strict在瀏覽器中標註
啟動命令在 8000 埠上提供這個任務:
potato start config.yaml -p 8000每名標註者登入後,會在波形上方看到詞,並在放置點之前從層選單中選擇一個層。一種可行的順序是先在每個詞的結尾放置停頓指數。接著標音高重音,最後在每個停頓指數 3 或 4 處標邊緣調。如果每個語句需要兩名標註者以計算一致性,請在配置中設定 num_annotators_per_item: 2。
匯出回 Praat
匯出命令為每名標註者儲存過的每個語句寫出一個 TextGrid:
python -m potato.export -c config.yaml -f textgrid -o textgrid_out在我們的測試中,兩名模擬標註者儲存了第一個語句,匯出寫出了這些檔案:
Files written:
textgrid_out/utt01_annotator1_tiers.TextGrid
textgrid_out/utt01_annotator2_tiers.TextGrid只有一名標註者的項目,檔名中不含使用者名稱,例如 utt01_tiers.TextGrid。Praat 6.1.38 通過 Parselmouth 0.4.6 讀取了這兩個檔案。Praat 識別出聲調層和停頓層為點層,識別出十個詞,以及雜項層上的一個 breath。第二名標註者的檔案與源 TextGrid 只有兩處不同:該標註者把一個聲調從 0.35 秒移到了 0.36 秒,以及 0 被寫成了 0.0。
往返過程中 TextGrid 保留和丟失的欄位
經過 Potato 往返一次,TextGrid 的以下部分會保留下來:
- 層。 層名以及點層或區間層的類型按匯入時的樣子返回;配置保持原始檔的順序時,層的順序也一致。
- 時間。 Potato 以毫秒為單位、保留三位小數儲存點的時間和區間邊界。因此每個時間都保持微秒精度。
- 標籤。 聲調標籤、停頓標籤和每個詞區間的文本都會返回,標籤內的引號會像 Praat 那樣寫成兩個。
- 網格長度。 網格結束於標註頁面測得的音訊長度,或原始檔的
xmax。
以下部分會丟失:
- 起始時間。 無論原始檔的
xmin是多少,匯出都讓網格和每個層從 0 開始。 - 未儲存的語句。 沒有人儲存過的語句根本不會得到 TextGrid。
- 檔名。 匯出把檔案命名為
<item>_<scheme>.TextGrid,有多名標註者時為<item>_<user>_<scheme>.TextGrid。 - 編碼。 Praat 常以 UTF-16 儲存,而匯出寫的是 UTF-8。Praat 兩種編碼都能讀取。
- 重疊。 Praat 不允許同一層上有重疊的區間,匯出會把每處重疊列為一條警告。
兩名標註者之間的一致性
Potato 位於 /admin/iaa 的一致性報告為每個 tiered_annotation 方案給出一個平均一致性,並把四個層合併在一起計算。Potato 按時間重疊匹配兩名標註者的點和區間,匹配上但標籤不同的一對得一半分。兩個點只有在時間完全相同時才算匹配。在我們的測試中,第一個語句的兩份答案只有一個聲調的位置相差 10 毫秒,得分是 0.93 而不是 1.0。另兩份答案的每個聲調和停頓都相差 1 毫秒,得分為 0.24,因為只有十個詞區間仍然匹配。
Potato 2.13.1 不計算帶時間容差的聲調標籤一致性,不計算分層的一致性,也不為停頓指數計算 kappa 或有序統計量。時間維度上的一致性中的容差掃描屬於機器人片段(robot episode)的分界點,不覆蓋 tiered_annotation。要得到 ToBI 的信度數字,請匯出兩名標註者的 TextGrid,再在 Praat 或你自己的指令碼中,按你選定的時間視窗配對兩名標註者的聲調。
本頁背後的測試執行
本頁的 TextGrid 和 WAV 檔案由一個指令碼生成,WAV 檔案裡是合成音而不是語音。指令碼按每個詞的長度為其分配時間,聲調和停頓的時間由我們手工選定。匯入、驗證器、伺服器和匯出都由 Potato 2.13.1 執行。兩名模擬標註者通過標註頁面傳送的同一個 /updateinstance 請求儲存結果。一致性數字來自在兩份儲存的答案上執行 /admin/iaa 背後的函式。
延伸閱讀
- 匯入項目:TextGrid 和 ELAN 匯入器的全部選項
- 語言學標註工具比較:Praat、ELAN、FLEx 和 EMU-SDMS 與 Potato 的對照,以及如何檢查強制對齊得到的音素邊界
- 時間維度上的一致性:Potato 如何在時間上匹配片段
- 用 Potato 做語言學研究:在同一處瞭解行間註釋、層修正和方言任務
參考文獻
- Beckman, M. E., Hirschberg, J., & Shattuck-Hufnagel, S. (2005). The original ToBI system and the evolution of the ToBI framework. In S.-A. Jun (Ed.), Prosodic Typology: The Phonology of Intonation and Phrasing (pp. 9-54). Oxford University Press. https://doi.org/10.1093/acprof:oso/9780199249633.003.0002
- Silverman, K., Beckman, M., Pitrelli, J., Ostendorf, M., Wightman, C., Price, P., Pierrehumbert, J., & Hirschberg, J. (1992). ToBI: A standard for labeling English prosody. Proceedings of the 2nd International Conference on Spoken Language Processing (ICSLP 1992), 867-870. https://doi.org/10.21437/ICSLP.1992-260