Files
llink/js/mobile/src/hooks/use-transcript-playback.ts
T
Arjun PatelandGitHub a8a0b7db1b infra: add linting and formatting for js projects (#230)
* wip

* wip

* wip

* format

* wip(mobile): lint and format

* cleanup

* nits

* nits

* idiomatic react

* nit

* format all root files
2026-06-02 07:44:24 -07:00

50 lines
1.5 KiB
TypeScript

import { useMemo } from 'react';
import type { Transcript } from '@/api/types';
type Sentence = Transcript['paragraphs'][number]['sentences'][number];
interface TranscriptPlaybackState {
/** The sentence currently being spoken, or null if between sentences */
activeSentence: Sentence | null;
/** Index of the active word within the transcript's flat words array */
activeWordIndex: number | null;
}
export function useTranscriptPlayback(
transcript: Transcript | undefined,
currentTime: number,
): TranscriptPlaybackState {
return useMemo(() => {
if (!transcript) return { activeSentence: null, activeWordIndex: null };
// Find the active sentence across all paragraphs
let activeSentence: Sentence | null = null;
for (const paragraph of transcript.paragraphs) {
const sentence = paragraph.sentences.find(
(s) => currentTime >= s.start && currentTime <= s.end,
);
if (sentence) {
activeSentence = sentence;
break;
}
}
// Binary search for active word
const words = transcript.words;
let activeWordIndex: number | null = null;
let lo = 0;
let hi = words.length - 1;
while (lo <= hi) {
const mid = (lo + hi) >>> 1;
if (currentTime < words[mid].start) hi = mid - 1;
else if (currentTime > words[mid].end) lo = mid + 1;
else {
activeWordIndex = mid;
break;
}
}
return { activeSentence, activeWordIndex };
}, [transcript, currentTime]);
}