How YouTube transcript timestamps work

Use Capslane transcript offsets and durations for synchronized playback, quote search, chapters and clip selection.

Offsets and durations use milliseconds

offset is the segment start from the beginning of the video. duration is the expected display or speech interval.

JSON segment
{
  "text": "Example segment",
  "offset": 8150,
  "duration": 1200,
  "lang": "en"
}

Align a segment with playback

Convert the player position to milliseconds before comparing it with the transcript.

JavaScript
function segmentAt(segments, currentTimeSeconds) {
  const position = currentTimeSeconds * 1000
  return segments.find((segment) =>
    position >= segment.offset &&
    position < segment.offset + segment.duration
  )
}

Player events are not frame-perfect. Keep the source segment timing and treat the active segment as a presentation state.

Chunking preserves the covered range

When chunkSize groups several native segments, the merged offset starts at the first segment and its duration covers the end of the final segment. Request the native segment size when editing precision matters.

Store integers and the source language

Store milliseconds as integers to avoid floating-point drift. Keep the video ID, selected language and transcript source next to the segments so later cache or model changes do not make results ambiguous.

Keep the original segment boundaries beside any text you normalize for search. Removing punctuation or joining sentences in a search index should not replace the canonical timing. Plain-text output does not include enough information to reconstruct those boundaries later.

Convert units only at the player boundary

The example segment starts at 8.15 seconds and ends at 9.35 seconds. An HTML media player's currentTime uses seconds, so seeking to this segment means assigning segment.offset / 1000. To build a YouTube link, use the validated video ID and a whole-second start value:

JavaScript playback link
const startSeconds = Math.floor(segment.offset / 1000)
const link = new URL("https://www.youtube.com/watch")
link.searchParams.set("v", videoId)
link.searchParams.set("t", String(startSeconds) + "s")

Flooring the link timestamp starts just before a fractional segment boundary. Retain millisecond precision in your own player or clip editor. A segment is not a word alignment: precise cuts still require review against the audio.

Handle gaps and overlapping captions

The lookup example returns the first segment covering the player position, or undefined in a gap. Clear the active caption during that gap. If your UI supports overlapping tracks, select all matching segments instead of assuming only one can be active.

chunkSize is a character budget, not seconds or token count. Capslane keeps each source segment intact, so one segment may exceed that budget. The option applies to immediate responses; completed jobs return canonical segments. Grouped chunks can cover pauses between their source segments. Omit it when you need the finest available source boundaries. Generated and native transcripts share units, but their segmentation and timing accuracy can differ.

For quote search, store the matching segment's start and end and show enough surrounding text to verify the quote. For subtitle export, convert milliseconds to the target format and review line wrapping and overlap. Capslane's JSON response is not itself an SRT or WebVTT file.

Try a real preview in the transcript inspector, then use the complete Python or Node.js example to retrieve all segments.