diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..29c07bf --- /dev/null +++ b/SPEC.md @@ -0,0 +1,116 @@ +# videnc-vibe Specification + +## Overview +FFmpeg-based video transcoder for DVD/Blu-ray to SVT-AV1 with automatic metadata fetching. + +## Configuration + +Config path: `-c` flag or `~/.config/videnc-vibe/config.yaml` + +```yaml +omdb_api_key: "your-key-here" + +encoding: + dvd: + crf: 30 + preset: 2 + bluray: + crf: 29 + preset: 3 + +paths: + input: "./input" + output: "./output" + originals: "./originals" + failed: "./failed" +``` + +## Flags +- `-d` : Delete original after successful encode (default: move to originals/) +- `-c` : Config file path (default: ~/.config/videnc-vibe/config.yaml) + +## Input Parsing + +Regex patterns: +- Movie: `tt\d+` → extract IMDB ID +- Series: `tvm\d+` + `s\d\de\d\d` → extract TVmaze ID + season + episode (both required) + +## Media Detection + +| Condition | Media Type | +|-----------|------------| +| < 600k pixels/frame | DVD | +| ≥ 600k pixels/frame | Blu-ray | + +## Encoding Parameters + +### Video +- Codec: SVT-AV1 +- Pixel format: yuv420p10le +- Scaling: zscale filter with spline36 +- Preset: 2 (DVD) / 3 (Blu-ray) - configurable +- CRF: 30 (DVD) / 29 (Blu-ray) - configurable +- SVT-AV1 params: film-grain=10,film-grain-denoise=1,scd=1,qm-min=4,qm-max=15 +- Deinterlace: bwdif mode 0 if interlaced + +### Audio +- Pipeline: Extract → WAV (48kHz) → Opus (48kHz) +- FFmpeg libopus is NOT used (poor quality) + +## Matroska Tags + +### Movie +| Tag | Source | +|-----|--------| +| TITLE | OMDb response | +| DATE_RELEASED | OMDb response (ISO 8601: YYYY-MM-DD) | +| IMDBID | Input filename | +| ORIGINAL_MEDIA_TYPE | DVD or Blu-ray | + +### Series +| Tag | Source | +|-----|--------| +| TITLE | TVmaze response (episode name) | +| COLLECTION | TVmaze response (show name) | +| SEASON | Parsed from filename | +| EPISODE | Parsed from filename | +| DATE_RELEASED | TVmaze response (ISO 8601: YYYY-MM-DD) | +| IMDBID | TVmaze response | +| TVMAZE_ID | Custom tag | +| ORIGINAL_MEDIA_TYPE | DVD or Blu-ray | + +## Stream Metadata +- Preserve language tags per stream + +## Output Naming + +| Scenario | Filename | +|----------|----------| +| Movie with metadata | `{Title}.{IMDBID}.mkv` | +| Series with metadata | `{ShowName}.S{season}E{episode}.mkv` | +| No ID match / API fail | `{random}.nometadata.mkv` | + +## File Handling + +| Outcome | Input file | Output file | +|---------|------------|-------------| +| Success | `-d`: delete, else: move to originals/ | move to output/ | +| Failure | move to failed/ | move to failed/ | + +## Logging + +- info.log: Human-readable info level +- error.log: Human-readable error level +- structured.json: JSON structured logs + +## Polling +- Scan input folder every 10-30 seconds for `.mkv` files + +## Commit Message Format +Use Conventional Commits style: +- `add:` for new features +- `fix:` for bug fixes +- `refactor:` for code restructuring +- `chore:` for maintenance tasks + +Example: "add: add command line argument support"