# Potato 2.7.1: The Transcript Already Exists

Source: https://www.potatoannotator.com/blog/potato-2-7-1-transcripts

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 out](/images/blog/potato-2-7-1-banner.svg "Potato 2.7.1")

## 21 formats in, one model out

Up from 6. The full list is on the [Transcript Formats](/docs/annotation-types/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 question](/images/docs/transcript-speaker-bubbles.png "Whatever 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:

```
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](/docs/features/think-aloud), 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

- [Transcript Formats](/docs/annotation-types/transcript-formats) — every format with its detection rule, the normalized turn model, sidecar rules, config keys, and troubleshooting keyed to real symptoms
- [How to Annotate Whisper Transcripts](/docs/guides/annotating-whisper-transcripts) — which output file to keep, and why diarization is a separate decision
- [How to Annotate YouTube Subtitles](/docs/guides/annotating-youtube-subtitles) — `yt-dlp`, and what auto-captions will and will not support
- [Transcript Format Ingestion](/showcase/transcript-formats) — a runnable design with six formats side by side

## 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.
