Make intro title fade optional
This commit is contained in:
parent
af3fd51226
commit
f51273d447
2 changed files with 34 additions and 15 deletions
|
|
@ -229,9 +229,10 @@ The most common visual timing/styling tweaks are exposed as constants near the t
|
|||
| `INTRO_LOGO_EXTRA_HOLD` | Extra seconds the synthesized intro still remains before the first crossfade. | `6.0` |
|
||||
| `INTRO_LOGO_FADE_OFFSET` | Minimum time (s) the logo stays fully visible before the first xfade is allowed to start. | `3.0` |
|
||||
| `INTRO_LOGO_DEFAULT_ALPHA` | Default opacity for the intro logo (1 = fully opaque, 0 = invisible). | `1.0` |
|
||||
| `INTRO_TITLE_FADE_DELAY` | Seconds after start before the main title begins fading in. | `3.0` |
|
||||
| `INTRO_TITLE_START_OFFSET` | Seconds after start before the title appears (or starts fading in). | `2.0` |
|
||||
| `INTRO_TITLE_FADE_LENGTH` | Seconds the fade-in/out lasts. | `1.0` |
|
||||
| `INTRO_TITLE_VISIBLE` | Seconds the title stays fully visible between fade in/out. | `4.0` |
|
||||
| `INTRO_TITLE_FADE_ENABLED` | If `False`, the title pops in at `INTRO_TITLE_START_OFFSET` instead of fading in. | `True` |
|
||||
| `DEFAULT_IMAGE_DURATION` | Default fully visible time per still image before fades are added. | `6.0` |
|
||||
| `DEFAULT_CROSSFADE_DURATION` | Default crossfade duration between media items. | `3.0` |
|
||||
| `FIRST_IMAGE_DURATION_MULTIPLIER` | Multiplier applied to the first still’s `--image-duration` to delay the first transition. | `2.0` |
|
||||
|
|
@ -259,7 +260,7 @@ Adjust these constants and rerun `movmaker.py` to change the intro behavior with
|
|||
- reads the Jamendo client ID from `JAMENDO_CLIENT_ID` or `~/.config/movmaker/jamendo.env`
|
||||
- fades music in over `DEFAULT_AUDIO_FADE_IN` seconds (2 s) and out over `DEFAULT_AUDIO_FADE_OUT` seconds (10 s) by default
|
||||
- builds a black intro still (matching the first media item’s resolution) when `--intro-logo` is provided, scales the logo to `INTRO_LOGO_TARGET_HEIGHT_RATIO` of the frame height (75 % by default), shows it at `INTRO_LOGO_DEFAULT_ALPHA` opacity (1.0 = fully opaque) from frame 0, and keeps it on screen for `audio_fade_in + INTRO_LOGO_EXTRA_HOLD` seconds (with defaults this is `DEFAULT_AUDIO_FADE_IN + INTRO_LOGO_EXTRA_HOLD`, i.e. 8 s) before allowing the first crossfade; the same clip is appended at the end so the last real scene crossfades back into the logo-on-black frame
|
||||
- opening title text fades in after `INTRO_TITLE_FADE_DELAY` seconds (2 s), stays visible for `INTRO_TITLE_VISIBLE` seconds (4 s), then fades out over `INTRO_TITLE_FADE_LENGTH` seconds (1 s)
|
||||
- opening title text shows up at `INTRO_TITLE_START_OFFSET` seconds (2 s). When `INTRO_TITLE_FADE_IN_ENABLED` is `True` it fades in/out using `INTRO_TITLE_FADE_LENGTH` (1 s); otherwise it appears instantly and only fades out (if `INTRO_TITLE_FADE_LENGTH` > 0). It remains fully visible for `INTRO_TITLE_VISIBLE` seconds (4 s).
|
||||
- fades the first real clip in with the `--video-fade` duration (default `DEFAULT_VIDEO_FADE`, currently 1 s) while leaving the logo intro instant-on when `INTRO_VIDEO_FADE_ENABLED` is `False`; when a logo intro is present, the reusable outro clip removes the need for a final global fade-out, so the crossfade into the outro handles the closing visuals while audio still follows `DEFAULT_AUDIO_FADE_OUT`
|
||||
- displays optional per-file captions at bottom center with slightly off-white text and a soft shadow; use `|` to split caption lines
|
||||
- adds persistent bottom-left title/date/place and bottom-right `Bubulescu.Org` stamps
|
||||
|
|
|
|||
44
movmaker.py
44
movmaker.py
|
|
@ -36,13 +36,14 @@ FFMPEG = BASE_DIR / "ffmpeg" / "ffmpeg"
|
|||
FFPROBE = BASE_DIR / "ffmpeg" / "ffprobe"
|
||||
INTRO_LOGO_NAME = "intro.png"
|
||||
DEFAULT_INTRO_LOGO = BASE_DIR / "img" / "moto_travel.png"
|
||||
INTRO_LOGO_TARGET_HEIGHT_RATIO = 0.90
|
||||
INTRO_LOGO_TARGET_HEIGHT_RATIO = 0.75
|
||||
INTRO_LOGO_EXTRA_HOLD = 6.0
|
||||
INTRO_LOGO_FADE_OFFSET = 3.0
|
||||
INTRO_LOGO_DEFAULT_ALPHA = 1.0
|
||||
INTRO_TITLE_FADE_DELAY = 2.0
|
||||
INTRO_TITLE_START_OFFSET = 4.0
|
||||
INTRO_TITLE_FADE_LENGTH = 1.0
|
||||
INTRO_TITLE_VISIBLE = 6.0
|
||||
INTRO_TITLE_FADE_ENABLED = True
|
||||
DEFAULT_IMAGE_DURATION = 6.0
|
||||
DEFAULT_CROSSFADE_DURATION = 3.0
|
||||
FIRST_IMAGE_DURATION_MULTIPLIER = 2.0
|
||||
|
|
@ -1001,17 +1002,34 @@ def build_video(
|
|||
subtitle_font_size = max(40, height // 18)
|
||||
main_title = data.title or title_lines[0]
|
||||
subtitle = " | ".join(x for x in [data.date, data.place] if x)
|
||||
fade_in_start = INTRO_TITLE_FADE_DELAY
|
||||
fade_in_end = fade_in_start + INTRO_TITLE_FADE_LENGTH
|
||||
visible_end = fade_in_end + INTRO_TITLE_VISIBLE
|
||||
fade_out_end = visible_end + INTRO_TITLE_FADE_LENGTH
|
||||
title_alpha = (
|
||||
f"if(lt(t\\,{fade_in_start:.3f})\\,0\\,"
|
||||
f"if(lt(t\\,{fade_in_end:.3f})\\,(t-{fade_in_start:.3f})/{INTRO_TITLE_FADE_LENGTH:.3f}\\,"
|
||||
f"if(lt(t\\,{visible_end:.3f})\\,1\\,"
|
||||
f"if(lt(t\\,{fade_out_end:.3f})\\,({fade_out_end:.3f}-t)/{INTRO_TITLE_FADE_LENGTH:.3f}\\,0))))"
|
||||
)
|
||||
title_enable = f"enable='between(t,{fade_in_start:.3f},{fade_out_end:.3f})'"
|
||||
fade_in_start = INTRO_TITLE_START_OFFSET
|
||||
fade_in_enabled = INTRO_TITLE_FADE_IN_ENABLED and INTRO_TITLE_FADE_LENGTH > 0
|
||||
fade_out_enabled = INTRO_TITLE_FADE_LENGTH > 0
|
||||
fade_in_end = fade_in_start + (INTRO_TITLE_FADE_LENGTH if fade_in_enabled else 0.0)
|
||||
visible_start = fade_in_end if fade_in_enabled else fade_in_start
|
||||
visible_end = visible_start + INTRO_TITLE_VISIBLE
|
||||
fade_out_end = visible_end + (INTRO_TITLE_FADE_LENGTH if fade_out_enabled else 0.0)
|
||||
if fade_in_enabled:
|
||||
title_alpha = (
|
||||
f"if(lt(t\\,{fade_in_start:.3f})\\,0\\,"
|
||||
f"if(lt(t\\,{fade_in_end:.3f})\\,(t-{fade_in_start:.3f})/{INTRO_TITLE_FADE_LENGTH:.3f}\\,"
|
||||
f"if(lt(t\\,{visible_end:.3f})\\,1\\,"
|
||||
f"if(lt(t\\,{fade_out_end:.3f})\\,({fade_out_end:.3f}-t)/{INTRO_TITLE_FADE_LENGTH:.3f}\\,0))))"
|
||||
)
|
||||
else:
|
||||
if fade_out_enabled:
|
||||
title_alpha = (
|
||||
f"if(lt(t\\,{fade_in_start:.3f})\\,0\\,"
|
||||
f"if(lt(t\\,{visible_end:.3f})\\,1\\,"
|
||||
f"if(lt(t\\,{fade_out_end:.3f})\\,({fade_out_end:.3f}-t)/{INTRO_TITLE_FADE_LENGTH:.3f}\\,0)))"
|
||||
)
|
||||
else:
|
||||
title_alpha = (
|
||||
f"if(lt(t\\,{fade_in_start:.3f})\\,0\\,"
|
||||
f"if(lt(t\\,{visible_end:.3f})\\,1\\,0))"
|
||||
)
|
||||
title_enable_end = fade_out_end if fade_out_enabled else visible_end
|
||||
title_enable = f"enable='between(t,{fade_in_start:.3f},{title_enable_end:.3f})'"
|
||||
if subtitle:
|
||||
title_y = f"(h-text_h)/2-{title_font_size // 2}"
|
||||
filters.append(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue