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.external_event_processor,
|
||||
self.plus_api,
|
||||
self.dispatcher,
|
||||
)
|
||||
|
||||
def init_onvif(self) -> None:
|
||||
|
||||
@ -167,9 +167,22 @@ class AudioEventMaintainer(threading.Thread):
|
||||
if not self.feature_metrics[self.config.name]["audio_enabled"].value:
|
||||
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)
|
||||
|
||||
# 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:
|
||||
if label not in self.config.audio.listen:
|
||||
continue
|
||||
|
||||
@ -28,6 +28,7 @@ from peewee import DoesNotExist, SqliteDatabase, fn, operator
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from tzlocal import get_localzone_name
|
||||
|
||||
from frigate.comms.dispatcher import Dispatcher
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.const import CLIPS_DIR, MAX_SEGMENT_DURATION, RECORD_DIR
|
||||
from frigate.events.external import ExternalEventProcessor
|
||||
@ -61,6 +62,7 @@ def create_app(
|
||||
onvif: OnvifController,
|
||||
external_processor: ExternalEventProcessor,
|
||||
plus_api: PlusApi,
|
||||
dispatcher: Dispatcher,
|
||||
):
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -81,6 +83,7 @@ def create_app(
|
||||
app.onvif = onvif
|
||||
app.external_processor = external_processor
|
||||
app.plus_api = plus_api
|
||||
app.dispatcher = dispatcher
|
||||
app.camera_error_image = None
|
||||
app.hwaccel_errors = []
|
||||
|
||||
@ -1396,6 +1399,38 @@ def recording_clip(camera_name, start_ts, end_ts):
|
||||
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/<float:start_ts>/end/<float:end_ts>")
|
||||
def vod_ts(camera_name, start_ts, end_ts):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user