Initial portable pretranscode service
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# Pretranscode
|
||||
|
||||
A small Jellyfin compatibility cache. It converts only known-incompatible video
|
||||
codecs to uniform 8-bit H.264 while preserving immutable originals.
|
||||
|
||||
## Design
|
||||
|
||||
- Originals are mounted read-only at `/source`.
|
||||
- Jellyfin reads a mirror tree at `/data/library` containing symlinks.
|
||||
- Each symlink points either to `/data/original` or a validated file under
|
||||
`/data/cache`.
|
||||
- Completed cache files replace symlinks atomically. Partial files are never
|
||||
exposed.
|
||||
- Cache eviction restores the original symlink before deleting cached content.
|
||||
- Jellyfin integration uses only its supported HTTP API.
|
||||
|
||||
There is one worker process. x264 uses available CPU cores; `nice 19`, idle I/O
|
||||
priority, and minimal Docker CPU shares make normal services take precedence.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Linux, Docker Compose, and ext4 tools
|
||||
- An existing Jellyfin server and API key
|
||||
- A shared Docker network between Jellyfin and Pretranscode
|
||||
- Jellyfin must have read-only access to the originals and cache
|
||||
|
||||
## Installation
|
||||
|
||||
1. Copy `.env.example` to `.env` and set all host paths and the Jellyfin API key.
|
||||
2. Provision the claimed cache allocation:
|
||||
|
||||
```bash
|
||||
sudo scripts/provision-cache.sh .env
|
||||
```
|
||||
|
||||
3. Mount the same paths in Jellyfin while keeping its existing logical library
|
||||
path:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ${PRETRANSCODE_VIEW_PATH}:/data/library:ro
|
||||
- ${MEDIA_LIBRARY_PATH}:/data/original:ro
|
||||
- ${PRETRANSCODE_CACHE_PATH}:/data/cache:ro
|
||||
```
|
||||
|
||||
4. Start Pretranscode:
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env up -d --build
|
||||
```
|
||||
|
||||
For Coolify, import `compose.yaml` as a Custom Docker Compose resource and enter
|
||||
the `.env.example` values through Coolify's environment-variable UI.
|
||||
|
||||
## Codec policy
|
||||
|
||||
Cached video is H.264 High Profile, Level 4.1, 8-bit `yuv420p`, CRF 20, capped
|
||||
at 12 Mbps. Existing audio, subtitles, chapters, and Matroska attachments are
|
||||
preserved when the container supports them.
|
||||
|
||||
The fixed source blacklist is:
|
||||
|
||||
- HEVC/H.265, including Dolby Vision
|
||||
- H.264 Hi10/10-bit
|
||||
- MPEG-2
|
||||
- VC-1
|
||||
|
||||
Client error reports never modify this list.
|
||||
|
||||
## Playback locking
|
||||
|
||||
- An active movie locks that movie.
|
||||
- An active episode locks its complete series.
|
||||
- Encoding is cancelled and its partial deleted if the item becomes locked.
|
||||
- A series remains locked for `SERIES_COOLDOWN_SECONDS` after playback.
|
||||
- Recently stopped content receives queue priority.
|
||||
|
||||
## Failure behavior
|
||||
|
||||
Graceful stops delete partial output. After a crash, startup removes stale
|
||||
partials and orphan files. Atomic symlinks always point to either an original or
|
||||
a completed cache file. If the cache mount marker is absent, the worker refuses
|
||||
to start.
|
||||
|
||||
## Migration
|
||||
|
||||
Copy or recreate these resources on the destination:
|
||||
|
||||
- Repository and `.env`
|
||||
- State directory
|
||||
- Symlink-view directory
|
||||
- Cache image/mount, if retaining completed transcodes
|
||||
|
||||
The cache is optional and can be rebuilt. The source fingerprint in every
|
||||
manifest prevents stale cache files from replacing changed originals. No
|
||||
Coolify UUID, Docker volume UUID, container name, or Jellyfin database path is
|
||||
stored by the application.
|
||||
Reference in New Issue
Block a user