From 36fe05c04b0cc2346a8a578c953a993a47a72e1e Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Tue, 24 Mar 2026 19:41:29 +0100 Subject: [PATCH] feat: show 3 words at a time in text overlay (TikTok style) Groups word timings by chunks of 3. The active word is highlighted in yellow/scaled; the 2 surrounding words show in white. Gives enough reading time while staying in sync with the voice. Co-Authored-By: Claude Sonnet 4.6 --- client/src/remotion/ImageComposition.tsx | 86 +++++++++++++----------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/client/src/remotion/ImageComposition.tsx b/client/src/remotion/ImageComposition.tsx index ecd3dfe..1fa0622 100644 --- a/client/src/remotion/ImageComposition.tsx +++ b/client/src/remotion/ImageComposition.tsx @@ -120,47 +120,53 @@ export const ImageComposition = ({ {/* Background music */} {musicUrl && } - {/* TikTok-style word-by-word text overlay (content section only) */} + {/* TikTok-style 3-words-at-a-time overlay (content section only) */} {frame < endingStart && ( - wordTimings && wordTimings.length > 0 ? ( - -
- {wordTimings.map((w, i) => { - const isActive = i === activeWordIdx; - if (!isActive) return null; - return ( - - {w.word} - - ); - })} -
-
- ) : overlayText ? ( + wordTimings && wordTimings.length > 0 && activeWordIdx >= 0 ? (() => { + // Group index: which chunk of 3 is currently active + const groupIdx = Math.floor(activeWordIdx / 3); + const groupStart = groupIdx * 3; + const groupWords = wordTimings.slice(groupStart, groupStart + 3); + return ( + +
+ {groupWords.map((w, gi) => { + const isActive = groupStart + gi === activeWordIdx; + return ( + + {w.word} + + ); + })} +
+
+ ); + })() : overlayText ? (