cool-lizard-26153
12/31/2025, 7:29 AMtall-airline-16756
12/31/2025, 7:30 AMtall-airline-16756
12/31/2025, 7:30 AMcool-lizard-26153
12/31/2025, 7:31 AMtall-airline-16756
12/31/2025, 7:31 AMcool-lizard-26153
12/31/2025, 7:35 AMtall-airline-16756
12/31/2025, 7:35 AMrtc.AudioStream.
• Compute a lightweight audio-energy metric per frame (RMS → dB) and/or SNR estimate.
• Create OpenTelemetry metrics (histogram for distribution, gauge or counter for samples).
• Record metrics with attributes like participant_id, track_id, bvc (raw/processed).
• Export via OTLP exporter (or your chosen backend).
2) OTEL setup (minimal)
• Install opentelemetry packages and exporter you want (OTLP, Prometheus, etc.).
• Create MeterProvider and a Meter, register an exporter/reader.
Example (conceptual snippets — adapt keys/endpoints):
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
exporter = OTLPMetricExporter(endpoint="<https://your-otlp-endpoint>", headers={"Authorization":"Bearer ..."})
reader = PeriodicExportingMetricReader(exporter, export_interval_millis=5000)
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)
meter = provider.get_meter("livekit.audio", "1.0")
3) Metrics to create
• Histogram audio.energy_db — records RMS level in dB (useful distribution).
• Histogram audio.snr_db — if you compute SNR.
• Counter audio.frames_processed — count frames analyzed.
energy_hist = meter.create_histogram("audio.energy_db", description="Frame RMS in dB", unit="dB")
snr_hist = meter.create_histogram("audio.snr_db", description="Estimated SNR in dB", unit="dB")
frames_counter = meter.create_counter("audio.frames_processed")
4) Lightweight audio analysis
• Use RMS for energy. For SNR estimate you need a noise floor sample or simple heuristic (energy of non-speech segments).
• Keep processing cheap (frame-level or short-buffered).
import numpy as np
def rms_db(frame_bytes):
# assume 16-bit PCM, mono for simplicity
arr = np.frombuffer(frame_bytes, dtype=np.int16).astype(np.float32)
rms = np.sqrt(np.mean(arr*arr))
return 20.0 * np.log10(rms + 1e-10)
For SNR you can:
• Track a running noise floor during silence (VAD helps), then compute snr_db = signal_db - noise_db.
• Or compute simple percentile-based noise floor across a sliding window.
5) Hook into LiveKit agent audio
• Use rtc.AudioStream(track) to iterate frames.
• For each frame compute energy_db (and snr_db if available).
• Record metrics with attributes to distinguish raw vs processed.
async def monitor_track(track, bvc_label):
stream = rtc.AudioStream(track)
async for frame in stream:
db = rms_db(frame.data)
energy_hist.record(db, {"track_id": track.sid, "bvc": bvc_label})
frames_counter.add(1, {"track_id": track.sid, "bvc": bvc_label})
# optional: compute SNR and record snr_hist.record(snr_db, {...})
6) Correlating pre/post BVC
• If client can send both raw and BVC-processed audio (two tracks), use same attributes (participant, timestamp window) to compare distributions.
• If you only have post-BVC on server, ask clients to optionally publish a raw audio track or periodically send short raw samples for comparison.
7) Practical tips
• Use histograms for distribution (median, p95) rather than only averages.
• Tag metrics with participant_id, track_id, direction (`inbound`/`outbound`), bvc: raw|processed.
• Sample frames (e.g., 1 of N) if volume is high to reduce CPU.
• Buffer a few frames if you need windowed SNR or voice activity detection (VAD).
• Keep heavy DSP off the critical path; use a worker thread/queue if processing slows audio handling.
8) If you can’t get raw audio to server
• Option A: Update clients to publish a second "raw" track (muted for media) solely for analysis.
• Option B: Have clients compute and export a small set of metrics locally (client-side OTLP or POST) and send those to your telemetry backend.
If you want, I can:
• Provide a complete copy-pasteable Python agent example that wires this end-to-end (OTLP exporter config + agent + monitor loop) for your environment.
• Or show how to implement simple VAD-based noise-floor tracking to compute SNR.
Which would you like next?
Sources: Capturing the First Few Seconds of a Call for Processing | Creating and Publishing Custom Metrics | Examples | livekit/livekit_composite | DeepWiki | https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal/signup|