chilly-microphone-36803
02/16/2026, 9:02 PMtall-airline-16756
02/16/2026, 9:02 PMtall-airline-16756
02/16/2026, 9:02 PMstt_node (a pipeline node/override in a custom Agent), apply EQ or other DSP (noise reduction, gain, filtering), then pass the processed PCM audio on to the STT implementation.
What this looks like in practice
• Intercept raw audio frames (e.g., rtc.AudioFrame) inside your Agent’s stt_node handler.
• Run an equalization filter or other DSP on the raw PCM data. You can use any DSP library available in your runtime (Node, Python, etc.) to implement filters (parametric EQ, shelving, bandpass, etc.).
• Forward the modified audio to the STT step (the pipeline will then send it to the chosen STT service).
Things to consider
• Real-time constraints: apply lightweight/streaming DSP so latency stays low.
• Sample rate / channel layout: ensure your EQ code preserves the sample rate and channel format expected by the STT model (resample or downmix if needed).
• Gain and clipping: watch overall levels to avoid clipping after boosting frequencies.
• CPU cost: heavier EQ or complex filters increase CPU usage—test under target load.
If you want, I can help with next steps:
• Suggest specific DSP libraries for your runtime (Node/Python) and example filter code.
• Show a small pseudo-code snippet of where to place EQ processing inside stt_node.
• Help verify sample rate/channel handling for your STT provider.
Which runtime are you using (Node or Python), and do you want a simple band‑pass/treble boost example or a parametric EQ?
Sources: Pipeline nodes and hooks | LiveKit Documentationchilly-microphone-36803
02/16/2026, 9:04 PMtall-airline-16756
02/16/2026, 9:04 PMstt_node override of a custom Agent.
What to do (high level)
• Override stt_node in your Agent to receive the incoming rtc.AudioStream.
• Convert each `rtc.AudioFrame`’s raw PCM bytes into a numpy array.
• Apply EQ/DSP to the PCM samples (bandpass, shelving, parametric EQ, gain, etc.).
• Convert processed samples back to bytes and yield new rtc.AudioFrame objects into the STT pipeline.
• Ensure sample rate, channel count, and format match what your STT provider expects.
Minimal Python outline (conceptual)
1. Convert frame data to numpy (int16 -> float32) for processing.
2. Apply filters (example uses a Butterworth bandpass to emphasize speech).
3. Clip and convert back to int16.
4. Yield a new rtc.AudioFrame into the downstream STT node.
Example skeleton (you can adapt this directly)
import numpy as np
from scipy.signal import butter, lfilter
from livekit.agents import Agent, stt, rtc
class EqualizedSTTAgent(Agent):
def __init__(self):
super().__init__()
self.sample_rate = 16000 # match your STT model
def _butter_bandpass_filter(self, data, lowcut, highcut, fs, order=6):
nyq = 0.5 * fs
b, a = butter(order, [lowcut/nyq, highcut/nyq], btype='band')
return lfilter(b, a, data)
async def stt_node(self, audio: rtc.AudioStream, model_settings: stt.ModelSettings):
async def processed_stream():
async for frame in audio:
# Convert to numpy float for DSP
samples = np.frombuffer(frame.data, dtype=np.int16).astype(np.float32)
# Example: emphasize speech band 300-3000 Hz
proc = self._butter_bandpass_filter(samples, 300.0, 3000.0, self.sample_rate)
# Optional: apply gain, normalization, or other EQ logic here
# Convert back to int16 safely
proc = np.clip(proc, -32768, 32767).astype(np.int16)
yield rtc.AudioFrame(
data=proc.tobytes(),
sample_rate=frame.sample_rate,
num_channels=frame.num_channels,
samples_per_channel=frame.samples_per_channel,
)
# Forward processed audio into the default STT node
async for event in Agent.default.stt_node(self, processed_stream(), model_settings):
yield event
Practical tips
• Latency: Use lightweight streaming-friendly filters. Higher filter orders and long FFT windows add latency.
• Sample rate and channels: Confirm STT expects mono or stereo and the sample rate (commonly 16 kHz for many STT models). Resample or downmix before STT if needed.
• Avoid clipping: After boosting frequencies, normalize or apply limiter to prevent clipping.
• CPU: Test CPU usage under realistic load—DSP cost can increase with more complex EQ.
• Libraries: For simple filters use scipy.signal. For more advanced/musical EQ consider pyroomacoustics, librosa (analysis-focused), or implement IIR biquad filters for efficiency.
• Testing: Compare STT transcripts before/after EQ with representative noisy audio to validate improvements.
If you want, I can:
• Provide a complete runnable example including session setup and AgentSession integration.
• Replace the bandpass example with a parametric multi-band EQ (biquad filters) and give presets for telephony or noisy rooms.
• Help verify correct sample rate/channel conversion for your STT provider — tell me which STT service you plan to use and whether your input is mono or stereo. Which of those would you like next? Sources: Capturing the First Few Seconds of a Call for Processing | Speech-to-text (STT) models overview | LiveKit Documentation