from pathlib import Path from werkzeug.datastructures import MultiDict from abogen.web.routes import _apply_prepare_form, _resolve_voice_setting from abogen.web.service import PendingJob def _make_pending_job() -> PendingJob: return PendingJob( id="pending", original_filename="example.epub", stored_path=Path("example.epub"), language="a", voice="af_nova", speed=1.0, use_gpu=False, subtitle_mode="none", output_format="mp3", save_mode="save_next_to_input", output_folder=None, replace_single_newlines=False, subtitle_format="srt", total_characters=0, save_chapters_separately=False, merge_chapters_at_end=True, separate_chapters_format="wav", silence_between_chapters=2.0, save_as_project=False, voice_profile=None, max_subtitle_words=50, metadata_tags={}, chapters=[], normalization_overrides={}, created_at=0.0, read_title_intro=False, normalize_chapter_opening_caps=True, ) def test_apply_prepare_form_handles_custom_mix_for_speakers(): pending = _make_pending_job() pending.speakers = { "hero": { "id": "hero", "label": "Hero", } } form = MultiDict( { "chapter_intro_delay": "0.5", "speaker-hero-voice": "__custom_mix", "speaker-hero-formula": "af_nova*0.6+am_liam*0.4", } ) _, _, _, errors, *_ = _apply_prepare_form(pending, form) assert not errors hero = pending.speakers["hero"] assert hero["voice_formula"] == "af_nova*0.6+am_liam*0.4" assert hero["resolved_voice"] == "af_nova*0.6+am_liam*0.4" assert "voice" not in hero or hero["voice"] != "__custom_mix" def test_resolve_voice_setting_handles_profile_reference(): profiles = { "Blend": { "language": "b", "voices": [ ("af_nova", 1.0), ("am_liam", 1.0), ], } } voice, profile_name, language = _resolve_voice_setting("profile:Blend", profiles=profiles) assert voice == "af_nova*0.5+am_liam*0.5" assert profile_name == "Blend" assert language == "b"