Compare commits

...
1 Commits
Author SHA1 Message Date
Gleb NikiforovandGitHub 4f03480afd Fix audio worker startup after enabling a disabled camera (#24806)
CI / AMD64 Build (push) Waiting to run
CI / AMD64 Smoke Test (push) Blocked by required conditions
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
* Fix audio worker startup after enabling a disabled camera

* Document audio lifecycle test helpers

* Focus audio startup coverage on the enabled update regression
2026-10-26 17:44:48 -05:00
2 changed files with 38 additions and 1 deletions
+1
View File
@@ -178,6 +178,7 @@ class AudioProcessor(FrigateProcess):
[ [
CameraConfigUpdateEnum.add, CameraConfigUpdateEnum.add,
CameraConfigUpdateEnum.audio, CameraConfigUpdateEnum.audio,
CameraConfigUpdateEnum.enabled,
CameraConfigUpdateEnum.ffmpeg, CameraConfigUpdateEnum.ffmpeg,
CameraConfigUpdateEnum.remove, CameraConfigUpdateEnum.remove,
], ],
+37 -1
View File
@@ -1,4 +1,4 @@
"""Tests for audio maintainer spawning on runtime camera adds.""" """Tests for audio maintainer spawning on runtime camera updates."""
import threading import threading
import unittest import unittest
@@ -42,6 +42,42 @@ class TestAudioSpawnIfNeeded(unittest.TestCase):
processor.logger = MagicMock() processor.logger = MagicMock()
return processor return processor
def test_initially_disabled_camera_spawns_after_enabled_update(self):
"""Consume an enabled update through the manager's real subscriber."""
config = _build_config()
config.cameras["front_door"].enabled = False
stop = MagicMock()
stop.wait.side_effect = [False, True]
processor = AudioProcessor(
config, {"front_door": MagicMock()}, MagicMock(), stop
)
processor.logger = MagicMock()
updates = iter([("config/cameras/front_door/enabled", True), (None, None)])
self.addCleanup(
setattr, threading.current_thread(), "name", threading.current_thread().name
)
with (
patch.object(processor, "pre_run_setup"),
patch("frigate.config.camera.updater.ConfigSubscriber") as transport,
patch("frigate.events.audio.AudioEventMaintainer") as maintainer,
):
def receive_update():
self.assertEqual(processor.audio_threads, {})
maintainer.assert_not_called()
return next(updates)
transport.return_value.check_for_update.side_effect = receive_update
maintainer.return_value.is_alive.return_value = False
processor.run()
self.assertEqual(
processor.audio_threads, {"front_door": maintainer.return_value}
)
maintainer.assert_called_once()
maintainer.return_value.start.assert_called_once()
def test_skips_camera_whose_metrics_have_not_been_created_yet(self): def test_skips_camera_whose_metrics_have_not_been_created_yet(self):
"""The camera maintainer creates metrics on its own poll of the add """The camera maintainer creates metrics on its own poll of the add
update, so the audio processor can see the camera first.""" update, so the audio processor can see the camera first."""