feat(lib): add voice reference resolution
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
"""Resolve a ComfyUI AUDIO input or string path into a voice-reference dict."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from lib.audio import audio_dict_to_wav
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def build_voice_reference(
|
||||
audio: Optional[dict],
|
||||
audio_path: str,
|
||||
temp_dir: str,
|
||||
) -> dict:
|
||||
"""Return a voice-reference container.
|
||||
|
||||
Priority:
|
||||
1. If `audio` is set, write it to a temp WAV and use that path.
|
||||
If `audio_path` is also set, log a warning and ignore it.
|
||||
2. Else if `audio_path` is non-empty, validate the path exists and use it.
|
||||
3. Else return source="none" / path=None (default voice).
|
||||
"""
|
||||
if audio is not None:
|
||||
if audio_path:
|
||||
log.warning("Both audio and audio_path provided; ignoring audio_path=%r", audio_path)
|
||||
path = audio_dict_to_wav(audio, dest_dir=temp_dir)
|
||||
return {"path": path, "source": "audio"}
|
||||
|
||||
if audio_path:
|
||||
if not os.path.isfile(audio_path):
|
||||
raise FileNotFoundError(f"Voice reference audio not found: {audio_path}")
|
||||
return {"path": audio_path, "source": "path"}
|
||||
|
||||
return {"path": None, "source": "none"}
|
||||
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
import pytest
|
||||
from lib.voice import build_voice_reference
|
||||
|
||||
|
||||
def test_no_inputs_returns_none_source(tmp_path):
|
||||
result = build_voice_reference(audio=None, audio_path="", temp_dir=str(tmp_path))
|
||||
assert result == {"path": None, "source": "none"}
|
||||
|
||||
|
||||
def test_audio_path_only(tmp_path, sample_comfy_audio):
|
||||
# Write a fake wav so the path exists
|
||||
import torchaudio
|
||||
wav_path = tmp_path / "ref.wav"
|
||||
torchaudio.save(str(wav_path), sample_comfy_audio["waveform"][0], sample_comfy_audio["sample_rate"])
|
||||
result = build_voice_reference(audio=None, audio_path=str(wav_path), temp_dir=str(tmp_path))
|
||||
assert result["source"] == "path"
|
||||
assert result["path"] == str(wav_path)
|
||||
|
||||
|
||||
def test_audio_path_missing_raises(tmp_path):
|
||||
with pytest.raises(FileNotFoundError):
|
||||
build_voice_reference(audio=None, audio_path=str(tmp_path / "nope.wav"), temp_dir=str(tmp_path))
|
||||
|
||||
|
||||
def test_audio_input_writes_temp_wav(tmp_path, sample_comfy_audio):
|
||||
result = build_voice_reference(audio=sample_comfy_audio, audio_path="", temp_dir=str(tmp_path))
|
||||
assert result["source"] == "audio"
|
||||
assert os.path.isfile(result["path"])
|
||||
assert result["path"].startswith(str(tmp_path))
|
||||
|
||||
|
||||
def test_audio_wins_over_path(tmp_path, sample_comfy_audio, caplog):
|
||||
import torchaudio
|
||||
wav_path = tmp_path / "ref.wav"
|
||||
torchaudio.save(str(wav_path), sample_comfy_audio["waveform"][0], sample_comfy_audio["sample_rate"])
|
||||
result = build_voice_reference(
|
||||
audio=sample_comfy_audio,
|
||||
audio_path=str(wav_path),
|
||||
temp_dir=str(tmp_path),
|
||||
)
|
||||
assert result["source"] == "audio"
|
||||
assert result["path"] != str(wav_path)
|
||||
assert any("audio_path" in rec.message for rec in caplog.records)
|
||||
Reference in New Issue
Block a user