v0.3.5.1 · self-hosted · open source

Reclaim disk space
on autopilot.

Transcode Talker scans your media library, queues oversized files, re-encodes them to HEVC with hardware acceleration, and gives you back tens of gigabytes, without you ever opening HandBrake again.

  • ✓ Hardware accelerated: VAAPI · QSV · NVENC · CPU fallback
  • ✓ Postgres or SQLite, your call
  • ✓ Self-hosted web app, runs in your browser
transcode-talker.local/dashboard

Dashboard

live
Total Encoded
922
+18 this week
Space Saved
181 GB
34.2% avg
Queue
3
running
Now encoding · Baka and Test S00E09.mkv 62%
VAAPI · CRF 26 · 334 fps · ETA 2m 04s
up to 80%
Smaller files with HEVC compression
4
Encoders: VAAPI, QSV, NVENC, libx265 CPU
6
UI languages: EN, PT, ES, FR, ZH, JA
MIT
Open source, self-hosted, no cloud
Features

Built for entire media libraries.

Designed for a single goal: shrink your library without losing quality, and never run the same conversion twice.

Hardware acceleration

VAAPI (AMD/Intel), QSV (Intel), or NVENC (NVIDIA). Automatically falls back to libx265 CPU when no GPU is mounted.

Filesystem scan

Walk any number of folders, filter by minimum size, and queue only files that aren't already HEVC.

Full history with audit

Every encode is recorded with hash, FPS, encoder used, CRF, and space saved. Export/import as JSON.

Postgres or SQLite

Postgres is the production default; SQLite stays for single-user setups. Switch with one env var.

Live progress over WebSocket

Real-time fps, ETA, current frame, and a streaming ffmpeg log. Survives API restarts via exponential backoff.

Admin log stream

Ring-buffered HTTP and business events with SSE streaming. Parses IP, method, path, and status inline.

Multilingual help

English, Português, Español, Français, 中文, 日本語. The in-app manual ships in six languages.

How it works

Three steps. That's the whole loop.

01

Scan

Point at /mnt/media (or anywhere). Filter by size threshold. Files already in HEVC are skipped automatically.

02

Encode

Worker pulls jobs from Postgres, runs ffmpeg with your chosen encoder/preset/CRF, and streams live progress over WebSocket.

03

Reclaim

Original is replaced atomically; hash and metrics get persisted to history. You watch your free space go up.

The interface

Built to be lived in.

Six screens, each doing one thing well. No tabs-in-tabs, no buried settings, no five-second polling loops.

localhost:4246/dashboard

Dashboard

live
Total Encoded
922
+18 this week
Space Saved
181GB
34.2% avg
Active Queue
3
running
Success Rate
98.7%
stable

Now encoding

Baka and Test S00E09.mkv62%
VAAPI · CRF 26 · 334 fps · ETA 2m 04s

Recent activity

  • Movie.S01E02.mkv · saved 412 MB
  • Show.Episode.mkv · saved 287 MB
  • Anime.E04.mkv · saved 633 MB
  • Big.Buck.Bunny.mkv · retried 1×
localhost:4246/scan

Scan & Select

/mnt/animes /mnt/media 126 candidates · 47 GB total
FileSizeCodec
Movies/Inception.mkv4.2 GBx264
Animes/Baka and Test S00E09.mkv1.2 GBx264
Shows/Office S03E18.mkv2.8 GBx264
Movies/Interstellar.mkv8.1 GBx264
Animes/Bleach S01E20.mkv980 MBx264
localhost:4246/encode

Encode Queue

● live
running Baka and Test S00E09.mkv 62% · 334 fps · ETA 2m 04s
queued Inception.mkv 4.2 GB · waiting
queued Office S03E18.mkv 2.8 GB · waiting

Live log

[22:48:34] ffmpeg -hwaccel vaapi -i input.mkv ...
[22:48:35] vaapi: AMD Renoir initialized (renderD128)
[22:48:36] frame=  2508 fps=334 q=-0.0 size=  142336kB time=00:01:44.65
[22:48:37] frame=  2841 fps=334 q=-0.0 size=  158204kB time=00:01:58.51
[22:48:38] frame=  3175 fps=334 q=-0.0 size=  175020kB time=00:02:12.36
localhost:4246/history

History

status: all encoder: vaapi 922 records · 181 GB saved
FilenameOriginalFinalSavedEncoderStatus
Baka and Test S00E09.mkv1.18 GB....vaapiinterrupted
Movie Inception.mkv8.13 GB5.21 GB2.92 GBvaapicompleted
Office S03E18.mkv2.81 GB1.87 GB0.94 GBvaapicompleted
Anime E04.mkv1.49 GB0.86 GB0.63 GBvaapicompleted
Bleach S01E20.mkv0.98 GB0.57 GB0.41 GBvaapicompleted
localhost:4246/roadmap

Roadmap

YAML-driven · live reload
severity: all priority: all version: 0.3.5.2

🐞 Bugs · 3 open

B-103 WebSocket reconnect doesn't surface a disconnected state Low
B-104 Storage page silently fails on hosts without /mnt/hdd Med
B-105 Folder picker doesn't refresh on parent change Low

✦ Improvements · 0 open

I-201 Full UI rewrite (React + Vite + Tailwind) done
I-202 Roadmap surface in the UI done

★ Features · 5 planned

F-301 Encode preset profiles (saveable) High
F-302 Scheduled scans (cron-style) Med
F-303 Webhook on completion Low
localhost:4246/settings/admin-logs

Admin Logs

● live
INFO22:48:34uvicorn.access
IP 192.0.2.41
HTTP Method GET
Path /api/health
HTTP Response 200
INFO22:48:36reencoder.api
Event encode.start
Job ID 7384
File Baka and Test S00E09.mkv
Encoder vaapi
WARN22:48:41reencoder.worker
Event encode.interrupted
Job ID 7384
Reason Interrupted by user
Architecture

Four containers, sharp boundaries. Same stack, one docker-compose.

Each service does one job. Talk over the docker network; the host only sees port 4246.

reencoder-web

nginx:1.27-alpine

Serves the Vite SPA bundle and reverse-proxies /api/* and /ws to the API.

4246 → 80

reencoder-api

FastAPI · Python 3.12

REST + WebSocket + SSE. Owns scans, queue mutations, history, config, and the live event bus.

4246/tcp internal

reencoder-worker

FFmpeg · Python 3.12

Pulls jobs from Postgres, spawns ffmpeg with hardware accel, streams progress. 8 CPU / 8 GB cap.

no public port

postgres

postgres:16-alpine

Metastore for sessions, jobs, history, scan results. Switch to SQLite with DB_BACKEND=sqlite.

5432 internal
Install

One command. Four containers up.

Compose ships sane defaults, no .env required for a local boot. Postgres is the production default; SQLite stays one env var away.

  • ✓ Linux host with Docker & Docker Compose
  • ✓ Optional: /dev/dri mapped for VAAPI/QSV acceleration
  • ✓ ~6 GB free for the Postgres volume + first build cache
# 1. Clone & enter
git clone https://github.com/<you>/reencoder-v3.git
cd reencoder-v3

# 2. Build & up (4 containers)
docker compose build
docker compose up -d

# 3. Verify
docker compose ps
NAME                STATUS              PORTS
reencoder-postgres  Up (healthy)        5432/tcp
reencoder-api       Up (healthy)        4246/tcp
reencoder-worker    Up (healthy)
reencoder-web       Up (healthy)        0.0.0.0:4246->80/tcp

# 4. Open the UI
open http://localhost:4246
Why this exists

HandBrake is great, until you have 5,000 files.

vs. manual HandBrake

  • ✓ Walks your library automatically
  • ✓ Skips files already in HEVC
  • ✓ Persists history; never re-encodes the same file twice
  • ✓ Resumes after crashes via heartbeat

vs. cloud services

  • ✓ Your media never leaves your home network
  • ✓ Uses the GPU you already own
  • ✓ Zero per-minute fees
  • ✓ Works offline

vs. bash scripts

  • ✓ Real UI with queue, history, search, filters
  • ✓ Audit trail with hashes per file
  • ✓ WebSocket live progress, not tail -f
  • ✓ Multi-encoder fallback when hardware breaks