Premium highlight overlay styling (P3.3)

Replace the plain hard-cut white caption with a refined 48px caption, a soft drop
shadow, a thin subtle border, and a smooth alpha fade in and out (0.4s ramps)
within each overlay timeline window. Highlight renderer only; the multi-clip
renderer and overlay placement/safe-area logic are unchanged. Test added;
mvn -o verify green (246 tests, 0 failures).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bg76sLc43Wc3j5ZcLkboYR
This commit is contained in:
JSLMPR 2026-07-22 09:52:12 +02:00
parent 0dd64d96cd
commit 24bd1d78f2
2 changed files with 25 additions and 3 deletions

View File

@ -555,9 +555,17 @@ public class HighlightFfmpegRenderer {
}
private String drawTextFilter(TextOverlay overlay) {
return "drawtext=text='%s':x=%s:y=%s:fontsize=54:fontcolor=white:borderw=2:bordercolor=black@0.75:enable='between(t\\,%s\\,%s)'"
.formatted(escapeDrawText(overlay.text()), overlayX(overlay.placement()), overlayY(overlay.placement()),
overlay.timelineStartSeconds(), overlay.timelineEndSeconds());
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"
+ ":alpha='%s':enable='between(t\\,%s\\,%s)'")
.formatted(escapeDrawText(overlay.text()), overlayX(overlay.placement()),
overlayY(overlay.placement()), alpha, start, end);
}
private String overlayX(String placement) {

View File

@ -76,6 +76,20 @@ class HighlightFfmpegRendererTest {
.contains("[voice_line_0][voice_line_1]amix=inputs=2:duration=longest"));
}
@Test
void stylesOverlaysWithSoftShadowAndAlphaFade() {
HighlightFfmpegRenderer renderer = renderer();
String filter = renderer.overlayFilter(List.of(
new TextOverlay("First light.", 0.5, 3.0, "center_safe", "fade", "hook")));
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("enable='between(t\\,0.5\\,3.0)'");
}
@Test
void buildsMeasuredQaProbeCommands() {
HighlightFfmpegRenderer renderer = renderer();