Output formats & subtitles
Set output_type to choose what the server returns: structured JSON, plain text, subtitle files, or formatted documents. The default is json. The server does the formatting. The SDK writes a file only when you call save().
The six formats
output_type | What you get | Use it when |
|---|---|---|
json (default) | Structured document with per-word timings and speakers. The SDK parses it into .text, .words, .utterances. | You're writing code against the result. |
txt | Plain transcript text, no timing or structure. | You just need the words. |
srt | SubRip subtitles: numbered cues with start and end times. | Captions for most video players and editors. |
vtt | WebVTT subtitles. | Web video (<track>) and HTML5 players. |
docx | Formatted Word document. | Shareable transcripts for non-technical readers. |
pdf | Formatted PDF document. | Fixed-layout, print-ready transcripts. |
Every SDK accepts output_type: as a keyword argument in Python, an option field in JavaScript, and the OutputType enum in Go (stt.OutputSRT) and C# (OutputType.Srt).
The JSON schema
The default json output is a document built around a words array. Each word has the token plus optional start, end, speaker, confidence, and language fields. With diarization on, the document may also include diarization segments. When the audio switches languages, it may also include a languages array. The SDK reads this into a transcript object: it derives .text, groups words into .utterances, and keeps the original in .raw.
{
"words": [
{ "word": "Hi", "start": 0.50, "end": 0.68, "speaker": "SPEAKER_1", "language": "en" },
{ "word": "there", "start": 0.68, "end": 0.94, "speaker": "SPEAKER_1", "language": "en" }
],
"diarization": [
{ "speaker": "SPEAKER_1", "start": 0.50, "end": 0.94 }
],
"languages": [
{ "language": "en", "start": 0.50, "end": 0.94 }
]
}Use result.to_dict() for a provider-neutral dict:
{
"id": "d1f2...-job-id",
"status": "completed",
"text": "Hi there ...",
"words": [
{ "word": "Hi", "text": "Hi", "start": 0.5, "end": 0.68, "speaker": "SPEAKER_1", "language": "en" }
],
"utterances": [
{ "text": "Hi there", "transcript": "Hi there", "speaker": "SPEAKER_1",
"start": 0.5, "end": 0.94, "words": [ ... ] }
],
"languages": [
{ "start": 0.5, "end": 0.94, "language": "en" }
],
"output_type": "json"
}For migrations, result.to_deepgram() returns the same data in Deepgram's pre-recorded response shape, with the text at results.channels[0].alternatives[0].transcript. See the Python SDK result-shape table for the full member list.
Subtitles: SRT & VTT
Request srt or vtt and the server returns a formatted subtitle file. For these outputs, result.text is the decoded file contents and result.save() writes it to disk, adding the extension for the output type when your path has none.
srt = client.transcribe("meeting.mp3", output_type="srt")
print(srt.text) # the decoded .srt contents
srt.save("meeting") # -> meeting.srt
vtt = client.transcribe("meeting.mp3", output_type="vtt")
vtt.save("meeting") # -> meeting.vttHow cues are built
Each cue is a run of consecutive words from one speaker, shown as at most two lines of up to 42 characters. A new cue starts when:
- the speaker changes (a cue never spans two speakers);
- the next word would need a third line, or would take the cue past 7 seconds;
- there is a pause of more than 1 second before the next word;
- a sentence ends (
.?!) and the cue has already run for at least 1 second.
A cue runs from its first word's start to its last word's end. With speaker labels on (the default), the cue's first line starts with the speaker, for example SPEAKER_1: . Turn speaker_labels off for captions without speaker names. SRT times are HH:MM:SS,mmm; VTT times are HH:MM:SS.mmm, after a WEBVTT header.
5
00:00:11,599 --> 00:00:15,820
SPEAKER_1: It is very select and they are not giving
many invitations to clerks.
6
00:00:16,769 --> 00:00:18,769
SPEAKER_1: The whole official world will be there.
7
00:00:19,629 --> 00:00:25,399
SPEAKER_2: She looked at him with an irritated glance
and said impatiently, And what do you wish
8
00:00:25,460 --> 00:00:26,600
SPEAKER_2: me to put on my back?WEBVTT
00:00:11.599 --> 00:00:15.820
SPEAKER_1: It is very select and they are not giving
many invitations to clerks.
00:00:16.769 --> 00:00:18.769
SPEAKER_1: The whole official world will be there.
00:00:19.629 --> 00:00:25.399
SPEAKER_2: She looked at him with an irritated glance
and said impatiently, And what do you wish
00:00:25.460 --> 00:00:26.600
SPEAKER_2: me to put on my back?Both are cue lists with timings. Use srt for desktop video editors and most players; use vtt for the web, where the HTML5 <track> element expects WebVTT.
Documents: DOCX & PDF
docx and pdf return a formatted document as raw bytes. Save them to disk or stream them to your user; don't decode them as text. docx is editable; pdf is fixed-layout and print-ready.
docx = client.transcribe("meeting.mp3", output_type="docx")
docx.save("meeting") # -> meeting.docx
pdf = client.transcribe("meeting.mp3", output_type="pdf")
# .content is the raw bytes if you'd rather stream than save
with open("meeting.pdf", "wb") as f:
f.write(pdf.content)When you submit and poll, ask for the format at retrieval time. Python get_transcript(job_id, output_type="srt"), Go GetTranscript(id, stt.OutputSRT). Submit with json to keep the richest data; you can render subtitles or documents from it later.
Choosing a format
- Building software:
json. It is the only format with structured timestamps and speaker data you can iterate. - Captioning video:
srtorvtt, formatted by the server. - Sharing with people:
docx(editable) orpdf(print-ready). - Just the words:
txt.
The cookbook has short subtitle recipes. Timestamps and diarization cover the structured data behind the json output.