eigyouonsei / tests /test_input.py
ryota
聞き返す用の音声を、音質を落とさずに作る
d7c6285
Raw
History Blame Contribute Delete
3.6 kB
"""受け取り方。ZIPでも音声ファイル単体でも、同じように扱えること。"""
import struct
import sys
import wave
import zipfile
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import pipeline as pl # noqa: E402
def make_wav(path: Path, seconds: float = 0.2) -> Path:
path.parent.mkdir(parents=True, exist_ok=True)
with wave.open(str(path), "wb") as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(16000)
f.writeframes(b"".join(
struct.pack("<h", (i % 100) * 50) for i in range(int(16000 * seconds))
))
return path
def test_音声ファイルをそのまま受け取れる(tmp_path):
src = make_wav(tmp_path / "受け取り" / "商談_A社.wav")
found = pl.collect_audio([src], tmp_path / "audio")
assert [name for name, _, _ in found] == ["商談_A社.wav"]
assert found[0][1].exists()
assert found[0][2] # 録音日時が入る
def test_ZIPと音声ファイルを混ぜても良い(tmp_path):
wav = make_wav(tmp_path / "受け取り" / "単体.wav")
inner = make_wav(tmp_path / "元" / "ZIPの中.wav")
zip_path = tmp_path / "受け取り" / "まとめ.zip"
with zipfile.ZipFile(zip_path, "w") as zf:
zf.write(inner, "ZIPの中.wav")
found = pl.collect_audio([zip_path, wav], tmp_path / "audio")
assert sorted(name for name, _, _ in found) == ["ZIPの中.wav", "単体.wav"]
def test_同じ名前でも上書きしない(tmp_path):
a = make_wav(tmp_path / "一つ目" / "同じ名前.wav")
b = make_wav(tmp_path / "二つ目" / "同じ名前.wav")
found = pl.collect_audio([a, b], tmp_path / "audio")
paths = {path for _, path, _ in found}
assert len(paths) == 2 # 別々のファイルとして残る
def test_音声でないものは無視する(tmp_path):
doc = tmp_path / "受け取り" / "資料.pdf"
doc.parent.mkdir(parents=True, exist_ok=True)
doc.write_bytes(b"%PDF-1.4")
assert pl.collect_audio([doc], tmp_path / "audio") == []
def test_危ないファイル名は無害にする():
assert pl.safe_filename("../../etc/passwd") == "passwd"
assert "/" not in pl.safe_filename("a/b/c.wav")
assert pl.safe_filename("") == "音声"
assert pl.safe_filename("a:b*c?.m4a").endswith(".m4a")
def test_再生用の音声を作れる(tmp_path):
"""どのブラウザでも鳴らせるよう mp3 に揃える。"""
src = make_wav(tmp_path / "元.wav", seconds=1.0)
out = pl.to_playback(src, tmp_path / "再生用.mp3")
assert out is not None and out.exists()
assert out.stat().st_size > 0
head = out.read_bytes()[:3]
assert head == b"ID3" or head[:2] in (b"\xff\xfb", b"\xff\xf3") # mp3の目印
def test_元の音質を落とさない(tmp_path):
"""聞き取りやすさを優先。周波数もチャンネル数も元のまま。"""
src = make_wav(tmp_path / "元.wav", seconds=1.0)
out = pl.to_playback(src, tmp_path / "再生用.mp3")
assert out is not None
assert abs(pl.probe_duration(out) - pl.probe_duration(src)) < 0.2 # 長さが変わらない
def test_すでにmp3ならそのまま使う(tmp_path):
"""変換を重ねるほど音は悪くなるので、作り直さない。"""
src = pl.to_playback(make_wav(tmp_path / "元.wav", seconds=1.0), tmp_path / "元.mp3")
out = pl.to_playback(src, tmp_path / "再生用.mp3")
assert out is not None
assert out.read_bytes() == src.read_bytes() # 中身がそのまま