mcut
@mcut/transcription

Functions

Subtitle formatting, caption building, and transcript search and edit functions exported by @mcut/transcription.

Subtitles

toSrt

function toSrt(input: TranscriptResult | SubtitleCue[]): string

Formats cues, or the cues derived from a transcript, as SubRip text with comma millisecond separators.

toVtt

function toVtt(input: TranscriptResult | SubtitleCue[]): string

Formats cues, or the cues derived from a transcript, as WebVTT text with a WEBVTT header.

transcriptToCues

function transcriptToCues(result: TranscriptResult): SubtitleCue[]

Returns display cues from provider segments, or from grouped words, or one cue over the full duration when only text exists.

Captions

buildApplyCaptionsCommand

function buildApplyCaptionsCommand(
  result: TranscriptResult,
  options: BuildApplyCaptionsOptions = {},
): CommandOfType<'applyCaptions'>

Returns an applyCaptions command whose captions come from toCaptionElements, targeting an optional track and replacing existing captions by default.

buildCaptionsCommand

function buildCaptionsCommand(
  project: Project,
  transcript: TranscriptResult,
  options: CaptionsCommandOptions = {},
): CommandOfType<'applyCaptions'>

Returns an applyCaptions command from validated options, resolving a caption style preset by id and scoping the transcript to one clip's audio window, and throws for an unknown style, a missing element, a clip with no source audio, or an element with a time remap. A multicam uses its audio source.

groupWords

function groupWords(words: TranscriptWord[], options: GroupWordsOptions = {}): WordGroup[]

Splits timed words into caption-sized groups, starting a new group at the character, duration, or gap limit and on speaker change.

toCaptionElements

function toCaptionElements(
  result: TranscriptResult,
  options: ToCaptionElementsOptions = {},
): CaptionElementInput[]

Converts a transcript into caption element inputs, grouping words or segments within the source range, shifting times by the offset, and clamping overlaps.

Transcript tools

mapCaptionWords

function mapCaptionWords(caption: TranscriptCaption): MappedWord[] | null

Locates each timed word inside the caption text in order and returns their character ranges, or null when the words no longer match the text.

mergeCaptions

function mergeCaptions(
  a: TranscriptCaption,
  b: TranscriptCaption,
): CaptionMergeResult

Merges two captions in either order into one spanning both, keeping word timings only when both sides carry them.

replaceAllMatches

function replaceAllMatches(
  captions: readonly TranscriptCaption[],
  query: string,
  replacement: string,
): CaptionContentPatch[]

Replaces every occurrence of the query across the captions and returns one content patch per changed caption.

replaceMatch

function replaceMatch(
  caption: TranscriptCaption,
  match: TranscriptMatch,
  replacement: string,
): CaptionContentPatch

Replaces one search match and returns a patch where replacement tokens take over the matched words' time span in proportion to their length.

retypeWord

function retypeWord(
  caption: TranscriptCaption,
  wordIndex: number,
  newText: string,
): CaptionContentPatch | null

Replaces the text of one word in place while keeping its timing, or returns null when the words no longer map to the text.

searchCaptions

function searchCaptions(
  captions: readonly TranscriptCaption[],
  query: string,
): TranscriptMatch[]

Runs a case-insensitive substring search across captions and returns each hit with its character range, word span, and absolute time.

searchProjectTranscript

function searchProjectTranscript(
  project: Project,
  queries: readonly string[],
): TranscriptSearchResult[]

Searches the word stream of every caption track and returns one result per query, in order. Matching ignores case and punctuation and runs across caption boundaries. Each match gives its timeline span, the eight words before and after it, and the silence on each side.

splitCaptionAtWord

function splitCaptionAtWord(
  caption: TranscriptCaption,
  wordIndex: number,
): CaptionSplitResult | null

Splits a caption immediately before the given word into two captions, or returns null when either half would be invalid or too short.

Corrections

correctCaptions

function correctCaptions(
  captions: readonly TranscriptCaption[],
  find: string,
  replace: string,
): TranscriptCorrection

Replaces whole-word, case-insensitive matches of find with replace across the captions of one track. Word timings stay. A multi-word find merged into one word spans the words it replaces, and a multi-word replace splits their timing by character share. A match split across two neighbouring captions moves into the first one, and the second starts after it or is removed when nothing is left. A match already inside an occurrence of replace is skipped, so a second call changes nothing. Apply the removals, then the patches in the order returned, so captions never overlap.

correctWords

function correctWords(
  words: readonly CaptionWord[],
  find: string,
  replace: string,
): { words: CaptionWord[]; count: number }

Applies the same correction to a plain word list, such as a stored source-time transcript, and returns the corrected words with the number of matches.

retypeCaption

function retypeCaption(caption: TranscriptCaption, text: string): CaptionContentPatch

Rewrites a caption's text as typed while keeping word timings. Words left unchanged keep their timing, the edited run takes the span of the words it replaces, and an inserted word shares the timing of its neighbour. Returns the text alone when the words no longer map to the old text.

Retakes

findRetakes

findRetakes(words, options) returns RetakeCandidate[], the spans a speaker abandoned and started again. It splits words into phrases at pauses of pauseMs or sentence punctuation. A phrase is a retake when a run of at least minMatchWords of its opening words, skipping fillers such as "um" and reading "gotta" as "got to", is spoken again within maxLookaheadMs. The restart may drift by up to two opening words when it begins a new phrase, as in "Every morning" restarted as "Each morning". Each candidate runs from the abandoned phrase start to the kept take start, so cutting it keeps the last take. Chained attempts merge into one candidate. Candidates come last to first, so cutting them in the returned order never shifts a range still to cut.

retakeOptionsSchema

OptionDefaultMeaning
pauseMs450A gap at least this long starts a new phrase
minMatchWords6Opening words a restart must repeat. Lower it to catch short restarts, at the cost of matching enumerations
maxLookaheadMs20000How far after a phrase start its restart may begin

On this page