- /api/recordings no longer lists rec_*.part.mp4 files: FFmpeg has not
written the moov atom yet, so they can never play. The in-progress
segment was always the newest entry at the top of the list.
- Record new segments with -movflags +faststart so the MP4 index is at
the front. iOS/Safari otherwise tail-seeks the moov and stalls.
- Add playsinline to the playback video for inline iOS playback.
- Add scripts/remux-faststart.sh to convert the existing archive
(dry-run by default, atomic, preserves mtime for retention).
A power cut makes the recordings drive's fsck slow, so the mount can
appear tens of seconds after nextnvr starts. The recorders then hit the
unmounted, root-owned mountpoint, failed mkdir, and exited permanently —
recording stayed dead until a manual restart.
- recorder: on mkdir failure, log and retry every 15s instead of exiting,
so recording resumes once storage returns
- storage: add waitForStorage() and call it before the writers start, so
startup waits (up to 120s) for the recordings dir to be present and
writable; live view still starts if storage never appears
Detect a disconnected or read-only recordings drive and surface it
without stopping recording or live view:
- storage.go: probe path existence, mount point, writability and free
space every 30s; capture mount expectation at startup so a clean
unmount (writes falling through to root fs) is also caught
- GET /api/storage endpoint; storage fields in /api/status
- red UI banner while storage is unavailable
- log ALERT on loss, OK on recovery
A stalled RTSP stream (TCP connection alive but no data) made the recorder's ffmpeg processes block forever on read(). The -t 300 flag only bounds by input timestamps, not wall-clock, so it never fired and the recorder loop never started the next segment.
Add -rw_timeout (10s socket I/O timeout) so ffmpeg exits on a stalled stream and the existing retry loop reconnects automatically.