// 卡拉OK填色随读(karaoke-fill-sync)——旁白读到哪个词,哪个词就被深色从左到右 // 点亮。两行标语 "SHIP FASTER / BREAK NOTHING",每个词双层同文本叠放:底层 G.line // 浅灰字,上层 G.ink 深字用 clip-path: inset(0 X% 0 0) 按词内进度线性填充(逐词独立 // 叠层,clip 百分比即词内进度,无需量测词在整行的像素占比)。词级时间表模拟语速: // SHIP 20–38、FASTER 42–75(长词慢读)、BREAK 85–103、NOTHING 107–130,词间停顿。 // 正在填的词底下有 8px 深色下划线跟随填充右缘作读指。0–19f hold;130–149f 真静止。 import React from 'react'; import { useCurrentFrame, interpolate } from 'remotion'; import { G } from '../../_fixtures/Fixtures'; type Word = { text: string; start: number; end: number }; const LINES: Word[][] = [ [ { text: 'SHIP', start: 20, end: 38 }, { text: 'FASTER', start: 42, end: 75 }, ], [ { text: 'BREAK', start: 85, end: 103 }, { text: 'NOTHING', start: 107, end: 130 }, ], ]; const KaraokeWord: React.FC<{ word: Word; frame: number }> = ({ word, frame }) => { // 词内 linear 填充进度,clamp 保证读完保持 const p = interpolate(frame, [word.start, word.end], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const active = frame >= word.start && frame < word.end; // 正在读这个词 return ( {/* 底层:浅灰未读字 */} {word.text} {/* 上层:深字按进度从左到右揭开 */} {word.text} {/* 读指下划线:只在正在填的词下出现,右缘跟随填充进度 */} {active && ( )} ); }; export const KaraokeFillSync: React.FC = () => { const frame = useCurrentFrame(); return (
{LINES.map((words, li) => (
{words.map((w) => ( ))}
))}
); };