In the otel metrics that livekit is exporting, is ...
# ask-ai
c
In the otel metrics that livekit is exporting, is there a way to get bvc parameters? Like how much of a noise is cut off? or what text is removed by bvc?
t
Thanks for reaching out, Bharath. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — you're asking whether LiveKit's OpenTelemetry (otel) metrics expose BVC (background voice cancellation) parameters like how much noise is removed or what "text" is removed. Short answer: LiveKit's otel metrics do not expose BVC-specific internals. • There is no metric reporting the magnitude of noise reduction or spectral suppression from BVC. • BVC processes audio; it does not remove or alter text, so there is no "text removed" data to report. What metrics are available: LiveKit exports observability metrics for media pipeline and components such as VAD, STT, TTS, LLM, latency, and other performance signals — but not low-level BVC filter parameters. If you need deeper insight, two practical alternatives: • Capture and compare audio before and after BVC (automated A/B analysis) to quantify noise reduction. • Instrument your pipeline to emit custom metrics around audio energy/signal-to-noise before/after the BVC step and export those via otel. Which option sounds most useful for your use case, or do you want guidance on how to capture/emit those custom metrics? Sources: VAD Metrics | LiveKit docs | Agents (Python) | livekit/livekit_composite | DeepWiki | Streamline Troubleshooting with Agent Observability | https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal/signup| | TTS Metrics | LiveKit docs
c
the second sounds good. can you suggest how do I go about that?
t
Thanks — I'll help you instrument custom metrics to measure audio-energy or SNR before and after BVC and export them via OpenTelemetry. A couple quick clarifying questions before I give concrete snippets so I focus on the right integration: 1. Where do you control the BVC step in your deployment — on the client (browser/mobile) or on a server/agent in your media path? 2. Which runtime/language are you using for that component (e.g., JavaScript/TypeScript in browser or Node, Python, Go, or another language on server)? If you prefer, I can give both a browser/JS and a server/Go example — say which one you'd like first.
c
I'm doing on server/agent end and my sdk is python
t
Thanks — I’ll walk you through a focused, server-side (agent) Python approach to emit custom OpenTelemetry metrics that let you compare audio energy / SNR before vs after BVC. I’ll assume you can access two streams (raw + post-BVC) — if you can’t, see note below about how to get raw audio from the client. 1) High-level steps • Capture audio frames for the raw and processed tracks using
rtc.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):
Copy code
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.
Copy code
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).
Copy code
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.
Copy code
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|