--- 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](./api/endpoints.md). ## 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`, default `55`) — FFmpeg `boxblur` intensity - **Background opacity** (`blurOpacity`, `0`–`100`, default `100`) — 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`–`200` px from the chosen anchor (default `20`) ### Typography (text mode) Curated fonts (bundled under `assets/fonts` after fetch): - `system` — FFmpeg default - `inter` · `montserrat` · `roboto` · `oswald` · `playfair` - `custom` — your `.ttf` / `.otf` (max 10 MB; upload with `type=font`, set `fontKey: "custom"` and `fontPath`) Refresh curated files if missing: ```bash node scripts/fetch-watermark-fonts.mjs ``` Text length is capped at 80 characters. ## Dashboard workflow 1. Add audio (and optional per-track covers) 2. Open **Layout Studio** on a track 3. Choose classic or a template, then tune blur, padding, gaps, and text offsets 4. Configure watermark mode, font, and position 5. Preview updates live; submit to enqueue encoding ## API See [Endpoints](./api/endpoints.md) for curl examples. Layout and watermark objects live under each item’s `metadata`: ```json { "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 } } ```