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-viewerOption 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-reactAPI 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
| Prop | Type | Default | Description |
|---|---|---|---|
audioSrc | string | — | Optional URL to an audio file. If omitted, uses Web Speech API or simulated timeline. |
alignment | CharacterAlignmentResponseModel | MOCK_ALIGNMENT | Optional custom alignment model containing character timings. |
componentColor | string | "var(--card)" | Container card background color. |
TranscriptViewerWords Props
| Prop | Type | Default | Description |
|---|---|---|---|
highlightBg | string | "var(--primary)" | Background highlight color for the currently spoken word. |
highlightText | string | "var(--primary-foreground)" | Text color for the currently active word. |
wordClassNames | string | — | Additional CSS classes applied to individual word spans. |
gapClassNames | string | — | Additional CSS classes applied to word gaps. |
renderWord | (props: { word, status }) => ReactNode | — | Custom render function for word elements. |
TranscriptViewerScrubBar Props
| Prop | Type | Default | Description |
|---|---|---|---|
showTimeLabels | boolean | true | Whether to render current time and duration labels. |
trackClassName | string | — | Custom classes for the track background bar. |
progressClassName | string | — | Custom classes for the active progress fill. |
thumbClassName | string | — | 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>
);
}