Separate YouTube video titles from on-video song/artist fields with Pro gating, serve curated fonts and watermark assets for 1:1 preview parity, and include billing/API/docs/deploy stack for self-hosted release.
4.5 KiB
sidebar_position
| sidebar_position |
|---|
| 3 |
Video editing
Self-hosted Songs2VID includes a Layout Studio on the dashboard upload form: art-track compositions, blur backgrounds, typography, and watermarks with live preview. The same options are available on the REST API.
Classic vs art-track
| Mode | Behavior |
|---|---|
| Classic (no template) | Cover letterboxed on a black frame — simple and reliable |
| Art-track template | Cover + title/artist arranged by a fixed template, with a blurred cover fill behind |
Templates are enum-based. Free-form cover coordinates (x, y, coverX, …) are rejected so encoding stays predictable.
Templates
| Template | Layout |
|---|---|
COVER_LEFT_TEXT_RIGHT |
Cover on the left; title & artist on the right |
COVER_TOP_TEXT_BOTTOM |
Cover on top; title & artist below |
COVER_RIGHT_TEXT_LEFT |
Cover on the right; title & artist on the left |
CENTERED_COMPACT |
Centered cover with a compact title/artist stack |
Pick a template in the UI under Composition, or set metadata.layout.template in the API.
Title and artist
Each track can have:
- Title — used on the video and as the YouTube title (often prefilled from the filename)
- Artist — drawn under the title on art-track layouts (max 80 characters)
Artist is especially useful when ID3 tags or your API payload include it.
Blur background
When an art-track template is active, the encoder builds a full-frame background from the cover:
- Blur amount (
blurAmount,0–100, default55) — FFmpegboxblurintensity - Background opacity (
blurOpacity,0–100, default100) — how strong the blurred fill is versus solid black (0= black,100= full blur)
Use lower opacity for a darker, more subdued frame; higher for a soft wash of the artwork.
Fine-tuning
All values are clamped. These nudge the composition inside the template — they are not free-form canvas placement.
| Control | Field | Range | Default | What it does |
|---|---|---|---|---|
| Padding | textPadding |
16–120 px | 48 | Space around cover and text |
| Title ↔ artist | titleArtistGap |
0–64 px | 10 | Vertical gap between title and artist |
| Text horizontal | textOffsetX |
−120–120 px | 0 | Shift the text block left/right |
| Text vertical | textOffsetY |
−120–120 px | 0 | Shift the text block up/down |
In the dashboard, sliders update the live preview. Via API, nest them under metadata.layout (camelCase or snake_case aliases are accepted).
Per-track covers
Upload a shared cover for the batch, then optionally set a different image per item (metadata.imagePath after uploading with type=image). Useful for singles that share an album batch but need distinct artwork.
Watermarks
Modes:
| Mode | Effect |
|---|---|
none |
No watermark |
default |
Built-in Songs2VID branding |
text |
Custom text with optional typography |
logo |
Custom PNG (upload with type=logo, then set logoPath) |
Position and offset
- Position:
top-left·top-right·bottom-left·bottom-right·center - Offsets (
offsetX/offsetY):0–200px from the chosen anchor (default20)
Typography (text mode)
Curated fonts (bundled under assets/fonts after fetch):
system— FFmpeg defaultinter·montserrat·roboto·oswald·playfaircustom— your.ttf/.otf(max 10 MB; upload withtype=font, setfontKey: "custom"andfontPath)
Refresh curated files if missing:
node scripts/fetch-watermark-fonts.mjs
Text length is capped at 80 characters.
Dashboard workflow
- Add audio (and optional per-track covers)
- Open Layout Studio on a track
- Choose classic or a template, then tune blur, padding, gaps, and text offsets
- Configure watermark mode, font, and position
- Preview updates live; submit to enqueue encoding
API
See Endpoints for curl examples. Layout and watermark objects live under each item’s metadata:
{
"title": "My Track",
"artist": "My Artist",
"layout": {
"template": "COVER_LEFT_TEXT_RIGHT",
"blurAmount": 60,
"blurOpacity": 85,
"textPadding": 48,
"titleArtistGap": 12,
"textOffsetX": 0,
"textOffsetY": 0
},
"watermark": {
"mode": "text",
"text": "My Label",
"fontKey": "montserrat",
"position": "bottom-right",
"offsetX": 24,
"offsetY": 24
}
}