Skip to content
Showcase/Transcript Format Ingestion
intermediateaudio

Transcript Format Ingestion

Six transcript formats rendered as the same speaker bubbles, with per-turn labels and spans that work regardless of where the transcript came from.

Transcript Format Ingestion annotation interface preview

Configuration Fileconfig.yaml

yaml
annotation_task_name: "Transcript Formats"
task_dir: "."
port: 8000

# Six instances, six different transcript formats. All of them render as the
# same speaker bubbles, because Potato normalizes every supported format to one
# turn model before display.
#
# Here the transcripts are inlined into the data file. They can equally be paths
# to sidecar files next to the media, which is usually what your ASR tool
# already produced:
#
#     "conversation": {"audio": "media/talk_01.mp3",
#                      "transcript": "media/talk_01.srt"}
#
# To build a data file from a folder of ASR output instead:
#
#     potato transcripts ./whisper_out --media-dir ./audio -o data/items.json
#     potato transcripts ./whisper_out --dry-run     # what did it detect?

data_files:
  - data/sample-data.json

item_properties:
  id_key: id
  text_key: title

instance_display:
  layout:
    direction: vertical
    gap: 16px
  fields:
    - key: title
      type: text
      label: "Format"

    - key: source_format
      type: text
      label: "Where this came from"

    - key: conversation
      type: audio_dialogue
      label: "Transcript"
      span_target: true
      display_options:
        audio_key: audio
        scroll_height: 420px
        show_timestamps: true
        # "auto" reads the field as a sidecar path when it looks like one.
        # These transcripts are inlined, so nothing is read from disk.
        transcript_is_path: auto
        # No fixed roster: these files use different speaker conventions
        # (Host/Guest, Interviewer/Participant, speaker_0/speaker_1, tier
        # names), so speakers get deterministic colors and alternating sides.
        allow_speaker_assignment: auto

annotation_schemes:
  # Whether the transcript survived ingestion intact, which is the judgment you
  # actually want a human to make before trusting a corpus.
  - annotation_type: radio
    name: ingestion_quality
    description: "Did this transcript come through correctly?"
    labels:
      - name: "clean"
        tooltip: "Timings, speakers, and text all look right"
      - name: "timing_off"
        tooltip: "Turns are misaligned with the audio"
      - name: "speakers_wrong"
        tooltip: "Turns are attributed to the wrong speaker, or not attributed"
      - name: "text_garbled"
        tooltip: "Text is missing, truncated, or mangled"

  # Per-turn labeling, bound to every turn of the conversation field.
  - annotation_type: radio
    name: turn_type
    description: "What is this turn doing?"
    labels:
      - question
      - answer
      - aside
    turn_level: true
    turn_binding:
      field: conversation

  # Spans work over normalized turns regardless of the source format.
  - annotation_type: span
    name: highlights
    description: "Highlight anything an annotator would need to check against the audio"
    target_field: conversation
    labels:
      - name: unclear
        key_value: "u"
      - name: likely_asr_error
        key_value: "e"

output_annotation_dir: "annotation_output/"
output_annotation_format: "json"

Sample Datasample-data.json

json
[
  {
    "id": "talk_01",
    "title": "SubRip (.srt)",
    "source_format": "Exported from a captioning tool. Speakers come from the \"Host:\" / \"Guest:\" prefix on each cue.",
    "conversation": {
      "audio": "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
      "transcript": "1\n00:00:00,000 --> 00:00:06,500\nHost: Welcome back. Today we're talking about what happens to a transcript before anyone annotates it.\n\n2\n00:00:06,500 --> 00:00:12,000\nHost: You've argued that most of the errors people blame on annotators actually start upstream.\n\n3\n00:00:12,000 --> 00:00:21,400\nGuest: Right. If the diarization is wrong, every downstream label inherits that mistake, and nobody notices until analysis.\n\n4\n00:00:21,400 --> 00:00:28,900\nHost: So what would you check first, before recruiting a single annotator?\n"
    }
  },
  {
    "id": "talk_02",
    "title": "WebVTT (.vtt)",
    "source_format": "WebVTT. Speakers come from the <v Name> voice tags, the format's own way of marking who is talking.",
    "conversation": {
      "audio": "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3",
      "transcript": "WEBVTT\n\nNOTE\nExported from a captioning tool. Voice tags carry the speaker.\n\n1\n00:00:00.000 --> 00:00:07.200\n<v Interviewer>Can you describe what a normal week looked like before the change?\n\n2\n00:00:07.200 --> 00:00:16.800\n<v Participant>It was mostly reactive. You'd come in, see what broke overnight, and spend the day on that.\n\n3\n00:00:16.800 --> 00:00:24.000\n<v Interviewer>And afterwards?\n\n4\n00:00:24.000 --> 00:00:33.500\n<v Participant>Afterwards there was a plan. Not a good one at first, but the difference was having one at all.\n"
    }
  }
]

// ... and 4 more items

Get This Design

This design is available in our showcase. Copy the configuration below to get started.

Quick start:

# Create your project folder
mkdir transcript-formats
cd transcript-formats
# Copy config.yaml from above
potato start config.yaml

Details

Annotation Types

radiospan

Domain

AudioSpeech

Use Cases

transcript annotationASR ingestionspeaker diarizationsubtitle annotation

Tags

audiotranscriptwhispersubtitlessrtwebvttdeepgramtextgrid