mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-21 05:58:12 +02:00
feat(reels): interrupteur « Afficher le logo sur la vidéo »
Le petit logo affiché pendant la vidéo devient optionnel (activé par défaut), sur les 4 pages Reel (vidéo et images, bureau et mobile) ainsi que dans l'aperçu. Le grand logo de l'effet de fin reste piloté par son propre interrupteur. Pris en charge par le rendu Remotion et par le rendu FFmpeg de secours (show_watermark). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ze4bs7tpF1KGWUk6ZZSZ4
This commit is contained in:
16 files changed
+102
-17
No files matched your search
@@ -86,6 +86,8 @@ class ReelRequest(BaseModel):
|
||||
# Préparation Remotion : le logo est composé par Remotion, mais sa présence
|
||||
# allonge la vidéo pour laisser place à l'effet de fin.
|
||||
has_logo: bool = False
|
||||
# Petit logo en coin pendant la vidéo (le grand logo de fin dépend de enable_ending_effect)
|
||||
show_watermark: bool = True
|
||||
# Champs d'anciennes versions, acceptés et ignorés
|
||||
music_id: str | None = None
|
||||
word_duration: float | None = None
|
||||
@@ -296,6 +298,7 @@ async def _gather(request: ReelRequest, workdir: Path, clock: Stopwatch, *, fetc
|
||||
watermark=watermark if has_watermark else None,
|
||||
outro_expected=not fetch_logo and request.has_logo,
|
||||
ending_effect=request.enable_ending_effect,
|
||||
show_watermark=request.show_watermark,
|
||||
keep_original_audio=info.has_audio,
|
||||
)
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ class RenderPlan:
|
||||
# Effet de fin prévu sans que le logo passe par FFmpeg (rendu Remotion)
|
||||
outro_expected: bool = False
|
||||
ending_effect: bool = True
|
||||
# Petit logo en coin pendant la vidéo (le grand logo de fin dépend de ending_effect)
|
||||
show_watermark: bool = True
|
||||
keep_original_audio: bool = False
|
||||
|
||||
@property
|
||||
@@ -175,17 +177,25 @@ def build_command(plan: RenderPlan) -> list[str]:
|
||||
current = "vbase"
|
||||
if wm_idx is not None:
|
||||
corner = "W-w-30:H-h-30"
|
||||
if plan.outro and plan.ending_effect:
|
||||
logo_start = plan.logo_start
|
||||
graph.append(f"[{wm_idx}:v]scale=200:-1,split=2[wm_small][wm_big0]")
|
||||
graph.append("[wm_big0]scale=-1:300[wm_big]")
|
||||
graph.append(f"[{current}][wm_small]overlay={corner}:enable='lt(t,{logo_start:.3f})'[vwm1]")
|
||||
graph.append(f"[vwm1][wm_big]overlay=(W-w)/2:(H-h)/2-100:enable='gte(t,{logo_start:.3f})'[vwm2]")
|
||||
current = "vwm2"
|
||||
else:
|
||||
big_logo = bool(plan.outro and plan.ending_effect)
|
||||
logo_start = plan.logo_start
|
||||
if big_logo and plan.show_watermark:
|
||||
graph.append(f"[{wm_idx}:v]split=2[wm_small0][wm_big0]")
|
||||
graph.append("[wm_small0]scale=200:-1[wm_small]")
|
||||
elif plan.show_watermark:
|
||||
graph.append(f"[{wm_idx}:v]scale=200:-1[wm_small]")
|
||||
graph.append(f"[{current}][wm_small]overlay={corner}[vwm1]")
|
||||
elif big_logo:
|
||||
graph.append(f"[{wm_idx}:v]null[wm_big0]")
|
||||
if plan.show_watermark:
|
||||
until = f":enable='lt(t,{logo_start:.3f})'" if big_logo else ""
|
||||
graph.append(f"[{current}][wm_small]overlay={corner}{until}[vwm1]")
|
||||
current = "vwm1"
|
||||
if big_logo:
|
||||
graph.append("[wm_big0]scale=-1:300[wm_big]")
|
||||
graph.append(
|
||||
f"[{current}][wm_big]overlay=(W-w)/2:(H-h)/2-100:enable='gte(t,{logo_start:.3f})'[vwm2]"
|
||||
)
|
||||
current = "vwm2"
|
||||
if plan.outro and plan.ending_effect:
|
||||
graph.append(f"[{current}]subtitles='{filter_path(plan.outro)}'[vout0]")
|
||||
current = "vout0"
|
||||
|
||||
@@ -77,6 +77,16 @@ def test_big_logo_waits_for_the_end_of_the_voice():
|
||||
assert "gte(t,6.800)" in _graph(build_command(plan))
|
||||
|
||||
|
||||
def test_corner_logo_can_be_hidden_while_keeping_the_ending_logo():
|
||||
base = dict(video=Path("in.mp4"), video_duration=6.0, output=Path("out.mp4"), watermark=Path("logo.png"))
|
||||
hidden = _graph(build_command(RenderPlan(**base, outro=Path("o.ass"), show_watermark=False)))
|
||||
assert "W-w-30:H-h-30" not in hidden
|
||||
assert "overlay=(W-w)/2" in hidden
|
||||
|
||||
nothing = _graph(build_command(RenderPlan(**base, show_watermark=False)))
|
||||
assert "overlay" not in nothing
|
||||
|
||||
|
||||
def test_prepared_video_has_no_audio_and_final_duration():
|
||||
from app.render import build_prepared_video_command
|
||||
|
||||
|
||||
Reference in new issue
Block a user