Skip to content
Search Documentation
Search across all documentation pages
Transcripts & Insights

Transcripts & Insights

Overview

When Transcodely generates captions for a video (the generate subtitle operation, see AI Captions), it also writes the transcript next to the caption file in three formats:

  • json: paragraphs, sentences and words with millisecond timings and per-word confidence. Built for code.
  • txt: plain paragraphs, no timestamps. Built for search indexes, CMS fields and copy-paste.
  • md: Markdown with a timestamp link on every paragraph. Built for show notes, docs sites and LLM context.

The transcript is part of the captions feature: it costs nothing on top of the captions fee, and you do not have to ask for it.

On top of the transcript you can opt in to insights: one AI pass over the transcript that returns title suggestions, a summary, key points, chapters, the questions the content answers, key terms, verbatim highlights and topics. Insights work for any kind of spoken content: courses, talks, interviews, product demos, podcasts, entertainment.


What you get

A generate track on output out_a1b2c3d4e5f6g7 that transcribes English produces these files in the job’s output destination:

FileWhat it is
{job_id}/subtitles/{output_id}_eng.vttThe caption file (WebVTT by default, or SRT).
{job_id}/subtitles/{output_id}_eng.transcript.jsonThe transcript, machine-readable.
{job_id}/subtitles/{output_id}_eng.transcript.txtThe transcript as plain text.
{job_id}/subtitles/{output_id}_eng.transcript.mdThe transcript as Markdown.

For a hosted video the files live under the video’s own storage prefix instead of {job_id}/subtitles/, next to its caption track.

With insights enabled, three more files land in the same folder once the insights are ready:

FileWhat it is
{output_id}_eng.insights.jsonEvery insights section, machine-readable.
{output_id}_eng.insights.mdEvery insights section as one Markdown document.
{output_id}_eng.chapters.vttThe chapters as a WebVTT chapters track.

Turn it on

There is nothing extra to turn on for transcripts: every generate track produces them. To choose the style of the txt and md renditions, or to request insights, add the transcript and insights options to the track. This request captions an already-hosted video, writes a verbatim transcript and asks for insights:

{
  "input_video_id": "vid_a1b2c3d4e5f6g7",
  "outputs": [
    {
      "subtitle_tracks": [
        {
          "operation": "generate",
          "transcript": { "style": "literal" },
          "insights": {
            "enabled": true,
            "hint": "Beginner cooking class; friendly tone"
          }
        }
      ]
    }
  ]
}
OptionTypeDescription
transcript.styleenumHow the txt and md renditions are written. One of: clean (default), literal. The json rendition always carries every word.
insights.enabledbooleanRun the insights pass after the job completes. Billed as described in Pricing.
insights.hintstringOptional guidance about the content, its audience or the tone you want, at most 300 characters. It steers the writing. It cannot change which sections you get or their format.

Both options are valid only on a generate track. They are rejected on any other operation.


Styles: clean and literal

People do not speak in finished sentences. The clean style is deliberately conservative. It removes only two things:

  • Hesitation sounds that are not words in the language, such as “um”, “uh”, “er” and “hmm” in English.
  • Stutters on short function words, such as “the the” or “I I”: an immediate exact repeat of a word like “the”, “a”, “and”, “to” or “I”, when nothing separates the two copies.

Content words are never removed, even when repeated: “very, very” and “no, no, no” stay as spoken. A removed word never takes the end of a sentence with it: its full stop, question mark or exclamation mark moves to the word before. Clean never changes, reorders or adds a word, so a clean transcript is the literal transcript with some words taken out. The literal style keeps every recognized word.

The same paragraph in both styles:

- So um the the first thing you want to do is, uh, heat the pan before you add the oil.
+ So the first thing you want to do is, heat the pan before you add the oil.

The lists of hesitation sounds and function words exist for English, German, Spanish, French and Bulgarian. For every other language nothing is removed, so clean and literal read the same.

In the json rendition, text and the paragraph and sentence text follow the style you chose. The words arrays are always verbatim, with the removed words flagged "filler": true, so you can render either style yourself.


The Markdown rendition

The Markdown file starts with YAML front matter, then one block per paragraph. Each block opens with a timestamp that links to #t=<seconds>:

---
transcodely_job: job_…
transcodely_output: out_…
language: eng
style: clean
duration_seconds: 1254.3
generated_at: 2026-10-24T10:00:00Z
---
# Transcript

**[00:00](#t=0)** First paragraph text…

**[01:35](#t=95)** Next paragraph…

Timestamps read MM:SS under one hour and H:MM:SS from one hour on. The link target is always whole seconds. The heading is always the word “Transcript”, because the transcript is written before anyone knows the video’s title. The insights Markdown file uses the video title instead.

To make the timestamp links work on your own page, map #t=95 to a seek. See Deep links.

The plain-text rendition

The txt file holds the paragraphs separated by one blank line. It has no timestamps and no front matter. It is UTF-8 with LF line endings and ends with a newline.

The JSON rendition

The json file is version 2 of the transcript schema. Times are in milliseconds:

{
  "version": 2,
  "language": "eng",
  "auto_generated": true,
  "duration_ms": 1254300,
  "style": "clean",
  "text": "So the first thing you want to do is, heat the pan before you add the oil.\n\nNext paragraph…",
  "speakers": [],
  "paragraphs": [
    {
      "id": "p1",
      "start_ms": 0,
      "end_ms": 9500,
      "text": "So the first thing you want to do is, heat the pan before you add the oil.",
      "sentences": [
        {
          "start_ms": 0,
          "end_ms": 4200,
          "text": "So the first thing you want to do is, heat the pan before you add the oil.",
          "words": [
            { "text": "So", "start_ms": 0, "end_ms": 180, "confidence": 0.97, "filler": false },
            { "text": "um", "start_ms": 180, "end_ms": 420, "confidence": 0.88, "filler": true }
          ]
        }
      ]
    }
  ],
  "segments": [
    { "start_ms": 0, "end_ms": 4200, "text": "So um the the first thing you want to do is, uh, heat the pan before you add the oil.", "confidence": 0.97 }
  ]
}
FieldDescription
versionAlways 2 for this shape.
styleThe style used for text and every paragraph and sentence text. Words always keep their verbatim text.
textThe whole transcript in that style, paragraphs separated by a blank line.
speakersReserved. Always empty: speakers are not identified.
paragraphs[].sentences[].words[]Every recognized word with its timing. confidence is omitted when the recognizer reports none. filler marks the words the clean style removes.
segmentsThe version 1 caption segments, kept unchanged for existing consumers.

A new paragraph starts only at the end of a sentence, and only when the speaker pauses for at least 0.8 seconds or the paragraph has reached 80 words or 40 seconds. The same audio always produces the same file, byte for byte.


Fetching a transcript

Transcripts are listed in two places, each with one entry per format:

  • On the job: subtitle_results[].transcript_renditions.
  • On a hosted video: text_tracks[].transcript_renditions.

Each entry carries format (json, txt or md), storage_key, url and, for Transcodely-managed storage, a signed_url. The signed URL is time-limited and re-issued on every read, so fetch the video or job again rather than storing it. It follows the same rules as every other signed asset URL. In your own bucket, read the file by its storage_key with your own credentials.

AttributeTypeDescription
formatenumOne of: json, txt, md.
storage_keystringKey of the file in the output destination.
urlstringFully-qualified storage URL of the file.
signed_urlstring | nullReady-to-fetch HTTPS URL, signed and time-limited. Managed storage only.

Download the Markdown transcript of a hosted video:

curl -s -X POST https://api.transcodely.com/transcodely.v1.VideoService/Get 
  -H "Authorization: Bearer ak_abc123" 
  -H "Content-Type: application/json" 
  -d '{"id": "vid_a1b2c3d4e5f6g7"}' 
| jq -r 'first(.video.text_tracks[].transcript_renditions[] | select(.format == "md") | .signed_url // empty)' 
| xargs curl -s -o transcript.md

In the dashboard, the Captions card on a video page has a download button for each format.

Jobs that completed before transcript renditions existed list no renditions. Their subtitle_results[].transcript_url still points at the older segment-level JSON.


Insights

What is in it

SectionWhat it is
title_suggestionsOne to three suggested titles, each at most 80 characters.
summaryA summary of the content, at most four sentences.
key_pointsThree to seven key points.
chaptersChapters ordered by start time and covering the whole video, at least two for anything three minutes or longer. Also written as chapters.vtt.
questionsUp to six questions the content answers, each with an answer of at most two sentences and the time the answer starts.
termsUp to ten key terms, each with the definition the content gives and the time it is introduced.
highlightsQuotable moments: verbatim quotes with the start and end time of their paragraph.
topicsUp to ten short topic labels.

Grounding rules

Every result is checked before it is saved. These checks are enforced, and a result that fails them is rejected:

  • Highlights are quotes, never paraphrases. Each highlight must appear word for word in the transcript.
  • Times come from the transcript. Every timestamp is the start of the transcript paragraph the item comes from. Chapters must be in order and inside the video’s duration.
  • Sizes are bounded. Each section must have the number of items listed above, titles at most 80 characters, a summary of at most four sentences and answers of at most two.
  • No links. No section may contain a URL.

If the result breaks a check, the pass retries once with the problems listed. If it still fails, the insights move to failed with insights_invalid and you are not charged.

Two more rules are instructions to the model rather than checks, so they are followed closely but not verified:

  • Answers and definitions come from the content. They should say what the video says, not what the model knows.
  • Same language. Insights are written in the transcript’s language unless your hint asks for another.

Async: watch for it or get a webhook

Insights run after the job completes, so they arrive a little after the captions. From the moment the job is created, Job.insights lists one entry per track that asked for them, with status pending. It then moves to ready or failed. Hosted videos carry the same entries on Video.insights.

Two webhook events tell you when that happens, both carrying a job snapshot like the other job.* events:

EventWhen
job.insights.readyThe insights for one of the job’s tracks are ready.
job.insights.failedThe insights for one of the job’s tracks could not be produced.

A ready entry on the job:

{
  "output_id": "out_a1b2c3d4e5f6g7",
  "language": "eng",
  "status": "ready",
  "title_suggestions": ["How to Sear a Steak", "Searing Steak at Home: The Basics"],
  "summary": "A beginner walkthrough of searing steak in a home kitchen. It covers heating the pan, choosing an oil and resting the meat.",
  "key_points": [
    "Heat the pan before adding oil.",
    "Use an oil with a high smoke point.",
    "Rest the steak for five minutes before cutting."
  ],
  "chapters": [
    { "start_seconds": 0, "end_seconds": 95, "title": "Heating the pan" },
    { "start_seconds": 95, "end_seconds": 410, "title": "Searing" },
    { "start_seconds": 410, "end_seconds": 512.4, "title": "Resting and serving" }
  ],
  "questions": [
    { "question": "Why heat the pan before the oil?", "answer": "Oil added to a cold pan breaks down before the pan is hot enough to sear.", "start_seconds": 12 }
  ],
  "terms": [
    { "term": "Smoke point", "definition": "The temperature at which an oil starts to burn.", "start_seconds": 131 }
  ],
  "highlights": [
    { "text": "heat the pan before you add the oil", "start_seconds": 0, "end_seconds": 9.5 }
  ],
  "topics": ["cooking", "steak", "searing"],
  "storage_key": "job_a1b2c3d4e5f6/subtitles/out_a1b2c3d4e5f6g7_eng.insights.json",
  "url": "gs://my-bucket/job_a1b2c3d4e5f6/subtitles/out_a1b2c3d4e5f6g7_eng.insights.json",
  "chapters_storage_key": "job_a1b2c3d4e5f6/subtitles/out_a1b2c3d4e5f6g7_eng.chapters.vtt",
  "chapters_url": "gs://my-bucket/job_a1b2c3d4e5f6/subtitles/out_a1b2c3d4e5f6g7_eng.chapters.vtt",
  "markdown_storage_key": "job_a1b2c3d4e5f6/subtitles/out_a1b2c3d4e5f6g7_eng.insights.md",
  "markdown_url": "gs://my-bucket/job_a1b2c3d4e5f6/subtitles/out_a1b2c3d4e5f6g7_eng.insights.md",
  "generated_at": "2026-10-24T10:04:12Z",
  "hint": "Beginner cooking class; friendly tone"
}

On managed storage each file also has a signed URL: signed_url, chapters_signed_url and markdown_signed_url.

When insights fail

A failed entry carries an error_code, and no insights fee is charged:

error_codeMeaning
insights_invalidNo result passed the grounding rules, even after a retry.
insights_unsupported_originThe API cannot write to the output destination, for example an http origin.
insights_too_longThe transcript is over the size limit.
insights_transcript_unavailableThe transcript could not be read.
insights_refusedThe content was declined.
insights_unavailableThe service was unavailable.

Chapters on hosted videos

For a hosted video, chapters.vtt is attached to the video as a text track of kind chapters. It is not listed in the streaming manifest. GetSeoMarkup turns the chapters into key moments for search engines.

The insights Markdown file

insights.md puts every section in one document under the video’s title, with ## Summary, ## Key points, ## Chapters (each linked as [MM:SS](#t=S)), ## Questions this covers, ## Key terms, ## Highlights and ## Topics.

Deployments without insights

If insights are not enabled on the deployment you call, a job that sets insights.enabled is rejected at creation with parameter_unsupported. You are never charged for insights that cannot run.


Pricing

WhatPrice
Transcripts (json, txt, md)Included in the AI captions fee of €0.05 per source minute.
Insights€0.02 per video + €0.005 per source minute.

Insights appear on the job as two fees rows that are confirmed or voided together: insights_job (unit job, €0.02) and insights (unit source_minute, €0.005). The dashboard shows them as one Insights line. They are estimated when the job is created, confirmed when the insights are ready, and voided if they fail.

A 10-minute video with captions and insights costs €0.50 for captions and €0.07 for insights, on top of the encode and the processing fee. See the pricing page for the full rate card.


Privacy

Captions are transcribed on Transcodely’s own worker fleet. The audio is never sent to a third party.

Insights are different. To produce them, the transcript text is sent to Anthropic, our AI subprocessor. The audio and video are never sent. Anthropic does not use it to train models. Insights run only for the tracks where you set insights.enabled. Anthropic is listed on the Subprocessors page.


Run this against your own file

A free account includes 30-second test encodes, so the request on this page can be tried before anything is configured.