Tdarr is a free, self-hosted app that automates GPU-accelerated video transcoding, and it is the smartest way to shrink bloated NVR security-camera footage with NVENC. If your home surveillance system is eating a terabyte a week, Tdarr can quietly re-encode last night's recordings from H.264 to HEVC on your GPU and hand you back 40–60% of your disk — automatically, on a schedule, forever. This guide covers what Tdarr really does (and what it doesn't), how to wire it up with an NVR, and how to get NVIDIA NVENC working inside Docker without losing a weekend.
First, an honest disclaimer — Tdarr is not an NVR
Tdarr does not connect to cameras, it does not ingest RTSP, and it does not record anything. That job belongs to a real NVR — Frigate, Blue Iris, Shinobi, Agent DVR, or Frigate's bundled go2rtc. Your NVR pulls the RTSP streams and writes recording files to disk. Tdarr watches that folder and transcodes the finished files. Anyone selling you "Tdarr for live RTSP" is confused. Used correctly as a post-processor, though, it's the single best storage upgrade a self-hosted camera rig can get.
What Tdarr Actually Does
Tdarr (by HaveAGitGat) is an automation layer that sits on top of FFmpeg and HandBrake. You point it at a folder of video, define the rules for what "good" looks like, and it continuously scans, queues, and transcodes everything that doesn't match — then health-checks the results. It's the same engine the Plex/Jellyfin crowd uses to normalize giant movie libraries, and those same superpowers apply beautifully to 24/7 camera footage.
- Library scanning & automation. Tdarr watches folders and acts on new files automatically. Set it once; it runs forever.
- Server + Nodes architecture. One Server coordinates the queue; one or more Nodes do the actual encoding. Nodes can live on other machines, so you can offload transcoding to a box with a beefy GPU and keep your NVR untouched.
- Plugins and Flows. Classic Plugins are pre-built rules ("if not HEVC, transcode to HEVC"). The newer Flows are a visual node-graph where you drag logic together — filters, encoders, branches — for total control.
- Hardware transcoding. NVENC (NVIDIA), QSV (Intel Quick Sync) and VAAPI (Intel/AMD) are all supported, turning a 20-minute CPU encode into a 2-minute GPU encode.
- Health checks & stats. Every output is verified, and a dashboard shows space saved, files processed, and transcode time. You can watch the terabytes melt.
Why NVR Footage Is the Perfect Tdarr Target
Most security cameras stream H.264 because it's universally compatible and cheap to encode on a tiny camera SoC. The problem: H.264 at 24/7, multiplied by 4, 8, or 16 cameras, is a storage massacre. HEVC (H.265) delivers roughly the same visual quality at 40–60% smaller file sizes. But you usually can't just record in HEVC — many NVRs, browsers, and mobile apps still choke on H.265 live playback, and re-encoding live costs CPU you'd rather spend on motion detection.
That's the gap Tdarr fills. Let the camera and NVR do what they're good at — record rock-solid H.264 in real time. Then, hours later when nobody's watching, Tdarr sweeps in and batch-converts yesterday's clips to HEVC on the GPU. You keep the same number of days of footage on far less disk, or the same disk holds twice the history.
The storage math, in plain numbers
Eight 4 MP cameras recording H.264 24/7 land around 8–12 GB per camera per day, call it ~80 GB/day for the system, or ~2.4 TB/month. Convert completed recordings to HEVC at ~50% and that drops to ~1.2 TB/month. On a 4 TB drive your retention roughly doubles — from about 50 days to 100 — for the price of some idle GPU cycles overnight.
The Honest Architecture: Who Does What
Here's the whole pipeline. Notice Tdarr only ever touches files after the NVR is done writing them.
| Stage | Component | Job |
|---|---|---|
| 1. Capture | IP Camera | Streams H.264/H.265 over RTSP |
| 2. Record | NVR (Frigate, Blue Iris, Shinobi, Agent DVR) | Pulls RTSP, writes recording files to a storage folder |
| 3. Transcode | Tdarr (Server + Node) | Watches the folder, GPU-transcodes finished H.264 files to HEVC |
| 4. Store / Review | Disk + NVR UI | Smaller HEVC files; same retention UI, way more days kept |
Never let Tdarr touch a file the NVR is still writing
If Tdarr grabs an in-progress recording, you get a corrupt clip and an angry NVR. Always add a filter so Tdarr ignores files modified in the last 60–120 minutes (Frigate users commonly use a one-hour buffer), and point Tdarr at the NVR's finished recordings directory — never the live/cache segment folder. Treat the source as read-only history, not live data.
GPU Acceleration: NVENC vs. QSV vs. VAAPI
Software (CPU/x265) encoding gives the best compression but is brutally slow — a single camera-day could take hours and peg every core. Hardware encoders trade a sliver of efficiency for enormous speed, which is exactly the right deal for bulk CCTV footage you're never going to pixel-peep.
| Encoder | Hardware | FFmpeg codec | Best for |
|---|---|---|---|
| NVENC | NVIDIA GTX 10-series → RTX 40-series | hevc_nvenc | Fastest bulk HEVC; RTX cards excel at quality-per-watt |
| QSV | Intel iGPU / Arc (Quick Sync) | hevc_qsv | Low-power always-on boxes; great on N100/N305 mini-PCs |
| VAAPI | Intel / AMD GPUs on Linux | hevc_vaapi | Driver-level Linux acceleration without vendor SDKs |
For most home labs with an NVIDIA card lying around, NVENC is the path of least resistance, so that's what the rest of this guide uses. On an RTX card, lean on the slower presets (p6/p7) for better compression and tune CQ (constant quality) somewhere between 22 and 28 for surveillance footage — you do not need movie-grade fidelity on a driveway at 3 a.m.
Setup Part 1 — Prep the Host for NVENC
Before Docker can hand your GPU to a container, the host needs NVIDIA drivers plus the NVIDIA Container Toolkit. On Ubuntu/Debian:
# 1. Confirm the driver sees your GPU
nvidia-smi
# 2. Install the NVIDIA Container Toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
# 3. Wire the toolkit into Docker and restart
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
Now verify the GPU is actually reachable from inside a Tdarr node container, using Tdarr's own official test command. It downloads a sample and forces an hevc_nvenc encode — if it finishes clean, you're done with the hard part:
docker run --rm \
-e "NVIDIA_DRIVER_CAPABILITIES=all" \
-e "NVIDIA_VISIBLE_DEVICES=all" \
--gpus=all \
ghcr.io/haveagitgat/tdarr_node:latest \
/bin/bash -e -c 'curl -o /tmp/s.mkv -L \
https://samples.tdarr.io/api/v1/samples/sample__1080__libx264__aac__30s__video.mkv; \
ffmpeg -i /tmp/s.mkv -c:v:0 hevc_nvenc /tmp/s-out.mkv'
If the test fails before you blame Tdarr
99% of "NVENC won't work in Docker" problems are host-side: a missing Container Toolkit, a driver/CUDA mismatch, or forgetting --gpus=all. Get the command above passing first. Once raw FFmpeg can encode on the GPU inside a container, Tdarr will too — its workers run the exact same binary.
Setup Part 2 — Deploy Tdarr with Docker Compose
This compose file runs the Tdarr Server (web UI + coordinator) and an internal Node (the GPU worker) together. Map three things: Tdarr's own config/logs, a fast scratch /temp for in-flight transcodes, and your NVR's recordings as the /media library.
services:
tdarr:
image: ghcr.io/haveagitgat/tdarr:latest
container_name: tdarr
restart: unless-stopped
ports:
- "8265:8265" # Web UI
- "8266:8266" # Server <-> Node
environment:
- TZ=America/New_York
- PUID=1000
- PGID=1000
- serverIP=0.0.0.0
- serverPort=8266
- webUIPort=8265
- internalNode=true
- inContainer=true
- nodeName=GPUNode
# ---- GPU passthrough ----
- NVIDIA_DRIVER_CAPABILITIES=all
- NVIDIA_VISIBLE_DEVICES=all
volumes:
- ./tdarr/server:/app/server
- ./tdarr/configs:/app/configs
- ./tdarr/logs:/app/logs
- /fast/ssd/tdarr_temp:/temp # scratch space (SSD ideal)
- /srv/nvr/recordings:/media # your NVR's FINISHED recordings
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Bring it up with docker compose up -d, then open http://your-server-ip:8265. You'll land on the Tdarr dashboard with your internal GPU node already connected.
Setup Part 3 — Build the NVR Library & Flow
In the Tdarr UI, go to Libraries → Add Library and point its source at /media (your mapped recordings folder). Then configure the rules:
- Folder watch: enable so new recordings are picked up automatically.
- Transcode options: add the "Migrate to HEVC" plugin (or build a Flow). Set the encoder to
hevc_nvencso encoding runs on the GPU. - Skip-if-already-HEVC: add a filter so Tdarr ignores files that are already H.265 — otherwise it re-encodes its own output forever.
- Age filter: ignore files modified within the last 60–120 minutes so you never touch an active recording.
- Quality: for NVENC on RTX, set preset
p6/p7and CQ ~24 for surveillance. Higher CQ = smaller files.
If you prefer the visual Flow editor, a typical CCTV flow looks like: Input File → Check Video Codec (is it HEVC? → skip) → Check File Age (<1h? → skip) → FFmpeg hevc_nvenc (CQ 24, preset p7) → Replace Original → Health Check. Drag, connect, save. Workers immediately start chewing through the backlog.
Sample before you commit to "Replace Original"
Run the flow on a copy of one full day first, eyeball a few clips for motion smearing or audio drift, and confirm your NVR still plays the HEVC results in its timeline. Only once you trust the output should you enable "replace original." On surveillance footage, also watch for over-aggressive CQ washing out license plates or faces at night — that's the one place fidelity actually matters.
Validation & Real-World Gotchas
Tdarr will save you piles of space, but CCTV is its own beast. Budget for these before you point it at a year of footage:
| Gotcha | What happens | Fix |
|---|---|---|
| HEVC playback compatibility | Some NVR web UIs / browsers won't play H.265 in-timeline | Test in your NVR before bulk-converting; keep recent days as H.264 if needed |
| Timestamps & metadata | Re-encoding can drop the original creation time the NVR sorts by | Preserve mtime in the flow, or transcode into a parallel archive folder |
| Audio tracks | Camera audio (AAC/PCM) sometimes gets dropped or re-encoded oddly | Set audio to copy in the FFmpeg step unless you need it shrunk |
| GPU session limits | Consumer NVIDIA cards historically cap simultaneous NVENC sessions | Limit GPU worker count to 2–3; modern drivers have lifted older limits |
| Disk thrash / SSD wear | Heavy read-encode-write cycles on the array | Use an SSD for /temp; schedule transcoding for off-hours |
Worth a quick disk audit before and after so you can actually see the win — if you're on Linux, the commands in our Ubuntu system monitoring & cleanup guide make it easy to watch free space climb. And if Tdarr is living behind a reverse proxy on a VPS or home server, our nginx VPS configuration guide covers locking the web UI down properly.
What To Realistically Expect
For a typical 8-camera H.264 setup converted to HEVC at sane quality, plan on roughly 45–55% storage reduction, GPU encodes running many times faster than real-time (a 10-minute clip in well under a minute on an RTX card), and a one-time backlog burn that may run your GPU hot for a day or two before it settles into a quiet trickle. After that, Tdarr just hums along: new recordings come in, age past the buffer, get squeezed, and your retention quietly doubles. Set it, forget it, reclaim your NAS.
Quick Reference Cheat Sheet
| Setting | Recommended value | Why |
|---|---|---|
| Encoder | hevc_nvenc | GPU HEVC, the whole point |
| Preset | p6 / p7 | Slower preset = better compression on NVENC |
| CQ (quality) | 22–28 (try 24) | Higher = smaller; surveillance tolerates it |
| Audio | copy | Don't waste cycles re-encoding camera audio |
| Age filter | Skip < 60–120 min old | Never touch an active recording |
| Codec filter | Skip if already HEVC | Prevents infinite re-encode loops |
| Temp dir | On SSD | Saves your array from thrash |