diff --git a/src/app/player/ScreeningPlayer.tsx b/src/app/player/ScreeningPlayer.tsx index 9efad36..9a8fda9 100644 --- a/src/app/player/ScreeningPlayer.tsx +++ b/src/app/player/ScreeningPlayer.tsx @@ -21,6 +21,9 @@ export interface ScreeningPlayerHandle { playFrom(videoId: string): void; } +/** Supported reel playback speeds, including normal rate as the default. */ +export const SCREENING_PLAYBACK_RATES = [1, 1.15, 1.25, 1.5, 2] as const; + const initialState = (index: number, durationSeconds: number): PlayerState => ({ phase: 'idle', index, @@ -50,11 +53,13 @@ export const ScreeningPlayer = forwardRef< ] as const; const controller = useRef(null); const announcedVideoId = useRef(null); + const playbackRateRef = useRef(1); const requestedIndex = playlist.findIndex((clip) => clip.videoId === initialVideoId); const initialIndex = Math.max(0, requestedIndex); const [state, setState] = useState( initialState(initialIndex, playlist[initialIndex]?.durationSeconds ?? 0), ); + const [playbackRate, setPlaybackRate] = useState(1); const publishState = useCallback( (next: PlayerState) => { @@ -81,9 +86,22 @@ export const ScreeningPlayer = forwardRef< getPlayback, onState: publishState, }); + controller.current.setPlaybackRate(playbackRateRef.current); return controller.current; }, [getPlayback, playlist, publishState, videos]); + const updatePlaybackRate = useCallback( + (rate: number) => { + playbackRateRef.current = rate; + setPlaybackRate(rate); + controller.current?.setPlaybackRate(rate); + for (const element of videos) { + if (element.current) element.current.playbackRate = rate; + } + }, + [videos], + ); + useImperativeHandle( ref, () => ({ @@ -272,6 +290,20 @@ export const ScreeningPlayer = forwardRef< {activeIndex + 1} of {playlist.length} +