Files
zoneminder/db/zm_update-1.39.35.sql
T
Isaac ConnorandClaude Opus 5 4619258293 feat: measure the audio level whatever AudioDetection is set to
Gating the measurement on AudioDetection made the graph useless for the job
it is most wanted for. AudioThreshold is a per-device number -- the floor on
one camera's mic is nothing like another's -- so it has to be measured before
it can be set, but nothing was measured until it was already set. Enabling
detection with a guessed threshold to find out what the real one should be is
backwards.

The level is now read for every monitor with decodable audio.  AudioDetection
governs only whether crossing the threshold contributes a score, which is
what the setting is named for. shared_data->audio_alarm stays 0 when it is
off, so nothing downstream changes for a monitor that does not want audio
alarms.

Nothing here depends on Analysing either. The measurement is in
Monitor::Capture, which runs on whatever Analysing is set to, and frame rows
come from Event::AddFrame, which a continuously recording monitor reaches
through the RECORDING_ALWAYS path with motion detection off. So a monitor
that only records continuously still gets levels on its rows.

Since Monitor::Capture retries Open on every audio packet until it succeeds,
and that now happens for every monitor with audio rather than the handful with
detection on, AudioDetector remembers a codec it has already failed to find a
decoder for. Without it a stream ZoneMinder cannot decode logs a warning at
the audio packet rate for as long as the monitor runs. A reconnect bringing a
different codec is still tried.

The cost is one audio decode per monitor with audio, where before it was one
per monitor with detection enabled. That is small next to the video path, but
it is not nothing on a box with many cameras.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JpiSWBmtQkR5bcgpHWY4ME
2026-09-20 18:17:44 -05:00

45 lines
1.9 KiB
SQL

--
-- This updates a 1.39.34 database to 1.39.35
--
-- Add Frames.AudioLevel so the event view can graph how loud a monitor was
-- alongside how much it moved.
--
-- zm_update-1.39.31.sql gave Monitors the audio detection settings, but the
-- level itself only ever existed in shared memory, which means it is gone the
-- moment the frame passes. Score has always been persisted per frame; this is
-- the audio equivalent, on the same 0-100 dBFS-derived scale the threshold
-- uses, so the two can share an axis.
--
-- The stored value is the peak since the previous Frames row rather than the
-- level at the instant the row was written. Rows are written well below the
-- capture rate -- only alarm, bulk and score-increasing frames get one -- so
-- sampling at write time would drop exactly the short loud noises that matter
-- on a surveillance timeline.
--
-- The level is measured whenever the monitor has decodable audio, not only
-- when AudioDetection is on. A threshold cannot be chosen without first seeing
-- what the device's floor and peaks are, so the setting governs only whether
-- crossing the threshold scores, never whether the level is recorded.
--
-- 0 therefore means silence, no audio stream, or a codec with no decoder. It
-- is also what every pre-existing row gets. The graph treats an all-zero
-- series as "no audio data" and draws no line, so backfilled rows do not
-- appear as a flat line along the bottom claiming silence was measured.
--
SELECT 'Checking for AudioLevel in Frames';
SET @s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Frames'
AND table_schema = DATABASE()
AND column_name = 'AudioLevel'
) > 0,
"SELECT 'Column AudioLevel already exists in Frames'",
"ALTER TABLE `Frames` ADD COLUMN `AudioLevel` tinyint(3) unsigned NOT NULL default '0' AFTER `Score`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;