mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-05 10:45:21 +03:00
Expose dBFS when doing audio analysis
This commit is contained in:
parent
ba3c7f59e5
commit
39a33f6143
@ -259,6 +259,7 @@ class FrigateApp:
|
|||||||
self.onvif_controller,
|
self.onvif_controller,
|
||||||
self.external_event_processor,
|
self.external_event_processor,
|
||||||
self.plus_api,
|
self.plus_api,
|
||||||
|
self.dispatcher,
|
||||||
)
|
)
|
||||||
|
|
||||||
def init_onvif(self) -> None:
|
def init_onvif(self) -> None:
|
||||||
|
|||||||
@ -167,9 +167,22 @@ class AudioEventMaintainer(threading.Thread):
|
|||||||
if not self.feature_metrics[self.config.name]["audio_enabled"].value:
|
if not self.feature_metrics[self.config.name]["audio_enabled"].value:
|
||||||
return
|
return
|
||||||
|
|
||||||
waveform = (audio / AUDIO_MAX_BIT_RANGE).astype(np.float32)
|
audio_as_float = audio.astype(np.float32)
|
||||||
|
waveform = audio_as_float / AUDIO_MAX_BIT_RANGE
|
||||||
model_detections = self.detector.detect(waveform)
|
model_detections = self.detector.detect(waveform)
|
||||||
|
|
||||||
|
# Calculate RMS (Root-Mean-Square) which represents the average signal amplitude
|
||||||
|
# Note: np.float32 isn't serializable, we must use np.float64 to publish the message
|
||||||
|
rms = np.sqrt(np.mean(np.absolute(audio_as_float**2))).astype(np.float64)
|
||||||
|
|
||||||
|
# Transform RMS to dBFS (decibels relative to full scale)
|
||||||
|
dBFS = 20 * np.log10(np.abs(rms) / AUDIO_MAX_BIT_RANGE)
|
||||||
|
|
||||||
|
requests.post(
|
||||||
|
f"http://127.0.0.1:5000/api/{self.config.name}/metadata",
|
||||||
|
json={"dBFS": dBFS, "rms": rms},
|
||||||
|
)
|
||||||
|
|
||||||
for label, score, _ in model_detections:
|
for label, score, _ in model_detections:
|
||||||
if label not in self.config.audio.listen:
|
if label not in self.config.audio.listen:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -28,6 +28,7 @@ from peewee import DoesNotExist, SqliteDatabase, fn, operator
|
|||||||
from playhouse.shortcuts import model_to_dict
|
from playhouse.shortcuts import model_to_dict
|
||||||
from tzlocal import get_localzone_name
|
from tzlocal import get_localzone_name
|
||||||
|
|
||||||
|
from frigate.comms.dispatcher import Dispatcher
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
from frigate.const import CLIPS_DIR, MAX_SEGMENT_DURATION, RECORD_DIR
|
from frigate.const import CLIPS_DIR, MAX_SEGMENT_DURATION, RECORD_DIR
|
||||||
from frigate.events.external import ExternalEventProcessor
|
from frigate.events.external import ExternalEventProcessor
|
||||||
@ -61,6 +62,7 @@ def create_app(
|
|||||||
onvif: OnvifController,
|
onvif: OnvifController,
|
||||||
external_processor: ExternalEventProcessor,
|
external_processor: ExternalEventProcessor,
|
||||||
plus_api: PlusApi,
|
plus_api: PlusApi,
|
||||||
|
dispatcher: Dispatcher,
|
||||||
):
|
):
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@ -81,6 +83,7 @@ def create_app(
|
|||||||
app.onvif = onvif
|
app.onvif = onvif
|
||||||
app.external_processor = external_processor
|
app.external_processor = external_processor
|
||||||
app.plus_api = plus_api
|
app.plus_api = plus_api
|
||||||
|
app.dispatcher = dispatcher
|
||||||
app.camera_error_image = None
|
app.camera_error_image = None
|
||||||
app.hwaccel_errors = []
|
app.hwaccel_errors = []
|
||||||
|
|
||||||
@ -1396,6 +1399,38 @@ def recording_clip(camera_name, start_ts, end_ts):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/<camera_name>/metadata", methods=["POST"])
|
||||||
|
def create_metadata_message(camera_name):
|
||||||
|
if not camera_name or not current_app.frigate_config.cameras.get(camera_name):
|
||||||
|
return jsonify(
|
||||||
|
{"success": False, "message": f"{camera_name} is not a valid camera."}, 404
|
||||||
|
)
|
||||||
|
|
||||||
|
request_json = request.get_json(silent=True)
|
||||||
|
if request_json == {}:
|
||||||
|
return jsonify(
|
||||||
|
{"success": False, "message": "Metadata json cannot be empty."}, 404
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
current_app.dispatcher.publish(
|
||||||
|
"metadata", json.dumps(request_json), retain=False
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"The error is {e}")
|
||||||
|
return jsonify(
|
||||||
|
{"success": False, "message": f"An unknown error occurred: {e}"}, 404
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify(
|
||||||
|
{
|
||||||
|
"success": True,
|
||||||
|
"message": "Successfully published metadata message.",
|
||||||
|
},
|
||||||
|
200,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/vod/<camera_name>/start/<int:start_ts>/end/<int:end_ts>")
|
@bp.route("/vod/<camera_name>/start/<int:start_ts>/end/<int:end_ts>")
|
||||||
@bp.route("/vod/<camera_name>/start/<float:start_ts>/end/<float:end_ts>")
|
@bp.route("/vod/<camera_name>/start/<float:start_ts>/end/<float:end_ts>")
|
||||||
def vod_ts(camera_name, start_ts, end_ts):
|
def vod_ts(camera_name, start_ts, end_ts):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user