How to make captions, a transcript and chapters for a podcast or YouTube video

You only need to transcribe the episode once with word timestamps. From that single result, you can build an SRT caption file, a transcript for the show notes, translated captions, and chapter timestamps. The API needs a link to a media file or an uploaded file. Since a YouTube watch page is a web page, pass in your own exported audio or video instead.

Get an API key Quickstart Supported languages

Last updated: · Markdown

Transcribe once

Export your episode as an audio file (MP3 or M4A) or video file. Upload it using the helper from the video editing guide and ask for JSON output:

{
  "audio_url": "https://example.com/interview.mp3",
  "model": "oracle",
  "language": "auto",
  "word_timestamps": true,
  "output_format": "json"
}

If you're transcribing an interview or a panel, set include_diarization: true so you can see who is speaking.

Captions as an SRT file

Turn the words into cues and upload the .srt to YouTube Studio or your podcast host. See the SRT guide for the code and the API's own SRT output, which puts one word per cue.

Translated captions

To get translated captions, you can either run the first transcript through your LLM, or send a second job on the same file using an Oracle model with translate_to and output_format: "srt". Running a separate job for each language keeps the translated subtitles lined up with the audio.

A transcript for the show notes

If you just want plain text, pass output_format: "txt", or stitch the text fields from your JSON segments together with the speaker labels. Give it a read-through before you publish, since automated transcripts often slip up on people's names, product names, and numbers.

Chapters with timestamps

Feed the numbered segments to your LLM and ask it to pick the segment numbers where new chapters start. Don't ask the LLM to write the timestamps directly. Instead, look up the start times for those segment numbers in your code. You can use this prompt with any model:

Below is a podcast transcript, one line per segment: S<number> [start-end] text.
Pick 5 to 9 chapter starts. For each give the segment number and a title of at most six words.
Return JSON: [{"segment": 0, "title": "Intro"}]. The first chapter must be segment 0.

chapters.py

# chapters.py — YouTube chapter lines from (seconds, title) pairs
def stamp(seconds):
    m, s = divmod(int(seconds), 60)
    h, m = divmod(m, 60)
    return f"{h}:{m:02}:{s:02}" if h else f"{m}:{s:02}"


def chapter_lines(chapters):
    return "\n".join(f"{stamp(start)} {title}" for start, title in chapters)


print(chapter_lines([(0, "Intro"), (95, "Why captions matter"), (412, "Editing from a transcript")]))

If you paste a list of timestamps into your video description, YouTube automatically turns them into chapters. For it to work, the first timestamp has to be 0:00, you need at least three timestamps in order, and each chapter must run for at least ten seconds.

Pricing

JobModelCost
One-hour episode, clear audiobaseUS$0.48
One-hour episode, production quality with speakersoracleUS$1.44
Translated captions, one houroracle_miniUS$0.96

Billed by the second with no minimum. Full rates: /llms/pricing.md.

Questions and answers

How do I get a transcript of a podcast episode?

Pass the audio file or its URL to POST /transcribe. Use output_format: "txt" if you want plain text, or json if you need timings and speakers.

Can I use a YouTube link?

No. A YouTube watch URL is a web page, and the API needs either an uploaded file or a direct link to a media file. Make sure you only use audio or video that you own or have permission to use.

How do I add captions to YouTube?

Follow the SRT guide to build an SRT file, then upload it under the video's subtitles tab in YouTube Studio.

How do I create chapters?

Give your LLM the numbered transcript and have it return the segment numbers where chapters should start. Use your code to pull the timestamps for those segments, then paste the list into your video description.

Can I get captions in several languages?

Yes. Run a separate job for each language using an Oracle model and the translate_to parameter.