Sora UI
Voice

Transcript Viewer

A component for displaying an audio transcript with word-by-word highlighting synced to audio playback.

Loading transcript...

Installation

Option A: Via Sora UI CLI (Recommended)

If your project uses `shadcn/ui`, you can install this component and its dependencies automatically:

npx soraui-cli add transcript-viewer

Option B: Manual Copy-Paste

1. Copy the code from the Code > Component tab above.
2. Paste it in your project at components/transcript-viewer.tsx.
3. Install the dependencies:
npm install clsx tailwind-merge lucide-react

API Reference

Transcript Viewer is built as a flexible set of compound components, giving you full control over layout, audio binding, word styling, and controls.

TranscriptViewerContainer Props

PropTypeDefaultDescription
audioSrcstring—Optional URL to an audio file. If omitted, uses Web Speech API or simulated timeline.
alignmentCharacterAlignmentResponseModelMOCK_ALIGNMENTOptional custom alignment model containing character timings.
componentColorstring"var(--card)"Container card background color.

TranscriptViewerWords Props

PropTypeDefaultDescription
highlightBgstring"var(--primary)"Background highlight color for the currently spoken word.
highlightTextstring"var(--primary-foreground)"Text color for the currently active word.
wordClassNamesstring—Additional CSS classes applied to individual word spans.
gapClassNamesstring—Additional CSS classes applied to word gaps.
renderWord(props: { word, status }) => ReactNode—Custom render function for word elements.

TranscriptViewerScrubBar Props

PropTypeDefaultDescription
showTimeLabelsbooleantrueWhether to render current time and duration labels.
trackClassNamestring—Custom classes for the track background bar.
progressClassNamestring—Custom classes for the active progress fill.
thumbClassNamestring—Custom classes for the draggable scrubber thumb.

Examples

Compound Component Pattern

Standard setup composing container, words, play/pause trigger, and progress scrub bar.

App.tsx
import {
  TranscriptViewerContainer,
  TranscriptViewerAudio,
  TranscriptViewerWords,
  TranscriptViewerPlayPauseButton,
  TranscriptViewerScrubBar
} from "@/components/transcript-viewer";

export default function Demo() {
  return (
    <TranscriptViewerContainer>
      <TranscriptViewerAudio />
      <TranscriptViewerWords 
        highlightBg="#ffffff"
        highlightText="#09090b"
      />
      <div className="flex items-center gap-4 w-full">
        <TranscriptViewerPlayPauseButton />
        <TranscriptViewerScrubBar className="flex-1" />
      </div>
    </TranscriptViewerContainer>
  );
}

Custom Character Alignment

Pass timestamps matching ElevenLabs or custom speech-to-text API alignment models.

App.tsx
import {
  TranscriptViewerContainer,
  TranscriptViewerAudio,
  TranscriptViewerWords,
  TranscriptViewerPlayPauseButton,
  TranscriptViewerScrubBar
} from "@/components/transcript-viewer";

const myAlignment = {
  characters: ["H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"],
  character_start_times_seconds: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
  character_end_times_seconds: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2],
};

export default function CustomAlignmentDemo() {
  return (
    <TranscriptViewerContainer 
      alignment={myAlignment}
      audioSrc="/sample/audio.mp3"
    >
      <TranscriptViewerAudio />
      <TranscriptViewerWords />
      <div className="flex items-center gap-4 w-full">
        <TranscriptViewerPlayPauseButton />
        <TranscriptViewerScrubBar className="flex-1" />
      </div>
    </TranscriptViewerContainer>
  );
}