NVR playback not working? A practical guide to fixing VOD, codec mismatches, and recording gaps in Frigate and self-hosted setups.
Your NVR is recording. Detections are firing. But when you try to pull up a clip from two hours ago, you get a black screen, a spinning loader, or nothing at all. This is one of the most frustrating issues in self-hosted camera systems, and it affects Frigate, go2rtc, and virtually every open-source NVR stack. The root causes range from codec mismatches to storage misconfigurations, and the fixes are rarely obvious from error logs alone. This guide walks through every common cause of broken playback and VOD, with concrete solutions for each.
“At one Class C multifamily property in Fort Worth, Cyrano caught 20 incidents including a break-in attempt in the first month. Customer renewed after 30 days.”
Fort Worth, TX property deployment
See Cyrano in action
1. Codec mismatches: the #1 cause of broken NVR playback
Most NVR playback failures come down to a single problem: the codec your camera outputs does not match what your browser or playback client can decode. This is especially common when cameras default to h265 (HEVC) encoding while the browser only supports h264. Frigate's web UI, Home Assistant's media player, and most browser-based viewers cannot natively decode h265 streams. The result is a black screen or an infinite loading spinner where your footage should be.
The fix depends on your camera and NVR configuration. If your camera supports dual streams, set the main stream to h264 for recording and use a secondary MJPEG or h264 substream for live view. In Frigate, this means configuring your camera's RTSP URL to point to the h264 stream under the record role and using the substream for the detect role.
A typical Frigate configuration that avoids codec issues looks like this:
cameras:
front_door:
ffmpeg:
inputs:
- path: rtsp://user:pass@192.168.1.100:554/stream1
roles:
- record
- path: rtsp://user:pass@192.168.1.100:554/stream2
roles:
- detect
output_args:
record: -f segment -segment_time 10 -segment_format mp4 -c:v copy
record:
enabled: true
retain:
days: 7
mode: motionThe critical detail is -c:v copy in the output args. This tells ffmpeg to pass through the video codec without transcoding, which preserves quality and keeps CPU usage low. But it also means the recorded segments inherit whatever codec the camera sends. If your camera is sending h265 on stream1, your recordings will be h265, and playback in a browser will fail.
To verify what codec your camera is actually sending, use ffprobe:
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name \ -of default=noprint_wrappers=1 rtsp://user:pass@192.168.1.100:554/stream1
If the output shows codec_name=hevc, you need to either change your camera settings to h264, add a transcode step in ffmpeg, or use a player that supports h265 (VLC works, browsers generally do not).
Another common codec issue involves MJPEG streams. Some older cameras only output MJPEG, which consumes significantly more bandwidth than h264 at equivalent quality. MJPEG also does not support inter-frame compression, so every frame is a full JPEG image. This means higher storage consumption and, on some NVR setups, playback stutter because the system cannot read frames fast enough from disk. If you are stuck with MJPEG cameras, consider using go2rtc as a restreaming proxy. It can accept an MJPEG input and re-encode it as h264 for downstream consumers:
# go2rtc.yaml
streams:
front_door:
- ffmpeg:rtsp://user:pass@192.168.1.100:554/mjpeg#video=h264This adds CPU load for the transcode, but it solves the playback problem and dramatically reduces storage usage. For setups with more than a few cameras, you will want hardware acceleration (VAAPI on Intel, NVENC on NVIDIA) to keep transcoding sustainable.
2. Storage and retention: why recordings disappear
The second most common playback complaint is clips that simply do not exist when you go looking for them. You know the camera was recording, detections were logged, but the actual video file is gone. This almost always comes down to retention settings, disk space management, or filesystem issues.
Frigate manages recordings through its retention system, which operates independently for continuous recordings and event clips. A common misconfiguration is setting retain: days: 7 for recordings but leaving the event retention at its default (which may be shorter or longer depending on your version). When you go to review an incident from three days ago, the recording segment exists but the event metadata has already been purged, so the VOD endpoint cannot find the clip.
Disk space is the other silent killer. Frigate does not gracefully handle full disks. When the recording partition fills up, new segments fail to write and older segments may become corrupted mid-rotation. The fix is monitoring disk usage and setting conservative retention limits. A good rule of thumb for storage planning:
- h264 at 2048kbps (typical 1080p substream): roughly 21 GB per camera per day of continuous recording
- h264 at 4096kbps (typical 1080p main stream): roughly 42 GB per camera per day
- h265 at equivalent quality: approximately 30% to 40% smaller than h264, so roughly 15 GB and 28 GB respectively
- Motion-only recording: reduces total storage by 60% to 80% depending on scene activity
For a 4-camera setup with 7-day motion-only retention at 2048kbps, plan for approximately 120 to 170 GB. For continuous recording, multiply by 3x to 5x. Many users underestimate this and fill their drives within days of enabling continuous recording.
Filesystem choice also matters. Ext4 is reliable but has a fixed inode limit that can be exhausted by thousands of small segment files before disk space runs out. XFS handles large numbers of small files better. Some users run Frigate recordings on ZFS with compression enabled, which reduces storage needs by 10% to 20% with minimal CPU overhead. Avoid running NVR recordings on network storage (NFS, SMB) unless your network can consistently sustain the write throughput. A single camera at 4Mbps generates sustained writes of 500KB/s, and four cameras push that to 2MB/s continuously. Network hiccups cause dropped frames and corrupted segments.
Finally, check your Frigate database. The SQLite database that indexes recordings can grow large over time and slow down queries. If playback is working but takes 30+ seconds to load a clip, the database is likely the bottleneck. Running VACUUM on the SQLite database periodically helps, and moving the database to an SSD (separate from the recording drive) makes a significant difference.
Tired of Troubleshooting Your NVR?
Cyrano plugs into your existing DVR/NVR via HDMI and adds real-time AI monitoring. No camera replacement, installs in 2 minutes.
Book a Demo3. Self-hosted NVR vs. managed monitoring: an honest comparison
Self-hosted NVR setups like Frigate offer unmatched flexibility and privacy. You control your data, you choose your hardware, and there are no monthly fees for the software itself. But there is a real cost in maintenance hours that is easy to underestimate.
The typical self-hosted NVR maintenance cycle includes: firmware updates for cameras that occasionally break RTSP compatibility, ffmpeg version upgrades that change default behaviors, go2rtc configuration changes between versions, Coral TPU driver issues after kernel updates, disk monitoring and retention tuning, and debugging playback issues like the ones described above. For a home user who enjoys tinkering, this is part of the hobby. For a property manager or business owner who needs cameras to work reliably for liability and safety, every hour spent debugging is an hour not spent on their actual job.
Managed NVR solutions (Verkada, Rhombus, Eagle Eye Networks) solve the maintenance problem by handling everything in the cloud, but they come with significant tradeoffs: vendor lock-in, recurring costs of $100+ per camera per year, limited hardware choice, and potential privacy concerns with cloud-stored footage.
A middle ground that has emerged is adding AI monitoring on top of existing hardware. Solutions like Cyrano, Spot AI, and others connect to your existing DVR or NVR and add intelligent detection without replacing your camera infrastructure. Cyrano, for example, connects via HDMI to your existing recorder and runs AI analysis on the video output. This means you keep your current cameras, storage, and recording setup. The AI layer handles detection and alerting while your NVR continues to handle what it does best: recording and playback. This approach avoids the codec and storage headaches entirely for the monitoring layer, since the NVR handles all of that independently.
The right choice depends on your situation. If you are running a homelab and enjoy the process of optimizing your setup, self-hosted Frigate with go2rtc is genuinely excellent software. If you need cameras to be a tool that works without intervention, managed or hybrid approaches save real time.
4. Codec and stream configuration best practices
Regardless of your NVR platform, following these stream configuration practices will prevent most playback issues:
Camera stream setup
- Main stream (for recording): h264 High profile, 1080p or higher resolution, 2048 to 4096 kbps CBR (constant bitrate). CBR is more predictable for storage planning than VBR. Avoid h265 unless all of your playback clients support it natively.
- Sub stream (for detection/live view): h264 or MJPEG, 640x480 or 720p, 512 to 1024 kbps. This stream feeds your AI detection and live preview. Lower resolution is fine because object detection models typically downscale to 320x320 anyway.
- Frame rate: 15 fps is sufficient for both recording and detection in security applications. 30 fps doubles your storage without meaningfully improving forensic value for most scenes. If you need smooth motion (tracking fast-moving vehicles, for example), 20 fps is a reasonable compromise.
- Keyframe interval (GOP): Set to 2x the frame rate (so every 2 seconds). A keyframe interval of 30 at 15 fps means a keyframe every 2 seconds. This is important for seek accuracy in playback. Longer GOP intervals mean less accurate seeking and potential artifacts when jumping to a specific timestamp.
go2rtc as a universal stream broker
go2rtc has become the standard restreaming layer for Frigate and other self-hosted NVR platforms. It solves several problems at once: it maintains a single RTSP connection to each camera (reducing camera CPU load), it can transcode between codecs, and it provides WebRTC and MSE playback endpoints that work reliably in browsers.
Key go2rtc configuration tips for reliable playback:
- Always use RTSP over TCP (
rtsp://...#tcp) instead of UDP. UDP streams drop packets on congested networks and produce artifacts. TCP retransmits lost packets, which occasionally adds latency but ensures clean frames. - If your camera sends h265 and you need browser playback, use the ffmpeg source with hardware transcoding:
ffmpeg:rtsp://...#video=h264#hardware=vaapi - For cameras that disconnect frequently, add the
reconnecttimeout:rtsp://...#timeout=30 - Use the go2rtc web UI (port 1984 by default) to verify stream health. The "streams" page shows active connections, codec info, bitrate, and consumer count. If a stream shows "no consumers" but you expect one, your Frigate configuration likely has a path mismatch.
RTSP vs. ONVIF vs. MJPEG: which protocol to use
RTSP is the standard protocol for IP camera video streams and should be your default choice. It supports h264 and h265, provides consistent framing, and works with every NVR platform. ONVIF is a device management protocol (for PTZ control, event subscriptions, and device discovery) that typically exposes RTSP URLs for video. Use ONVIF for initial camera setup and discovery, then configure RTSP URLs directly in your NVR for reliability.
MJPEG should be a last resort. It is bandwidth-inefficient (5x to 10x more bandwidth than h264 at equivalent quality), does not support audio, and puts high CPU load on the camera. The only scenario where MJPEG makes sense is with legacy cameras that have no RTSP support, or for very low-resolution snapshots used purely for detection.
5. When DIY NVR hits its limits for property security
There is a threshold where self-hosted NVR setups transition from "capable home security" to "operational liability." That threshold is different for everyone, but there are common signs:
- Playback fails during the incident that matters most. You had an actual security event, went to pull the clip, and the recording was corrupted, overwritten, or encoded in a format your phone cannot play. When security footage is needed for a police report or insurance claim and it is not there, the entire system has failed at its primary purpose.
- You are spending more time maintaining than monitoring.If camera firmware updates, ffmpeg version compatibility, disk space alerts, and go2rtc configuration changes consume hours every month, the "free" NVR software is costing you real money in time.
- Multiple properties or stakeholders. A single Frigate instance works well for one location. Managing five apartment buildings, each with 8+ cameras, using self-hosted NVR across separate networks, introduces exponential complexity. Each site needs independent monitoring, storage, updates, and troubleshooting.
- Accountability requirements. Property managers, HOAs, and commercial tenants increasingly expect documented security coverage with audit trails. A Frigate dashboard is hard to share with non-technical stakeholders. They want a phone notification with a screenshot and a clear description of what happened, not a link to a self-hosted web UI that requires VPN access.
None of this means self-hosted NVR is wrong. For single-site residential use, Frigate running on a Raspberry Pi or Intel NUC with a Coral TPU is one of the best security camera setups available at any price point. The detection accuracy is excellent, the community is active, and the privacy benefits are real.
But when security cameras transition from "hobby project" to "business requirement," reliability becomes non-negotiable. That is the point where either investing heavily in redundant self-hosted infrastructure or moving to a managed solution makes sense. The cost of a managed system looks different when compared against the cost of a missed incident or a week spent rebuilding a failed NVR server.
Whatever path you choose, the fundamentals in this guide (h264 for recording, proper retention math, RTSP over TCP, go2rtc as your stream broker) will serve you well. Get the codec and storage basics right, and 90% of playback issues disappear before they start.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.