feat(watermark): add watermark configuration and overlay support in video builder

Co-authored-by: Copilot <copilot@github.com>
pull/2558/head
MinhVu2711 2 months ago
parent 741f794729
commit 16de343e0b

@ -98,8 +98,17 @@ background_video = "minecraft" # Video nền
background_audio = "lofi" # Audio nền
background_audio_volume = 0.15 # Âm lượng audio nền (0 = tắt)
max_video_length = 120 # Max thời lượng video (giây)
watermark_enabled = true # Enable/disable watermark overlay
watermark_path = "assets/backgrounds/transparent-bg.png" # Path to watermark PNG file
```
**Watermark:**
- `watermark_enabled`: Set to `true` để thêm watermark vào tất cả videos, `false` để tắt
- `watermark_path`: Đường dẫn tới file PNG watermark (mặc định: `assets/transparent-bg.png`)
- File phải có kích thước 1080×1920 pixels với alpha transparency
- Vùng transparent sẽ hiển thị video phía dưới
- Watermark xuất hiện suốt thời lượng của video
TTS engine được lấy từ section `[settings.tts]` trong `config.toml`. Mặc định dùng **GoogleTranslate** (không cần API key).
---

@ -16,7 +16,7 @@ load_dotenv()
OHFREEME_API_URL = os.getenv("OHFREEME_API_URL", "")
OHFREEME_BASE_URL = os.getenv("OHFREEME_BASE_URL", "")
JWT_TOKEN = os.getenv("OHFREEME_JWT_TOKEN", "")
OHFREEME_JWT_TOKEN = os.getenv("OHFREEME_JWT_TOKEN", "")
VOICES_FILE = Path(__file__).resolve().parent.parent / "config" / "ohfreeme_voices.json"
MAX_RETRIES = 3
RATE_LIMIT_WAIT = 10
@ -101,13 +101,16 @@ class OhFreeMe:
"pitch": settings.config["settings"]["tts"].get("ohfreeme_pitch", 0),
}
headers = {
"accept": "*/*",
"cache-control": "no-cache",
"content-type": "application/json",
"origin": OHFREEME_BASE_URL,
"cookie": f"auth_token={JWT_TOKEN}",
"referer": OHFREEME_BASE_URL,
"user-agent": self._pick_user_agent(),
"accept": "*/*",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8,vi;q=0.7", # important
"sec-fetch-mode": "cors", # important
"sec-fetch-site": "same-origin", # important
"Cookie": f"auth_token={OHFREEME_JWT_TOKEN}", # important
"user-agent": self._pick_user_agent(), # important
# "origin": OHFREEME_BASE_URL,
# "referer": f"{OHFREEME_BASE_URL}/",
}
# streaming NDJSON response with debug logging
@ -138,7 +141,7 @@ class OhFreeMe:
continue
# debug: print raw line (decoded) to terminal
if data.get("status") == "done":
print_substep(f"[OhFreeMe debug] Received line: {data}", style="blue")
print_substep(f"[OhFreeMe debug] Received")
return self._extract_audio(data)
raise RuntimeError(f"OhFreeMe TTS failed after {MAX_RETRIES} retries (rate limited)")

@ -111,6 +111,10 @@ class ManualVideoBuilder:
# Output settings
self.output_dir = Path(self.config.get("output_dir", "manual_results"))
# Watermark settings
self.watermark_enabled = self.config.get("watermark_enabled", True)
self.watermark_path = Path(self.config.get("watermark_path", "assets/backgrounds/transparent-bg.png"))
def build(self) -> str:
"""Build the final video.
@ -189,12 +193,24 @@ class ManualVideoBuilder:
)
current_time += s["audio_duration"]
# Step 7: Render
# Step 7: Overlay watermark (if enabled)
if self.watermark_enabled and self.watermark_path.exists():
print_step("🎨 Applying watermark...")
watermark_input = ffmpeg.input(str(self.watermark_path))["v"]
background_clip = background_clip.overlay(
watermark_input,
x=0,
y=0,
)
elif self.watermark_enabled and not self.watermark_path.exists():
print_substep(f"Warning: Watermark enabled but file not found: {self.watermark_path}", style="yellow")
# Step 8: Render
print_step("🎥 Rendering the video...")
self.output_dir.mkdir(parents=True, exist_ok=True)
# Normalize filename
filename = self._normalize_filename(self.post.get("title", self.post_id))
filename = self._normalize_filename(self.post_id)
output_path = str(self.output_dir / f"{filename}.mp4")
# Prevent path too long
if len(output_path) > 251:

@ -50,7 +50,9 @@ MANUAL_DEFAULTS = {
"background_audio_dir": "assets/backgrounds/audio",
"background_audio_volume": 0.1,
"max_video_length": 120,
"screenshot_width_percent": 85
"screenshot_width_percent": 85,
"watermark_enabled": True,
"watermark_path": "assets/backgrounds/transparent-bg.png",
}
# Full default settings.config that TTS engines and shared modules expect.

Loading…
Cancel
Save