Skip to content
Announcements6 min read

Potato 2.7.1: The Transcript Already Exists

Potato 2.7.1 reads 21 transcript and subtitle formats directly, loads them from sidecar files next to your media, and ships a converter that turns a folder of ASR output into an annotation-ready data file.

Potato Team

Almost nobody comes to an annotation tool with raw audio and nothing else. They come with a transcript. Somebody ran Whisper over a folder of interviews. Somebody pulled captions off a hundred conference talks. Somebody inherited a corpus of TextGrids from a fieldwork project that ended in 2019.

And then the tool asks them to write a conversion script.

Potato 2.7.1 is about removing that step. It reads 21 transcript and subtitle formats directly, loads them from files sitting next to your media rather than requiring everything to be pasted into a data file, and includes a converter for the case where you do want one data file at the end.

Potato 2.7.1: 21 transcript formats in, one turn model outPotato 2.7.1

21 formats in, one model out

Up from 6. The full list is on the Transcript Formats page, but roughly: nine kinds of ASR output (Whisper JSON, WhisperX and other diarized JSON, whisper.cpp, Whisper TSV, AWS Transcribe, Deepgram, AssemblyAI, Rev.ai, SPoRC), six subtitle and caption formats (SubRip, WebVTT, SubStation Alpha, TTML and DFXP, YouTube json3, YouTube srv1/srv2/srv3), three from the forced-alignment world (NIST CTM, Praat TextGrid, ELAN EAF), and three generic shapes for data that came from somewhere else entirely.

The alignment formats are the addition we are happiest about. Export to EAF and TextGrid already existed, so tiered annotations now round-trip: bring an existing alignment in, correct it in Potato, send it back to ELAN or Praat.

Detection works off the shape of the data rather than the file extension, which means a WebVTT file named captions.txt still parses as WebVTT, and it means the same transcript works inlined or read from disk without a config change.

Word-level timings and per-segment confidence are preserved where the source provides them. Formats that are natively word-level, like CTM, Deepgram, and AssemblyAI, get grouped into turns on speaker change plus a pause threshold.

A transcript rendered as colored speaker bubbles with per-turn play buttons and an inline label questionWhatever format went in, this is what comes out

Sidecar files

Your ASR tool already wrote the files in a sensible layout: media here, transcript next to it. There was no good reason to make you flatten that into a data blob, so now you can point at it:

json
{"id": "int_001", "conversation": {"audio": "media/int_001.mp3",
                                   "transcript": "media/int_001.srt"}}

Paths resolve relative to task_dir and go through the same directory-traversal validation as every other configured path. If your data genuinely holds one-line inline transcripts that happen to look like filenames, transcript_is_path: false turns the heuristic off.

The practical benefit is that your transcripts stay files. You can diff them, regenerate them, and hand them to someone else, instead of having a copy fossilized inside a JSON array.

A converter for the other case

Sometimes you do want one data file. potato transcripts globs a folder, pairs each transcript to its media by basename, derives item ids from filenames, and writes the result:

bash
potato transcripts ./whisper_out --media-dir ./audio -o data/interviews.json

--dry-run writes nothing and tells you what it found, which is also the first thing to run when a transcript renders as one undifferentiated block:

text
Scanned 3 file(s):
  interview_01.json      Whisper JSON      42 turns    891.4s  undiarized
  interview_02.json      WhisperX JSON     51 turns   1120.8s  2 speaker(s): SPEAKER_00, SPEAKER_01
  interview_03.json      Whisper JSON      38 turns    754.2s  undiarized

3 item(s), 131 turn(s).

A file reporting plain text is almost always a Whisper .txt that got mixed in with the .json output. The .txt has no timings at all, and you cannot recover them without re-running the model. That single fact accounts for most of the "why does my transcript look wrong" reports we see.

--emit-config prints a matching config.yaml alongside the data file.

One vocabulary across four schemas

audio_dialogue, speech_transcript, voice_interaction, and tiered_annotation each used to parse transcript data their own way and accept different subsets of formats, for no reason anyone could articulate. They now share one normalizer, so whatever one accepts, all four accept.

Existing configs are unaffected. Each schema keeps its old parsing as a fallback, and every transcript shape that worked before still works byte for byte.

tiered_annotation also gains opt-in transcript seeding. Point transcript_field at your transcript and a tier arrives pre-populated, so annotators correct an existing alignment instead of re-segmenting speech from scratch:

yaml
  - annotation_type: tiered_annotation
    name: tiers
    source_field: audio_url
    media_type: audio
    transcript_field: asr_output   # opt-in; omit to start from a blank timeline
    transcript_tier: utterance
    tiers:
      - name: utterance
        labels:
          - name: speech
            color: "#7c3aed"

Seeded intervals are not saved until an annotator actually edits them, so an untouched seed never gets misattributed as human work.

What Potato still does not do

It does not transcribe, and it does not diarize. ASR runs upstream. Potato reads what your pipeline produced.

This comes up because Potato does run a local Whisper model, for Think-Aloud Mode, which records annotators talking while they work. That is a capture feature aimed at your annotators, not at your corpus. Different thing, same word.

Word-level confidence is parsed and kept in the data model where the source provides it, but there is no interface for viewing it yet.

And some formats have no parser at all: SAMI, MicroDVD, SubViewer, Transcriber .trs, EXMARaLDA, CHAT/CHILDES, standalone RTTM, and native Montreal Forced Aligner or Gentle output. Convert those first. We publish that list because a supported-format list with nothing excluded from it is not worth much.

Documentation

Upgrading

bash
pip install --upgrade potato-annotation==2.7.1

You do not need to change any configuration. Every transcript shape Potato accepted before, it still accepts.