---
**Article**: [Working with Timestamps, Utterances, and Speaker Diarization in Deepgram](/content/learn/article/index.html)
**Author**: Stephen Oladele  
**Date**: Sep 22, 2025  
**Read Time**: 15 min

## 🎥 Video Overview

## ⏩ TL;DR
- STT is the baseline; the value is in the metadata. Deepgram returns timestamped transcripts with utterances and speaker diarization so you can answer *who said what, when*—reliably.
- Turn `utterances=true`, `diarize=true`, and `smart_format=true` on Deepgram’s STT API to get structured, context-aware results out of the box.
- With this, you can power search, segmentation, QA checks, and analytics (talk time, interruptions, and silence).

## **Introduction**
Speech-to-text (STT) isn’t just about words—it’s about **context**. In real conversations, *who* spoke, *when* they spoke, and *how long* they spoke often matter as much as *what* they said. A flat, speakerless transcript throws away that structure.

Deepgram’s [speaker diarization STT](/content/product/speech-to-text/index.html) and utterance segmentation give you timestamped transcripts that preserve conversational context:
- **Utterances**: semantically coherent segments with start/end times.
- **Speaker labels**: identify who spoke in each segment.
- **Word-level timing** (optional): fine-grained alignment when you need it.

In this guide, you’ll:
1. Call Deepgram with utterances, diarize, and smart_format enabled.
2. Understand the response (words → utterances → speakers).
3. Normalize it into a “turns” data model you can store, index, and analyze.

## **Speech Is Made of Contextual Segments—Text Should Be Too!**
Human speech isn’t a neat paragraph; it comes in [segments](https://onlinelibrary.wiley.com/doi/10.1155/2022/7994191) like questions, answers, interjections, and hand-offs. To keep that structure, your transcript needs three things:
- **Utterances**: coherent segments of speech with a single intent.
- **Timestamps**: start/end times for each segment (and words) so you can align UI, video, or actions.

## **How Deepgram exposes this (out of the box)**:
- Enable [utterances=true](https://developers.deepgram.com/docs/utterances) to receive `results.utterances[]` with `{start, end, transcript, confidence, words[]}`.
- Enable [diarize=true](https://developers.deepgram.com/docs/diarization) to add speaker labels per utterance (and per word).
- Enable [smart_format=true](https://developers.deepgram.com/docs/smart-format) for readable punctuation/casing and normalized entities (numbers, dates, etc.).

## **Working with Utterances, Timestamps, and Diarization in Deepgram**
With Nova-2 and Nova-3, Deepgram can return timestamped transcripts complete with utterances and speaker diarization STT—all in one call. To enable these features, all you need to do is pass the corresponding parameters in your API request.

### Example Curl Command:
```bash
curl \
  -X POST \
  -H "Authorization: Token YOUR_DEEPGRAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"}' \
  "https://api.deepgram.com/v1/listen?model=nova-3&language=en&utterances=true&diarize=true&smart_format=true"
```

### Example JSON Response:
```json
{
  "start": 10.0713,
  "end": 11.6713,
  "confidence": 0.9994,
  "channel": 0,
  "transcript": "Life moves pretty fast.",
  "words": [
    {"word":"Life","start":10.0713,"end":10.3113,"confidence":0.9990,"speaker":0},
    {"word":"moves","start":10.3113,"end":10.6313,"confidence":0.9997,"speaker":0}
  ],
  "speaker": 0,
  "id": "35404fd9-12ed-4b58-a9a9-9eaf93475ef6"
}
```

## **Python SDK (prerecorded)**
```python
from deepgram import DeepgramClient, PrerecordedOptions

dg = DeepgramClient("YOUR_SECRET")

AUDIO_URL = {"url": "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"}

opts = PrerecordedOptions(
    model="nova-3",
    language="en",
    smart_format=True,
    utterances=True,
    diarize=True,
)

res = dg.listen.prerecorded.v("1").transcribe_url(AUDIO_URL, opts)

print(res.to_json(indent=2))
```

## **Adding Captions to Audio with Deepgram**
Deepgram’s timestamped transcripts (with `utterances=true` and optional `diarize=true`) map cleanly to standard caption formats: SRT and WebVTT.

| Format | Time syntax           | Speaker tags                  | Best for                       |
|--------|-----------------------|-------------------------------|--------------------------------| 
| SRT    | HH:MM:SS,mmm          | Not standard                  | Offline editors, legacy players | 
| WebVTT | HH:MM:SS.mmm          | <v Speaker N> native          | HTML5 <track> & styling via ::cue |

### Option A: Use the Caption Helpers
```python
from deepgram import DeepgramClient, PrerecordedOptions
from deepgram_captions import DeepgramConverter, webvtt, srt

dg = DeepgramClient()  # reads DEEPGRAM_API_KEY from env
with open("PATH_TO_YOUR_FILE", "rb") as f:
    payload = f.read()

opts = PrerecordedOptions(
    model="nova-3",
    language="en",
    smart_format=True,
    utterances=True,
    diarize=True,
)

res = dg.listen.rest.v("1").transcribe_file(payload, opts)
dg_tx = DeepgramConverter(res.to_dict())  # convert SDK object to plain dict

# Write WebVTT
with open("output.vtt", "w", encoding="utf-8") as out:
    out.write(webvtt(dg_tx))

# Write SRT
with open("output.srt", "w", encoding="utf-8") as out:
    out.write(srt(dg_tx))
```

### Production Pointers
- **Line length and duration:** keep cues ≤ 42 chars and ≤ 6 s. Split long utterances if needed.
- **Overlap:** if back-channels overlap, shift them ±100 ms or merge.
- **Async transcription:** use `transcribe_file_async + webhook` for large batches.

## **Conclusion: Transcription Is Just the Beginning**
Treating speech as **structured data**—not just words—unlocks real product value. With Deepgram, you get **timestamped transcripts**, **utterances**, and **speaker diarization**, enabling you to answer *who said what, and when*.
