Skip to content
Туториалы10 мин чтения

Разметка просодии по ToBI с полным циклом через Praat TextGrid

Разметка тонов ToBI и индексов границ на точечных уровнях в Potato 2.13.1, от импорта ваших файлов Praat TextGrid до экспорта TextGrid, которые Praat читает обратно.

Potato Team

Фонетисты и исследователи просодии, у которых есть записи и файлы Praat TextGrid, могут по этому руководству провести разметку ToBI в Potato 2.13.1 и получить метки обратно в виде TextGrid. ToBI (Tones and Break Indices, «тоны и индексы границ») представляет собой набор соглашений для транскрипции интонации и просодического членения. Silverman et al. (1992) ввели ToBI для американского английского. Задача на этой странице показывает осциллограмму записи и четыре уровня под осциллограммой. Уровни тонов и индексов границ содержат моменты времени, уровень слов содержит интервалы, а уровень misc отмечает сбои речи и шум. Точечные уровни появились в Potato 2.13.1, и импортёр, и экспортёр textgrid читают и записывают точечные уровни Praat. Несколько разметчиков могут размечать одни и те же высказывания на одном сервере, и работа каждого разметчика экспортируется в отдельный TextGrid.

Четыре уровня ToBI

Транскрипция ToBI сопоставляет аудио и запись F0 с четырьмя уровнями. Beckman, Hirschberg и Shattuck-Hufnagel (2005) перечисляют уровни исходной системы для основного варианта американского английского (MAE_ToBI) так:

  • Тоны. Тональные акценты, фразовые акценты и пограничные тоны, каждый в одной точке времени.
  • Слова. Орфографическая транскрипция с отмеченным во времени концом каждого слова.
  • Индексы границ. Число от 0 до 4, обозначающее степень стыка после каждого слова.
  • Misc. Сбои речи, комментарии и другие события.

В Praat TextGrid тоны и индексы границ обычно лежат на точечных уровнях (TextTier), а слова и misc лежат на интервальных уровнях. Набор меток в конфигурации ниже следует таблицам MAE_ToBI из той же главы:

Тип меткиМетки
Тональные акцентыH*, L*, L+H*, L*+H, H+!H*, а также пониженные (downstep) !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

Схема tiered_annotation в Potato рисует осциллограмму всей записи, увеличенную осциллограмму текущего окна и по одной строке на каждый уровень. На точечном уровне разметчик щелчком ставит точку с активной меткой и перетаскиванием сдвигает точку. Чтобы сменить метку точки, разметчик выделяет точку и нажимает кнопку другой метки, а клавиша 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. Уровень фонов (phones), созданный программой выравнивания, удалите до импорта, потому что конфигурация ниже называет только четыре уровня ToBI. Уровни, где уже есть метки, приходят в Potato как предразметка. Первый проход другого разметчика поэтому поступает как предразметка.

Импорт файлов TextGrid

Команда импорта превращает папку в проект Potato с одним элементом на каждый TextGrid:

bash
potato import -i textgrids -o tobi_project

В нашей тестовой папке было три высказывания, одно уже размеченное и два только со словами. Импортёр вывел следующее:

text
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 становится уровнем одной схемы tiered_annotation с именем tiers, и каждый точечный уровень остаётся точечным. Уровень, где не больше 30 различных значений, получает эти значения в качестве своих меток. В нашей папке уровень тонов получил только пять тонов, использованных в размеченном высказывании, а уровень границ получил 0, 1, 3 и 4. Уровень с большим числом различных значений получает единственную метку, названную по имени уровня, а текст каждого интервала хранит в поле value сегмента. Уровень слов любого реального корпуса относится именно к таким уровням. Каждая импортированная точка и каждый импортированный интервал становятся предразметкой. Каждый разметчик видит импортированные метки как отправную точку, и Potato сохраняет метки, только когда этот разметчик сохранит работу.

Слова над осциллограммой

На каждом интервале уровня слов стоит метка words, а само слово остаётся в поле value. Импортёр записывает в текст каждого элемента имя файла TextGrid. Запустите следующий скрипт в tobi_project, чтобы заменить этот текст словами высказывания по порядку:

python
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. Новая конфигурация сохраняет сгенерированные настройки данных и предразметки и даёт каждому уровню полный набор меток:

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. Экспорт записывает уровни в порядке конфигурации.
  • Фиксированный список misc. Уровни Potato не принимают вводимых вручную меток. Уровень misc поэтому предлагает шесть меток событий, а комментарии в свободной форме остаются в Praat.
  • %r на уровне тонов. MAE_ToBI отмечает перезапуск контура на уровне тонов, а сам сбой речи отмечает на уровне misc.
  • words как единственная метка слов. Метка совпадает с тем, что записал импортёр. Уровень слов поэтому служит для сдвига границ слов, а новый интервал, нарисованный на уровне слов, экспортируется с текстом words.

Валидатор сверяет каждый ключ с собственным списком Potato и вывел OK — no issues found. для этой конфигурации и для конфигурации, которую сгенерировал импортёр:

bash
python -m potato.validate_cli config.yaml --strict

Разметка в браузере

Команда запуска поднимает задачу на порту 8000:

bash
potato start config.yaml -p 8000

Каждый разметчик входит в систему, видит слова над осциллограммой и выбирает уровень в меню уровней, прежде чем ставить точки. В одном из рабочих порядков индексы границ сначала ставятся в конце каждого слова. Затем идут тональные акценты, а краевые тоны ставятся последними при каждом индексе границы 3 или 4. Если каждое высказывание должны разметить два разметчика для оценки согласованности, задайте в конфигурации num_annotators_per_item: 2.

Экспорт обратно в Praat

Команда экспорта записывает по одному TextGrid на каждого разметчика и каждое сохранённое высказывание:

bash
python -m potato.export -c config.yaml -f textgrid -o textgrid_out

В нашем тесте первое высказывание сохранили два смоделированных разметчика, и экспорт записал эти файлы:

text
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 нашёл уровни tones и breaks как точечные, десять слов и вдох (breath) на уровне misc. Файл второго разметчика отличался от исходного TextGrid только одним тоном, который разметчик сдвинул с 0,35 на 0,36 секунды, и записью 0 в виде 0.0.

Что из TextGrid сохраняется и что теряется при полном цикле

Полный цикл через Potato сохраняет следующие части TextGrid:

  • Уровни. Имена уровней и их тип (точечный или интервальный) возвращаются в том виде, в каком были импортированы, а порядок уровней совпадает, если конфигурация сохраняет исходный порядок.
  • Время. Potato хранит время точек и границы интервалов в миллисекундах с тремя знаками после запятой. Каждое значение времени поэтому сохраняет точность до микросекунды.
  • Метки. Метки тонов, метки границ и текст каждого интервала слов возвращаются, а кавычка внутри метки удваивается так, как её записывает Praat.
  • Длина сетки. Сетка заканчивается на длине аудио, которую измерила страница разметки, или на xmax исходного файла.

Полный цикл теряет следующие части:

  • Время начала. Экспорт начинает сетку и каждый уровень с 0, каким бы ни было xmin исходного файла.
  • Несохранённые высказывания. Высказывание, которое никто не сохранил, вообще не получает 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 нет согласованности меток тонов с допуском по времени, нет согласованности по отдельным уровням и нет каппы или порядковой статистики для индексов границ. Перебор допусков на странице Согласованность во времени относится к точкам разрыва в эпизодах роботов и не охватывает tiered_annotation. Для показателей надёжности ToBI экспортируйте TextGrid обоих разметчиков и сопоставьте тоны двух разметчиков в окне, которое выберете сами, в Praat или в собственном скрипте.

Тестовый прогон, на котором основана эта страница

Файлы TextGrid и WAV на этой странице записал скрипт, и WAV-файлы содержат синтетический тон, а не речь. Скрипт рассчитал время каждого слова по длине слова, а время тонов и границ мы выбрали вручную. Импорт, валидатор, сервер и экспорт работали в Potato 2.13.1. Два смоделированных разметчика сохраняли работу тем же запросом /updateinstance, который отправляет страница разметки. Показатели согласованности получены запуском функции, стоящей за /admin/iaa, на двух сохранённых ответах.

Что читать дальше

Литература

  1. 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
  2. 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