ToBI Prosody Labeling with Praat TextGrid Round Trips
Label ToBI tones and break indices as point tiers in Potato 2.13.1, starting from your Praat TextGrids and exporting TextGrids that Praat reads back.
Phoneticians and prosody researchers with recordings and Praat TextGrids can follow this tutorial to run ToBI labeling in Potato 2.13.1 and get the labels back as TextGrids. ToBI (Tones and Break Indices) is a set of conventions for transcribing intonation and prosodic phrasing. Silverman et al. (1992) introduced ToBI for American English. The task on this page shows the recording's waveform with four tiers below the waveform. The tones tier and the break-index tier hold time points, the words tier holds intervals, and the misc tier marks disfluencies and noise. Point tiers arrived in Potato 2.13.1, and the importer and the textgrid exporter both read and write Praat point tiers. Several transcribers can label the same utterances on one server, and each transcriber's work exports as a separate TextGrid.
The four ToBI tiers
A ToBI transcription pairs the audio and an F0 record with four tiers. Beckman, Hirschberg, and Shattuck-Hufnagel (2005) list the tiers of the original Mainstream American English system (MAE_ToBI) as follows:
- Tones. Pitch accents, phrase accents, and boundary tones, each at one time point.
- Words. An orthographic transcription, with each word's end marked in time.
- Break indices. A number from 0 to 4 for the degree of juncture after each word.
- Misc. Disfluencies, comments, and other events.
In a Praat TextGrid, the tones and break indices are usually point tiers (TextTier), and the words and misc are interval tiers. The label inventory in the config below follows the MAE_ToBI tables in the same chapter:
| Label type | Labels |
|---|---|
| Pitch accents | H*, L*, L+H*, L*+H, H+!H*, and the downstepped !H*, L+!H*, L*+!H |
| Phrase accents | L-, H-, !H- (at every break index 3 or 4) |
| Boundary tones | L%, H% (at every break index 4), and the marginal initial %H |
| Uncertainty | *?, -?, %? for whether a tone occurred, and X*?, X-?, X%? for which tone |
| Break indices | 0, 1, 2, 3, 4, with - for uncertainty (3-, 4-) and p for hesitation (1p, 2p, 3p) |
The tiered view and the missing F0 track
Potato's tiered_annotation scheme draws the waveform of the whole recording, a zoomed waveform of the current window, and one row per tier. On a point tier, the transcriber clicks to place a point with the active label and drags to move a point. The transcriber relabels a point by selecting the point and clicking a different label button, and presses Delete to remove a selected point. On an interval tier, the transcriber clicks and drags.
Potato 2.13.1 has no F0 track or spectrogram in the tiered view. Transcribers judge pitch accents against the F0 contour. Keep Praat open on the same WAV file for the pitch track. Each tier also offers only the labels the config lists, with no box for typing a label. The words therefore come from the TextGrids rather than from the transcriber.
Preparing the TextGrids
Put one TextGrid and one WAV file per utterance in a folder, with matching names such as utt01.TextGrid and utt01.wav. Name the tiers tones, words, breaks, and misc, with tones and breaks as point tiers. A forced aligner can produce the words tier, and the Montreal Forced Aligner writes long-format TextGrids by default. Add the three missing tiers to an aligner's output in Praat with the Insert point tier and Insert interval tier commands. Remove an aligner's phones tier before importing because the config below names only the four ToBI tiers. Tiers that already hold labels come into Potato as pre-annotations. A first pass by another transcriber therefore arrives as pre-annotations.
Importing the TextGrids
The import command turns the folder into a Potato project with one item per TextGrid:
potato import -i textgrids -o tobi_projectOur test folder held three utterances, one already labeled and two with words only. The importer reported the following:
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.mdEach TextGrid tier becomes a tier of one tiered_annotation scheme named tiers, and each point tier stays a point tier. A tier with at most 30 distinct values gets the values as the tier's labels. In our folder, the tones tier received only the five tones the labeled utterance used, and the breaks tier received 0, 1, 3, and 4. A tier with more distinct values gets a single label named after the tier and keeps each interval's text in the segment's value field. The words tier of any real corpus is such a tier. Every imported point and interval is a pre-annotation. Each transcriber sees the imported labels as a starting point, and Potato stores the labels only when that transcriber saves.
Showing the words above the waveform
The words tier shows the label words on every interval, and the word itself stays in the value field. The importer sets each item's text to the TextGrid's file name. Run the following script in tobi_project to replace that text with the utterance's words in order:
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 then shows "Marianna made the marmalade before the guests arrived at noon" above the tiers for the first utterance.
The config
The config below replaces the generated config.yaml. The new config keeps the generated data and pre-annotation settings and gives each tier the full label inventory:
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]The config makes the following choices:
- Full label lists. The importer lists only the labels found in the files, and a transcriber cannot place a tone missing from the config.
- Combined edge tones. MAE_ToBI gives the phrase accent and boundary tone at a break index 4 the time of that break. One point labeled L-L% therefore marks the phrase accent and the boundary tone together. Bare L% and H% are left out for the same reason.
- Tier names and order. The pre-annotations land on the right rows when the names match the TextGrid tiers. The export writes tiers in config order.
- A fixed misc list. Potato tiers take no typed labels. The misc tier therefore offers six event labels, and free-text comments stay in Praat.
%ron the tones tier. MAE_ToBI marks a contour restart on the tones tier and the disfluency itself on the misc tier.wordsas the only words label. The label matches what the importer wrote. The words tier is therefore for moving word boundaries, and a new interval drawn on the words tier exports with the textwords.
The validator checks every key against Potato's own list and printed OK — no issues found. for this config and for the config the importer generated:
python -m potato.validate_cli config.yaml --strictLabeling in the browser
The start command serves the task on port 8000:
potato start config.yaml -p 8000Each transcriber signs in, sees the words above the waveform, and picks a tier from the tier menu before placing points. One workable order is to place break indices at each word end first. Pitch accents come next, and the edge tones go last at each break index 3 or 4. Set num_annotators_per_item: 2 in the config if every utterance should get two transcribers for agreement.
Exporting back to Praat
The export command writes one TextGrid per transcriber per saved utterance:
python -m potato.export -c config.yaml -f textgrid -o textgrid_outTwo simulated transcribers saved the first utterance in our test, and the export wrote these files:
Files written:
textgrid_out/utt01_annotator1_tiers.TextGrid
textgrid_out/utt01_annotator2_tiers.TextGridA project with one transcriber gets file names without the user name, such as utt01_tiers.TextGrid. Praat 6.1.38 read both files through Parselmouth 0.4.6. Praat found the tones and breaks as point tiers, the ten words, and a breath on the misc tier. The second transcriber's file differed from the source TextGrid only in the one tone the transcriber had moved from 0.35 to 0.36 seconds and in writing 0 as 0.0.
TextGrid fields a round trip keeps and loses
A round trip through Potato keeps these parts of a TextGrid:
- Tiers. Tier names and point or interval types come back as imported, and the tier order matches when the config keeps the source order.
- Times. Potato stores point times and interval boundaries in milliseconds to three decimals. Every time therefore keeps microsecond precision.
- Labels. Tone labels, break labels, and the text of every word interval come back, and a quotation mark inside a label is doubled as Praat writes one.
- Grid length. The grid ends at the audio length that the annotation page measured, or at the source's
xmax.
A round trip loses these parts:
- Start times. The export starts the grid and every tier at 0, whatever the source's
xminwas. - Unsaved utterances. An utterance no one saved gets no TextGrid at all.
- File names. The export names files
<item>_<scheme>.TextGrid, or<item>_<user>_<scheme>.TextGridwith several transcribers. - Encoding. Praat often saves UTF-16, and the export writes UTF-8. Praat reads both encodings.
- Overlaps. Praat refuses overlapping intervals on one tier, and the export lists each overlap as a warning.
Agreement between two transcribers
Potato's agreement report at /admin/iaa gives one mean agreement per tiered_annotation scheme and pools the four tiers together. Potato matches the two transcribers' points and intervals by temporal overlap, and a matched pair with different labels earns half credit. Two points match only at exactly the same time. In our test, two answers for the first utterance that differed only in one tone placed 10 milliseconds apart scored 0.93 instead of 1.0. Two answers with every tone and break 1 millisecond apart scored 0.24 because only the ten word intervals still matched.
Potato 2.13.1 computes no tone-label agreement with a time tolerance, no per-tier agreement, and no kappa or ordinal statistic for break indices. The tolerance sweep on Agreement over Time belongs to robot-episode break-points and does not cover tiered_annotation. For ToBI reliability figures, export both transcribers' TextGrids and pair the two transcribers' tones within a window of your choosing in Praat or a script of your own.
The test run behind this page
A script wrote the TextGrids and WAV files on this page, and the WAV files hold a synthetic tone rather than speech. The script timed each word by its length, and we chose the tone and break times by hand. Potato 2.13.1 ran the import, the validator, the server, and the export. Two simulated transcribers saved through the same /updateinstance request the annotation page sends. The agreement figures come from running the function behind /admin/iaa on the two saved answers.
Where to go next
- Importing Projects, for every option of the TextGrid and ELAN importers
- Linguistic annotation tools compared, for Praat, ELAN, FLEx, and EMU-SDMS beside Potato, and for checking forced-aligned phone boundaries
- Agreement over Time, for how Potato matches segments in time
- Linguistics in Potato, for glossing, tier correction, and dialect tasks in one place
References
- 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