修复 Pipecat 实时链路并补齐网页测试
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
"""传输适配层的无硬件回归测试。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import tempfile
|
||||
import time
|
||||
import wave
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from av import AudioFrame
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from client.test_client import FileAudioTrack, ReplyRecorder
|
||||
from services.bot_server import SimpleVAD
|
||||
|
||||
|
||||
def _write_test_wav(path: Path) -> None:
|
||||
samples = np.ones(1600, dtype=np.int16) * 1000 # 100ms 语音
|
||||
with wave.open(str(path), "wb") as output:
|
||||
output.setnchannels(1)
|
||||
output.setsampwidth(2)
|
||||
output.setframerate(16000)
|
||||
output.writeframes(samples.tobytes())
|
||||
|
||||
|
||||
async def test_file_track_clock() -> None:
|
||||
with tempfile.TemporaryDirectory(prefix="transport_test_") as directory:
|
||||
path = Path(directory) / "input.wav"
|
||||
_write_test_wav(path)
|
||||
track = FileAudioTrack(path, tail_silence_s=0.8)
|
||||
track._t0 = time.perf_counter() - 10 # 测试不需要真实等待
|
||||
pts = []
|
||||
while not track.finished:
|
||||
pts.append((await track.recv()).pts)
|
||||
|
||||
assert len(pts) == 90, len(pts) # 100ms 音频 + 800ms 静音
|
||||
assert all(after > before for before, after in zip(pts, pts[1:])), pts[-5:]
|
||||
|
||||
|
||||
def test_vad_tail_silence() -> None:
|
||||
vad = SimpleVAD()
|
||||
events = [vad.feed(np.ones(320, dtype=np.int16) * 1000, 20) for _ in range(20)]
|
||||
events += [vad.feed(np.zeros(320, dtype=np.int16), 20) for _ in range(40)]
|
||||
assert "end" in events
|
||||
|
||||
|
||||
def test_reply_requires_non_silent_audio() -> None:
|
||||
recorder = ReplyRecorder(Path("/tmp/unused-transport-test.wav"))
|
||||
silence = AudioFrame(format="s16", layout="mono", samples=320)
|
||||
silence.planes[0].update(np.zeros(320, dtype=np.int16).tobytes())
|
||||
silence.sample_rate = 48000
|
||||
recorder.feed(silence)
|
||||
assert not recorder.has_speech
|
||||
assert recorder.sample_rate == 48000
|
||||
|
||||
speech = AudioFrame(format="s16", layout="mono", samples=320)
|
||||
speech.planes[0].update((np.ones(320, dtype=np.int16) * 500).tobytes())
|
||||
speech.sample_rate = 48000
|
||||
recorder.feed(speech)
|
||||
assert recorder.has_speech
|
||||
|
||||
|
||||
async def main() -> int:
|
||||
await test_file_track_clock()
|
||||
test_vad_tail_silence()
|
||||
test_reply_requires_non_silent_audio()
|
||||
print("传输适配层回归测试:3/3 PASS")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(asyncio.run(main()))
|
||||
Reference in New Issue
Block a user