YouTube chapter generator: timestamps from a transcript

A YouTube chapter generator turns a transcript into timestamps and titles from 00:00: sentence timings from speech-to-text, topic breaks from an LLM.

6 min readSume
All posts

A YouTube chapter generator turns a video's transcript into a list of timestamps and titles that you paste into the video description, starting at 00:00. It needs two things: sentence timestamps from speech-to-text, and a language model that decides where the topic changes. With Sume, STT 1.0 returns the timed sentences and Agent Completions returns the chapters as JSON in a schema you define.

YouTube's rules below are quoted from YouTube Help: Video Chapters. The Sume steps follow the Sume API reference for STT 1.0, plus Agent Completions and Structured output. All were read on 2026-09-27.

What does YouTube need for chapters?

Chapters come from a list of timestamps in the description. YouTube can also add automatic chapters, but “not all videos are eligible for automatic chapters”, and a list you add yourself “will override automatic video chapters.” If your channel doesn't have chapters yet, YouTube says to apply for access to Advanced features.

From YouTube Help: Video Chapters, read 2026-09-27.
RuleYouTube Help says
Where“In the Description, add a list of timestamps and titles.”
First timestamp“Make sure that the first timestamp you list starts with 00:00.”
Count and order“Your video should have at least three timestamps listed in ascending order.”
Length“The minimum length for video chapters is 10 seconds.”

How do I get timestamps from what is said?

Transcribe the audio with sentence segments. STT 1.0 takes a public HTTPS audio URL, not a YouTube link, so start from your own video file: extract its audio track and host it where STT 1.0 can fetch it. For a video already on Sume, video inspect with transcribe: true and the same segmentation returns sentence segments without that step.

  • Each segment carries index, text, start, end, and duration_seconds, in seconds from the start of the audio.
  • One request covers up to 10 minutes. For a longer video, transcribe it in parts and add each part's start time to its segments, as in Transcribe long audio files.
curl -X POST https://api.sume.com/v1/stt-1.0/transcribe \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: episode-42-part-1" \
  -d '{
    "audio_url": "https://example.com/audio/episode-42-part-1.m4a",
    "duration_seconds": 600,
    "segmentation": { "mode": "sentence" }
  }'

How do I turn the transcript into chapters?

Give the timed sentences to a language model and ask for chapter starts and titles in a fixed JSON shape. With Sume's POST /v1/agent/completions, send the segments in input, which the agent treats as data rather than instructions, and bind the shape with output_schema. Summarize a video with an API uses the same call for a summary; here the output is only chapter starts and titles.

  • generation_spend_cap_usd is required, has no default, and can't be 0. Chapters need no media generation, so a small cap is enough.
  • The schema must fit the strict subset: the root is an object, every object sets additionalProperties: false, and every property is listed in required.
  • The call returns 202 with an agent.run receipt. Poll its status_url until next_action stops being poll_status; a completed run fills output with your chapters. If nothing satisfies the schema, output is null, output_error says why, and over the API the run ends failed.
  • The API key needs the agent_completions:write scope, which keys created before Agent Completions shipped don't carry.
curl -sS -X POST https://api.sume.com/v1/agent/completions \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: episode-42-chapters" \
  -d '{
    "instruction": "Split this talk into chapters where the topic changes. Start each chapter at a segment start. Keep titles short.",
    "input": { "segments": [{ "index": 0, "text": "Welcome back to the show.", "start": 0, "end": 2.4 }] },
    "output_schema": {
      "name": "acme/youtube-chapters/v1",
      "schema": {
        "type": "object", "additionalProperties": false, "required": ["chapters"],
        "properties": { "chapters": { "type": "array", "items": {
          "type": "object", "additionalProperties": false,
          "required": ["start_seconds", "title"],
          "properties": {
            "start_seconds": { "type": "number" }, "title": { "type": "string" } } } } }
      }
    },
    "generation_spend_cap_usd": 1
  }'

How do I format the chapters for the description?

Check the model's list against YouTube's rules in code before you paste it: sort by start time, set the first to 00:00, drop any chapter that would run under 10 seconds, and require at least three. This formatter writes MM:SS, adding hours past 60 minutes:

const pad = (n) => String(n).padStart(2, "0");
function stamp(seconds) {
  const s = Math.floor(seconds);
  const h = Math.floor(s / 3600);
  const m = Math.floor((s % 3600) / 60);
  return (h ? h + ":" + pad(m) : pad(m)) + ":" + pad(s % 60);
}

function toDescription(chapters, videoSeconds) {
  const sorted = [...chapters].sort((a, b) => a.start_seconds - b.start_seconds);
  const kept = [{ ...sorted[0], start_seconds: 0 }]; // the first timestamp is 00:00
  for (const c of sorted.slice(1)) {
    // YouTube: each chapter runs 10 seconds or longer
    if (c.start_seconds - kept[kept.length - 1].start_seconds >= 10) kept.push(c);
  }
  if (videoSeconds - kept[kept.length - 1].start_seconds < 10) kept.pop();
  if (kept.length < 3) throw new Error("YouTube needs at least three timestamps");
  return kept.map((c) => stamp(c.start_seconds) + " " + c.title).join("\n");
}

What does it cost?

Transcription is $0.01 per audio minute on API pricing, plus a 5.5% agent fee by default, so the transcript of a 30-minute video is $0.30 before the fee.

The completion's cost, the agent's own turns included, is debited_usd from GET /v1/usage?run_id=… (Usage). The spend cap counts generation, not the agent's LLM turns, so read the actual cost there.

Sources

Related posts

More in Agents

All Agents posts

Written by Sume