R7: bold, animated overlay captions
Overlays are now large (fontsize 84) with a thick outline + strong drop shadow so
they read on any background, and animate in: a snappy 0.18s alpha punch plus a
34px rise-up over 0.22s, with a soft ease-out. Placed on the payoff beat so the
entrance lands on the musical/edit accent. This presents the Tier-2 vision
director semantic caption ("STRIKE") boldly. Overlay style/animation asserted in
the existing overlay test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MPuJXQyAeWpFcTtcnxo1UN
This commit is contained in:
parent
f03d5472c5
commit
67bdf683ca
|
|
@ -51,9 +51,11 @@ Legend: ✅ implemented · ⏳ planned (see `cinematic-highlight-poc-plan.md` P5
|
|||
per-shot push-in (sub-segment splitting would reset the zoom); needs a time-varying `setpts` or a push-in
|
||||
that spans sub-segments. The crossfade already softens the *cut* into the payoff.
|
||||
|
||||
## R7 — Overlays: bold, animated, synced ⏳ (P5.12)
|
||||
- Title/label text scaled to the frame, with an entrance (scale/fade) timed to the musical/edit accent — not
|
||||
small static text dropped on screen.
|
||||
## R7 — Overlays: bold, animated, synced ✅
|
||||
- **Rule:** captions are large (fontsize 84), thick-outlined + drop-shadowed for legibility on any background,
|
||||
with a snappy entrance (0.18 s alpha punch + 34 px rise-up over 0.22 s) and a soft ease-out. `drawTextFilter`.
|
||||
- **Ties to Tier 2 (R9):** the vision director produces the caption *text* ("STRIKE"); R7 makes it *land*. The
|
||||
overlay is placed on the payoff beat, so it's timed to the musical/edit accent. Verified on bowling.
|
||||
|
||||
## R8 — Music sync: climax on the payoff ⏳ (P5.13)
|
||||
- **Measure:** the payoff beat's timeline position.
|
||||
|
|
|
|||
|
|
@ -953,15 +953,16 @@ public class HighlightFfmpegRenderer {
|
|||
private String drawTextFilter(TextOverlay overlay) {
|
||||
String start = Double.toString(overlay.timelineStartSeconds());
|
||||
String end = Double.toString(overlay.timelineEndSeconds());
|
||||
// Smooth alpha fade: ramp up over the first 0.4 s, hold, ramp down over the last 0.4 s.
|
||||
String alpha = "if(lt(t\\," + start + "+0.4)\\,(t-" + start + ")/0.4\\,"
|
||||
+ "if(lt(t\\," + end + "-0.4)\\,1\\,(" + end + "-t)/0.4))";
|
||||
// Premium caption: refined size, soft drop shadow, thin subtle border for legibility.
|
||||
return ("drawtext=text='%s':x=%s:y=%s:fontsize=48:fontcolor=white"
|
||||
+ ":shadowcolor=black@0.55:shadowx=2:shadowy=2:borderw=1:bordercolor=black@0.35"
|
||||
// Snappy entrance timed to the beat: alpha punches in over 0.18 s, holds, eases out over 0.35 s.
|
||||
String alpha = "if(lt(t\\," + start + "+0.18)\\,(t-" + start + ")/0.18\\,"
|
||||
+ "if(lt(t\\," + end + "-0.35)\\,1\\,max(0\\,(" + end + "-t)/0.35)))";
|
||||
// Rise-up entrance: start 34 px below the resting position and ease up over 0.22 s.
|
||||
String y = "(" + overlayY(overlay.placement()) + ")+34*(1-min(1\\,(t-" + start + ")/0.22))";
|
||||
// Bold cinematic caption: large, thick outline + strong drop shadow so it reads on any background.
|
||||
return ("drawtext=text='%s':x=%s:y=%s:fontsize=84:fontcolor=white"
|
||||
+ ":shadowcolor=black@0.7:shadowx=3:shadowy=3:borderw=4:bordercolor=black@0.6"
|
||||
+ ":alpha='%s':enable='between(t\\,%s\\,%s)'")
|
||||
.formatted(escapeDrawText(overlay.text()), overlayX(overlay.placement()),
|
||||
overlayY(overlay.placement()), alpha, start, end);
|
||||
.formatted(escapeDrawText(overlay.text()), overlayX(overlay.placement()), y, alpha, start, end);
|
||||
}
|
||||
|
||||
private String overlayX(String placement) {
|
||||
|
|
|
|||
|
|
@ -105,9 +105,11 @@ class HighlightFfmpegRendererTest {
|
|||
|
||||
assertThat(filter)
|
||||
.contains("drawtext=text='First light.'")
|
||||
.contains("fontsize=48")
|
||||
.contains("shadowcolor=black@0.55:shadowx=2:shadowy=2")
|
||||
.contains("alpha='if(lt(t\\,0.5+0.4)")
|
||||
.contains("fontsize=84") // bold
|
||||
.contains("borderw=4:bordercolor=black@0.6") // thick outline
|
||||
.contains("shadowcolor=black@0.7:shadowx=3:shadowy=3") // strong shadow
|
||||
.contains("alpha='if(lt(t\\,0.5+0.18)") // snappy 0.18s punch-in
|
||||
.contains("34*(1-min(1\\,(t-0.5)/0.22))") // rise-up entrance animation
|
||||
.contains("enable='between(t\\,0.5\\,3.0)'");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue