Problem
When ZoneMinder exports several events as a single concatenated MP4 (the "merged download" path in web/includes/download_functions.php), the only record of the original capture time is the OSD timestamp burned into the pixels. The H.264 bitstream metadata carries nothing useful:
- No SEI user data on any frame
- No per-frame tags
- No subtitle/text/data stream
- No chapter markers
- PTS is monotonic and uniform across event boundaries, with no wall-clock anchor
Recovering the capture time of a given frame currently requires OCRing the burned-in timestamp.
Proposal
Add an opt-in config option ZM_OPT_EXPORT_TIMESTAMP_TRACK (default no). When enabled, the merged-export ffmpeg invocation writes a WebVTT file with one cue per second of footage, where each cue's text is the wall-clock StartDateTime + offset of the source event for that second, then muxes it into the output MP4 as a mov_text subtitle stream alongside the existing -c copy video/audio. Also stamps -metadata creation_time with the earliest event start (UTC ISO-8601).
Off behavior is byte-identical to today.
Why a subtitle track
- Standard MP4 subtitle stream — readable by
ffprobe -show_streams and extractable with ffmpeg -map 0:s -f srt - without re-encoding video.
- Survives
-c copy concat without touching the video stream.
- Per-second granularity matches the resolution of the burned-in OSD it replaces.
- Players that don't render subtitles play the file unchanged.
Tradeoffs / caveats
mov_text is rendered by VLC and Safari but ignored by Chrome's <video> element without an explicit <track>. The intended consumers here are programmatic tools that want timestamps without OCR, not viewers.
- For a 1-hour export the VTT track is ~3600 cues / a few hundred KB; negligible compared to the video payload.
- For events where
Length is null/0 (in-progress events), falls back to EndDateTime - StartDateTime. If both are unusable the event's cues are skipped with a debug log.
- New option won't be active until
zmupdate.pl syncs the new ConfigData entry to the DB, same as any other new config option.
Alternative considered
A sidecar .vtt file in the tar/zip archive is simpler but only helps the archive-format download — not the bare .mp4 (noArchive) case, which is the case the original investigation was about.
Problem
When ZoneMinder exports several events as a single concatenated MP4 (the "merged download" path in
web/includes/download_functions.php), the only record of the original capture time is the OSD timestamp burned into the pixels. The H.264 bitstream metadata carries nothing useful:Recovering the capture time of a given frame currently requires OCRing the burned-in timestamp.
Proposal
Add an opt-in config option
ZM_OPT_EXPORT_TIMESTAMP_TRACK(defaultno). When enabled, the merged-export ffmpeg invocation writes a WebVTT file with one cue per second of footage, where each cue's text is the wall-clockStartDateTime + offsetof the source event for that second, then muxes it into the output MP4 as amov_textsubtitle stream alongside the existing-c copyvideo/audio. Also stamps-metadata creation_timewith the earliest event start (UTC ISO-8601).Off behavior is byte-identical to today.
Why a subtitle track
ffprobe -show_streamsand extractable withffmpeg -map 0:s -f srt -without re-encoding video.-c copyconcat without touching the video stream.Tradeoffs / caveats
mov_textis rendered by VLC and Safari but ignored by Chrome's<video>element without an explicit<track>. The intended consumers here are programmatic tools that want timestamps without OCR, not viewers.Lengthis null/0 (in-progress events), falls back toEndDateTime - StartDateTime. If both are unusable the event's cues are skipped with a debug log.zmupdate.plsyncs the new ConfigData entry to the DB, same as any other new config option.Alternative considered
A sidecar
.vttfile in the tar/zip archive is simpler but only helps the archive-format download — not the bare.mp4(noArchive) case, which is the case the original investigation was about.