import ast import shutil import subprocess import tempfile import unittest from pathlib import Path import numpy as np import soundfile as sf import torch from fireredtts3 import reference_asr APP_PATH = Path(__file__).parents[1] / "app.py" class _FakeGradio: class Error(Exception): pass @staticmethod def Info(_message): return None def _load_app_audio_function(): tree = ast.parse(APP_PATH.read_text(encoding="utf-8")) function = next( node for node in tree.body if isinstance(node, ast.FunctionDef) and node.name == "_load_audio" ) namespace = { "gr": _FakeGradio, "np": np, "sf": sf, "torch": torch, "decode_audio_with_ffmpeg": reference_asr.decode_audio_with_ffmpeg, } compiled = compile(ast.Module(body=[function], type_ignores=[]), APP_PATH, "exec") exec(compiled, namespace) # noqa: S102 - executes trusted local application code return namespace["_load_audio"] class AppAudioLoadingIntegrationTests(unittest.TestCase): @unittest.skipUnless(shutil.which("ffmpeg"), "FFmpeg is required for M4A coverage") def test_generate_speech_loads_an_m4a_reference_audio(self): load_audio = _load_app_audio_function() with tempfile.TemporaryDirectory() as tmpdir: wav_path = Path(tmpdir) / "reference.wav" m4a_path = Path(tmpdir) / "reference clip.m4a" time = np.arange(8000, dtype=np.float32) / 8000 sf.write(wav_path, 0.25 * np.sin(2 * np.pi * 440 * time), 8000) subprocess.run( [ "ffmpeg", "-nostdin", "-loglevel", "error", "-y", "-i", str(wav_path), "-c:a", "aac", str(m4a_path), ], check=True, ) waveform, sampling_rate = load_audio(m4a_path, max_seconds=20.0) self.assertEqual(sampling_rate, 16000) self.assertEqual(waveform.ndim, 2) self.assertEqual(waveform.shape[0], 1) self.assertGreaterEqual(waveform.shape[1], 16000) self.assertLess(waveform.shape[1], 17000) self.assertLessEqual(float(waveform.abs().max()), 0.95) if __name__ == "__main__": unittest.main()