mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-11-07 21:23:02 -05:00
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
45 lines
1.9 KiB
SQL
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;
|