mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-09-12 21:27:39 -04:00
ZoneMinder has carried audio for years without ever listening to it: the packets go into the event and nothing reads them. AudioDetector decodes them in the capture thread and reports a 0-100 level, which Analyse() turns into score alongside motion, ONVIF and Amcrest. The level is dBFS-derived, not a raw amplitude ratio. Linear RMS is unusable as a setting: ordinary speech sits at 1-3% of full scale, so every sound worth catching would be crammed into the bottom two points of the range and no operator could tune it. Mapping -60..0 dBFS onto 0..100 puts speech around 43 instead. Three columns on Monitors: AudioDetection to enable it, AudioThreshold for the level to alarm at, and AudioAlarmScore for what it contributes. AudioAlarmScore defaults to 9, matching what an ONVIF or Amcrest alarm already adds. A threshold of 0 means off, so enabling detection without choosing a threshold cannot alarm on silence -- a plain level >= threshold test would alarm on every packet in that state. The level and the alarm flag go in SharedData's two spare bytes, renamed from reserved1/reserved2. Offsets and sizes are unchanged, so the 888-byte cross-process layout and the Memory.pm and Monitor.php offset tables all still agree; the readers are renamed in the same commit so the level is available to the web UI. The decoder is opened lazily on the first audio packet rather than at camera setup, so a monitor with detection off never carries one and a stream that gains audio on reconnect still gets picked up. Scoring reads the capture thread's most recent level rather than scoring per audio packet, because the score belongs to a video frame and audio packets do not arrive in step with them. Tested: 242 assertions over the pure helpers - the RMS of both sample formats, the dB scale's monotonicity and endpoints, full-scale clamping of decoder overshoot, and the threshold-0 case. The repo's Catch2 harness needs v3 and only v2 is installed here, so tests/zm_audio_detector.cpp was compiled against a v2 shim to check it, and an identical set of assertions was run standalone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UvTCzCbvGt8xKQRNCSA7o8