Skip to content

Commit 078f974

Browse files
authored
fix: correct error handling in process_reverse_stream (#588)
1 parent 6ab39ac commit 078f974

2 files changed

Lines changed: 62 additions & 2 deletions

File tree

livekit-rtc/livekit/rtc/apm.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ def process_reverse_stream(self, data: AudioFrame) -> None:
9090

9191
resp = FfiClient.instance.request(req)
9292

93-
if resp.apm_process_stream.error:
94-
raise RuntimeError(resp.apm_process_stream.error)
93+
if resp.apm_process_reverse_stream.error:
94+
raise RuntimeError(resp.apm_process_reverse_stream.error)
9595

9696
def set_stream_delay_ms(self, delay_ms: int) -> None:
9797
"""

tests/rtc/test_agc.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import os
2+
import wave
3+
import numpy as np
4+
5+
from livekit.rtc import AudioProcessingModule, AudioFrame
6+
7+
FIXTURES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures")
8+
9+
10+
def test_agc_modifies_audio():
11+
num_channels = 1
12+
13+
input_wav = os.path.join(FIXTURES_DIR, "test_audio.wav")
14+
output_wav = os.path.join(FIXTURES_DIR, "test_processed.wav")
15+
16+
apm = AudioProcessingModule(auto_gain_control=True)
17+
18+
any_frame_modified = False
19+
20+
with wave.open(input_wav, "rb") as wf_in:
21+
assert wf_in.getnchannels() == num_channels, "Input file must be mono."
22+
sample_rate = wf_in.getframerate()
23+
sampwidth = wf_in.getsampwidth()
24+
frames_per_chunk = sample_rate // 100
25+
26+
with wave.open(output_wav, "wb") as wf_out:
27+
wf_out.setnchannels(num_channels)
28+
wf_out.setsampwidth(sampwidth)
29+
wf_out.setframerate(sample_rate)
30+
31+
while True:
32+
raw_bytes = wf_in.readframes(frames_per_chunk)
33+
if not raw_bytes:
34+
break
35+
36+
data = np.frombuffer(raw_bytes, dtype=np.int16)
37+
if len(data) < frames_per_chunk:
38+
data = np.pad(data, (0, frames_per_chunk - len(data)))
39+
40+
original = data.copy()
41+
42+
frame = AudioFrame(
43+
data=data.tobytes(),
44+
sample_rate=sample_rate,
45+
num_channels=num_channels,
46+
samples_per_channel=frames_per_chunk,
47+
)
48+
49+
apm.process_stream(frame)
50+
51+
processed = np.frombuffer(frame.data, dtype=np.int16)
52+
if not np.array_equal(original, processed):
53+
any_frame_modified = True
54+
55+
wf_out.writeframes(frame.data.tobytes())
56+
57+
assert any_frame_modified, (
58+
"APM did not modify any audio frames — processing may be a no-op. "
59+
"With AGC enabled, output should differ from input."
60+
)

0 commit comments

Comments
 (0)