Skip to content

Embed wall-clock timestamps in exported MP4s as a mov_text subtitle track #4761

@connortechnology

Description

@connortechnology

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions