64 lines
2.1 KiB
Python
64 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Smoke tests for hermes_voice_gateway helper code.
|
|
|
|
These tests avoid live Hermes/STT/TTS calls. They verify the pieces that are
|
|
safe to exercise locally: content-type mapping, response MIME mapping, header
|
|
sanitization, fallback ACK WAV generation, and ffmpeg WAV normalization when
|
|
ffmpeg is available.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import tempfile
|
|
import wave
|
|
from pathlib import Path
|
|
|
|
from api_server_endpoint import (
|
|
audio_extension_for_content_type,
|
|
audio_response_mime,
|
|
convert_audio_to_esp32_wav,
|
|
make_ack_wav,
|
|
safe_audio_header,
|
|
)
|
|
|
|
|
|
def _assert_wav_16k_mono_s16(path: Path) -> None:
|
|
with wave.open(str(path), "rb") as wav:
|
|
assert wav.getnchannels() == 1, wav.getnchannels()
|
|
assert wav.getsampwidth() == 2, wav.getsampwidth()
|
|
assert wav.getframerate() == 16000, wav.getframerate()
|
|
assert wav.getnframes() > 0, wav.getnframes()
|
|
|
|
|
|
def main() -> None:
|
|
assert audio_extension_for_content_type("audio/wav") == ".wav"
|
|
assert audio_extension_for_content_type("audio/wav; charset=binary") == ".wav"
|
|
assert audio_extension_for_content_type("audio/webm") == ".webm"
|
|
assert audio_extension_for_content_type("application/unknown") == ".wav"
|
|
|
|
assert audio_response_mime("reply.wav") == "audio/wav"
|
|
assert audio_response_mime("reply.mp3") == "audio/mpeg"
|
|
assert audio_response_mime("reply.bin") == "application/octet-stream"
|
|
|
|
assert safe_audio_header("hello\nworld\r\x00!", 100) == "hello world !"
|
|
assert safe_audio_header("abcdef", 3) == "abc"
|
|
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
tmpdir = Path(tmp)
|
|
ack = make_ack_wav(tmpdir / "ack.wav")
|
|
_assert_wav_16k_mono_s16(ack)
|
|
|
|
if shutil.which("ffmpeg"):
|
|
converted = convert_audio_to_esp32_wav(str(ack), output_dir=tmpdir, device_id="kitchen/button")
|
|
_assert_wav_16k_mono_s16(converted)
|
|
assert "kitchen_button" in converted.name
|
|
else:
|
|
print("ffmpeg not found; skipped conversion path")
|
|
|
|
print("hermes_voice_gateway smoke tests passed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|