mirror of
https://github.com/denizsafak/abogen.git
synced 2026-09-20 11:40:57 +02:00
refactor: SynthParams dataclass for synthesize_text
- Frozen dataclass in domain/conversion_engine.py with common params - synthesize_text now takes params=SynthParams + unique kwargs - Executor, PyQt legacy, WebUI legacy, and tests updated - Adding new common params now only requires changing the dataclass
This commit is contained in:
@@ -29,6 +29,7 @@ from abogen.application.conversion_result import ConversionResult
|
|||||||
from abogen.domain.audio_sink import open_audio_sink
|
from abogen.domain.audio_sink import open_audio_sink
|
||||||
from abogen.domain.conversion_engine import (
|
from abogen.domain.conversion_engine import (
|
||||||
SegmentStats,
|
SegmentStats,
|
||||||
|
SynthParams,
|
||||||
process_and_write_subtitles,
|
process_and_write_subtitles,
|
||||||
synthesize_text,
|
synthesize_text,
|
||||||
)
|
)
|
||||||
@@ -138,6 +139,18 @@ def execute_conversion(
|
|||||||
|
|
||||||
effective_subtitle_mode = request.subtitle_mode if subtitle_writer else "Disabled"
|
effective_subtitle_mode = request.subtitle_mode if subtitle_writer else "Disabled"
|
||||||
|
|
||||||
|
synth = SynthParams(
|
||||||
|
tts_context=tts_context,
|
||||||
|
stats=stats,
|
||||||
|
check_cancel=check_cancelled,
|
||||||
|
on_progress=lambda pct, etr: events.progress(pct, etr),
|
||||||
|
audio_sink=audio_sink,
|
||||||
|
subtitle_mode=effective_subtitle_mode,
|
||||||
|
max_subtitle_words=request.max_subtitle_words,
|
||||||
|
lang_code=request.language,
|
||||||
|
use_spacy_segmentation=use_spacy,
|
||||||
|
)
|
||||||
|
|
||||||
# Chapter directory
|
# Chapter directory
|
||||||
chapter_dir = None
|
chapter_dir = None
|
||||||
if request.save_chapters_separately and len(plan.chapters) > 1:
|
if request.save_chapters_separately and len(plan.chapters) > 1:
|
||||||
@@ -154,20 +167,12 @@ def execute_conversion(
|
|||||||
intro_backend = pipeline_provider.get(intro_provider, request.language, request.use_gpu)
|
intro_backend = pipeline_provider.get(intro_provider, request.language, request.use_gpu)
|
||||||
synthesize_text(
|
synthesize_text(
|
||||||
text=plan.intro.text,
|
text=plan.intro.text,
|
||||||
tts_context=tts_context,
|
params=synth,
|
||||||
backend=intro_backend,
|
backend=intro_backend,
|
||||||
voice=intro_voice,
|
voice=intro_voice,
|
||||||
speed=intro_speed or request.speed,
|
speed=intro_speed or request.speed,
|
||||||
stats=stats,
|
|
||||||
check_cancel=check_cancelled,
|
|
||||||
on_progress=lambda pct, etr: events.progress(pct, etr),
|
|
||||||
chapter_sink=None,
|
chapter_sink=None,
|
||||||
audio_sink=audio_sink,
|
|
||||||
preview_callback=lambda text: events.log(f" {text[:80]}"),
|
preview_callback=lambda text: events.log(f" {text[:80]}"),
|
||||||
subtitle_mode=effective_subtitle_mode,
|
|
||||||
max_subtitle_words=request.max_subtitle_words,
|
|
||||||
lang_code=request.language,
|
|
||||||
use_spacy_segmentation=use_spacy,
|
|
||||||
)
|
)
|
||||||
intro_emitted = True
|
intro_emitted = True
|
||||||
events.log("Intro synthesized.")
|
events.log("Intro synthesized.")
|
||||||
@@ -209,20 +214,12 @@ def execute_conversion(
|
|||||||
intro_backend = pipeline_provider.get(intro_provider, request.language, request.use_gpu)
|
intro_backend = pipeline_provider.get(intro_provider, request.language, request.use_gpu)
|
||||||
synthesize_text(
|
synthesize_text(
|
||||||
text=plan.intro.text,
|
text=plan.intro.text,
|
||||||
tts_context=tts_context,
|
params=synth,
|
||||||
backend=intro_backend,
|
backend=intro_backend,
|
||||||
voice=intro_voice,
|
voice=intro_voice,
|
||||||
speed=intro_speed or request.speed,
|
speed=intro_speed or request.speed,
|
||||||
stats=stats,
|
|
||||||
check_cancel=check_cancelled,
|
|
||||||
on_progress=lambda pct, etr: events.progress(pct, etr),
|
|
||||||
chapter_sink=chapter_sink,
|
chapter_sink=chapter_sink,
|
||||||
audio_sink=audio_sink,
|
|
||||||
preview_callback=lambda text: events.log(f" Intro: {text[:80]}"),
|
preview_callback=lambda text: events.log(f" Intro: {text[:80]}"),
|
||||||
subtitle_mode=effective_subtitle_mode,
|
|
||||||
max_subtitle_words=request.max_subtitle_words,
|
|
||||||
lang_code=request.language,
|
|
||||||
use_spacy_segmentation=use_spacy,
|
|
||||||
)
|
)
|
||||||
intro_emitted = True
|
intro_emitted = True
|
||||||
if request.chapter_intro_delay > 0:
|
if request.chapter_intro_delay > 0:
|
||||||
@@ -239,20 +236,12 @@ def execute_conversion(
|
|||||||
if heading_text:
|
if heading_text:
|
||||||
synthesize_text(
|
synthesize_text(
|
||||||
text=heading_text,
|
text=heading_text,
|
||||||
tts_context=tts_context,
|
params=synth,
|
||||||
backend=chapter_backend,
|
backend=chapter_backend,
|
||||||
voice=chapter_voice,
|
voice=chapter_voice,
|
||||||
speed=chapter_speed or request.speed,
|
speed=chapter_speed or request.speed,
|
||||||
stats=stats,
|
|
||||||
check_cancel=check_cancelled,
|
|
||||||
on_progress=lambda pct, etr: events.progress(pct, etr),
|
|
||||||
chapter_sink=chapter_sink,
|
chapter_sink=chapter_sink,
|
||||||
audio_sink=audio_sink,
|
|
||||||
preview_callback=lambda text: events.log(f" Title: {text[:80]}"),
|
preview_callback=lambda text: events.log(f" Title: {text[:80]}"),
|
||||||
subtitle_mode=effective_subtitle_mode,
|
|
||||||
max_subtitle_words=request.max_subtitle_words,
|
|
||||||
lang_code=request.language,
|
|
||||||
use_spacy_segmentation=use_spacy,
|
|
||||||
)
|
)
|
||||||
if request.chapter_intro_delay > 0:
|
if request.chapter_intro_delay > 0:
|
||||||
_append_silence(
|
_append_silence(
|
||||||
@@ -282,20 +271,12 @@ def execute_conversion(
|
|||||||
seg_start_time = stats.current_time
|
seg_start_time = stats.current_time
|
||||||
local_segments, accumulated_tokens = synthesize_text(
|
local_segments, accumulated_tokens = synthesize_text(
|
||||||
text=segment.text,
|
text=segment.text,
|
||||||
tts_context=tts_context,
|
params=synth,
|
||||||
backend=seg_backend,
|
backend=seg_backend,
|
||||||
voice=seg_voice,
|
voice=seg_voice,
|
||||||
speed=seg_speed or request.speed,
|
speed=seg_speed or request.speed,
|
||||||
stats=stats,
|
|
||||||
check_cancel=check_cancelled,
|
|
||||||
on_progress=lambda pct, etr: events.progress(pct, etr),
|
|
||||||
chapter_sink=chapter_sink,
|
chapter_sink=chapter_sink,
|
||||||
audio_sink=audio_sink,
|
|
||||||
preview_callback=lambda text: events.log(f" {text[:80]}"),
|
preview_callback=lambda text: events.log(f" {text[:80]}"),
|
||||||
subtitle_mode=effective_subtitle_mode,
|
|
||||||
max_subtitle_words=request.max_subtitle_words,
|
|
||||||
lang_code=request.language,
|
|
||||||
use_spacy_segmentation=use_spacy,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Process subtitles
|
# Process subtitles
|
||||||
@@ -366,20 +347,12 @@ def execute_conversion(
|
|||||||
|
|
||||||
synthesize_text(
|
synthesize_text(
|
||||||
text=plan.outro.text,
|
text=plan.outro.text,
|
||||||
tts_context=tts_context,
|
params=synth,
|
||||||
backend=outro_backend,
|
backend=outro_backend,
|
||||||
voice=outro_voice,
|
voice=outro_voice,
|
||||||
speed=outro_speed or request.speed,
|
speed=outro_speed or request.speed,
|
||||||
stats=stats,
|
|
||||||
check_cancel=check_cancelled,
|
|
||||||
on_progress=lambda pct, etr: events.progress(pct, etr),
|
|
||||||
chapter_sink=None,
|
chapter_sink=None,
|
||||||
audio_sink=audio_sink,
|
|
||||||
preview_callback=lambda text: events.log(f" {text[:80]}"),
|
preview_callback=lambda text: events.log(f" {text[:80]}"),
|
||||||
subtitle_mode=effective_subtitle_mode,
|
|
||||||
max_subtitle_words=request.max_subtitle_words,
|
|
||||||
lang_code=request.language,
|
|
||||||
use_spacy_segmentation=use_spacy,
|
|
||||||
)
|
)
|
||||||
events.log("Outro synthesized.")
|
events.log("Outro synthesized.")
|
||||||
|
|
||||||
|
|||||||
@@ -191,24 +191,34 @@ def process_and_write_subtitles(
|
|||||||
subtitle_writer.write_entry(start=start, end=end, text=text)
|
subtitle_writer.write_entry(start=start, end=end, text=text)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class SynthParams:
|
||||||
|
"""Common parameters for synthesize_text calls.
|
||||||
|
|
||||||
|
Packed once by the executor to avoid repeating identical kwargs.
|
||||||
|
When adding new common params, change only this dataclass.
|
||||||
|
"""
|
||||||
|
tts_context: TTSContext
|
||||||
|
stats: SegmentStats
|
||||||
|
check_cancel: CancelChecker
|
||||||
|
on_progress: Callable[[int, str], None]
|
||||||
|
audio_sink: Optional[AudioSink] = None
|
||||||
|
subtitle_mode: str = "Disabled"
|
||||||
|
max_subtitle_words: int = 50
|
||||||
|
lang_code: str = "a"
|
||||||
|
use_spacy_segmentation: bool = False
|
||||||
|
|
||||||
|
|
||||||
def synthesize_text(
|
def synthesize_text(
|
||||||
*,
|
*,
|
||||||
text: str,
|
text: str,
|
||||||
tts_context: TTSContext,
|
params: SynthParams,
|
||||||
backend: Any,
|
backend: Any,
|
||||||
voice: Any,
|
voice: Any,
|
||||||
speed: float,
|
speed: float,
|
||||||
stats: SegmentStats,
|
|
||||||
check_cancel: CancelChecker,
|
|
||||||
on_progress: Callable[[int, str], None],
|
|
||||||
chapter_sink: Optional[AudioSink] = None,
|
chapter_sink: Optional[AudioSink] = None,
|
||||||
audio_sink: Optional[AudioSink] = None,
|
|
||||||
preview_callback: Optional[Callable[[str], None]] = None,
|
preview_callback: Optional[Callable[[str], None]] = None,
|
||||||
on_segment: Optional[Callable[[SegmentInfo], None]] = None,
|
on_segment: Optional[Callable[[SegmentInfo], None]] = None,
|
||||||
subtitle_mode: str = "Disabled",
|
|
||||||
max_subtitle_words: int = 50,
|
|
||||||
lang_code: str = "a",
|
|
||||||
use_spacy_segmentation: bool = False,
|
|
||||||
split_pattern_override: Optional[str] = None,
|
split_pattern_override: Optional[str] = None,
|
||||||
) -> tuple[int, list]:
|
) -> tuple[int, list]:
|
||||||
"""Normalize text and run TTS — the single entry point for both UIs.
|
"""Normalize text and run TTS — the single entry point for both UIs.
|
||||||
@@ -216,22 +226,22 @@ def synthesize_text(
|
|||||||
Combines TTSContext.normalize() + run_tts_segment_loop() into one call.
|
Combines TTSContext.normalize() + run_tts_segment_loop() into one call.
|
||||||
UI-specific concerns (provider resolution, progress display) stay in the UI.
|
UI-specific concerns (provider resolution, progress display) stay in the UI.
|
||||||
"""
|
"""
|
||||||
normalized = tts_context.normalize(text)
|
normalized = params.tts_context.normalize(text)
|
||||||
return run_tts_segment_loop(
|
return run_tts_segment_loop(
|
||||||
text=normalized,
|
text=normalized,
|
||||||
backend=backend,
|
backend=backend,
|
||||||
voice=voice,
|
voice=voice,
|
||||||
speed=speed,
|
speed=speed,
|
||||||
split_pattern=split_pattern_override or tts_context.split_pattern,
|
split_pattern=split_pattern_override or params.tts_context.split_pattern,
|
||||||
stats=stats,
|
stats=params.stats,
|
||||||
check_cancel=check_cancel,
|
check_cancel=params.check_cancel,
|
||||||
on_progress=on_progress,
|
on_progress=params.on_progress,
|
||||||
chapter_sink=chapter_sink,
|
chapter_sink=chapter_sink,
|
||||||
audio_sink=audio_sink,
|
audio_sink=params.audio_sink,
|
||||||
preview_callback=preview_callback,
|
preview_callback=preview_callback,
|
||||||
on_segment=on_segment,
|
on_segment=on_segment,
|
||||||
subtitle_mode=subtitle_mode,
|
subtitle_mode=params.subtitle_mode,
|
||||||
max_subtitle_words=max_subtitle_words,
|
max_subtitle_words=params.max_subtitle_words,
|
||||||
lang_code=lang_code,
|
lang_code=params.lang_code,
|
||||||
use_spacy_segmentation=use_spacy_segmentation,
|
use_spacy_segmentation=params.use_spacy_segmentation,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ from abogen.domain.output_paths import (
|
|||||||
)
|
)
|
||||||
from abogen.domain.audio_helpers import build_ffmpeg_command, to_float32
|
from abogen.domain.audio_helpers import build_ffmpeg_command, to_float32
|
||||||
from abogen.domain.audio_sink import AudioSink, open_audio_sink
|
from abogen.domain.audio_sink import AudioSink, open_audio_sink
|
||||||
from abogen.domain.conversion_engine import synthesize_text, SegmentStats, SegmentInfo
|
from abogen.domain.conversion_engine import synthesize_text, SynthParams, SegmentStats, SegmentInfo
|
||||||
from abogen.domain.intro_outro import resolve_intro, resolve_outro
|
from abogen.domain.intro_outro import resolve_intro, resolve_outro
|
||||||
from abogen.domain.audio_buffer import (
|
from abogen.domain.audio_buffer import (
|
||||||
create_silence,
|
create_silence,
|
||||||
@@ -1016,18 +1016,26 @@ class ConversionThread(QThread):
|
|||||||
total_characters=self.total_char_count,
|
total_characters=self.total_char_count,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
synth_params = SynthParams(
|
||||||
synthesize_text(
|
|
||||||
text=text_segment,
|
|
||||||
tts_context=self._tts_context,
|
tts_context=self._tts_context,
|
||||||
backend=self.backend,
|
|
||||||
voice=loaded_voice,
|
|
||||||
speed=self.speed,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=_qt_check_cancel,
|
check_cancel=_qt_check_cancel,
|
||||||
on_progress=_qt_on_progress,
|
on_progress=_qt_on_progress,
|
||||||
chapter_sink=chapter_sink,
|
|
||||||
audio_sink=merged_sink if merge_chapters_at_end else None,
|
audio_sink=merged_sink if merge_chapters_at_end else None,
|
||||||
|
subtitle_mode=self.subtitle_mode,
|
||||||
|
max_subtitle_words=self.max_subtitle_words,
|
||||||
|
lang_code=self.lang_code,
|
||||||
|
use_spacy_segmentation=getattr(self, "use_spacy_segmentation", False),
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
synthesize_text(
|
||||||
|
text=text_segment,
|
||||||
|
params=synth_params,
|
||||||
|
backend=self.backend,
|
||||||
|
voice=loaded_voice,
|
||||||
|
speed=self.speed,
|
||||||
|
chapter_sink=chapter_sink,
|
||||||
on_segment=_qt_on_segment,
|
on_segment=_qt_on_segment,
|
||||||
split_pattern_override=active_split_pattern,
|
split_pattern_override=active_split_pattern,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ from abogen.domain.audio_buffer import (
|
|||||||
)
|
)
|
||||||
from abogen.domain.audio_sink import AudioSink, open_audio_sink
|
from abogen.domain.audio_sink import AudioSink, open_audio_sink
|
||||||
from abogen.domain.pipeline_factory import PipelinePool
|
from abogen.domain.pipeline_factory import PipelinePool
|
||||||
from abogen.domain.conversion_engine import synthesize_text, process_and_write_subtitles, SegmentStats
|
from abogen.domain.conversion_engine import synthesize_text, SynthParams, process_and_write_subtitles, SegmentStats
|
||||||
from abogen.domain.voice_loader import VoiceCache, resolve_voice
|
from abogen.domain.voice_loader import VoiceCache, resolve_voice
|
||||||
from abogen.domain.voice_utils import resolve_voice_target as _resolve_voice_target
|
from abogen.domain.voice_utils import resolve_voice_target as _resolve_voice_target
|
||||||
|
|
||||||
@@ -462,23 +462,27 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
def _preview(text: str) -> None:
|
def _preview(text: str) -> None:
|
||||||
job.add_log(f"{prefix}{stats.processed_chars:,}/{job.total_characters or '—'}: {text[:80]}")
|
job.add_log(f"{prefix}{stats.processed_chars:,}/{job.total_characters or '—'}: {text[:80]}")
|
||||||
|
|
||||||
local_segments, accumulated_tokens = synthesize_text(
|
synth_params = SynthParams(
|
||||||
text=source_text,
|
|
||||||
tts_context=tts_context,
|
tts_context=tts_context,
|
||||||
backend=backend,
|
|
||||||
voice=resolved_voice,
|
|
||||||
speed=effective_speed,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=canceller,
|
check_cancel=canceller,
|
||||||
on_progress=_on_progress,
|
on_progress=_on_progress,
|
||||||
chapter_sink=chapter_sink,
|
|
||||||
audio_sink=audio_sink,
|
audio_sink=audio_sink,
|
||||||
preview_callback=_preview,
|
|
||||||
subtitle_mode=job.subtitle_mode if (subtitle_writer and audio_sink) else "Disabled",
|
subtitle_mode=job.subtitle_mode if (subtitle_writer and audio_sink) else "Disabled",
|
||||||
max_subtitle_words=job.max_subtitle_words,
|
max_subtitle_words=job.max_subtitle_words,
|
||||||
lang_code=job.language,
|
lang_code=job.language,
|
||||||
use_spacy_segmentation=job.subtitle_mode not in ("Disabled", "Line"),
|
use_spacy_segmentation=job.subtitle_mode not in ("Disabled", "Line"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
local_segments, accumulated_tokens = synthesize_text(
|
||||||
|
text=source_text,
|
||||||
|
params=synth_params,
|
||||||
|
backend=backend,
|
||||||
|
voice=resolved_voice,
|
||||||
|
speed=effective_speed,
|
||||||
|
chapter_sink=chapter_sink,
|
||||||
|
preview_callback=_preview,
|
||||||
|
)
|
||||||
current_time = stats.current_time
|
current_time = stats.current_time
|
||||||
|
|
||||||
if subtitle_writer and audio_sink and accumulated_tokens:
|
if subtitle_writer and audio_sink and accumulated_tokens:
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from typing import Any
|
|||||||
|
|
||||||
from abogen.domain.conversion_engine import (
|
from abogen.domain.conversion_engine import (
|
||||||
synthesize_text,
|
synthesize_text,
|
||||||
|
SynthParams,
|
||||||
run_tts_segment_loop,
|
run_tts_segment_loop,
|
||||||
process_and_write_subtitles,
|
process_and_write_subtitles,
|
||||||
SegmentStats,
|
SegmentStats,
|
||||||
@@ -133,18 +134,22 @@ class TestSynthesizeText:
|
|||||||
def on_progress(pct, etr):
|
def on_progress(pct, etr):
|
||||||
progress_calls.append((pct, etr))
|
progress_calls.append((pct, etr))
|
||||||
|
|
||||||
segments, tokens = synthesize_text(
|
params = SynthParams(
|
||||||
text="Hello world.",
|
|
||||||
tts_context=tts_ctx,
|
tts_context=tts_ctx,
|
||||||
backend=backend,
|
|
||||||
voice="M1",
|
|
||||||
speed=1.0,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=cancel,
|
check_cancel=cancel,
|
||||||
on_progress=on_progress,
|
on_progress=on_progress,
|
||||||
audio_sink=sink,
|
audio_sink=sink,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
segments, tokens = synthesize_text(
|
||||||
|
text="Hello world.",
|
||||||
|
params=params,
|
||||||
|
backend=backend,
|
||||||
|
voice="M1",
|
||||||
|
speed=1.0,
|
||||||
|
)
|
||||||
|
|
||||||
assert segments >= 1
|
assert segments >= 1
|
||||||
assert len(sink.written) >= 1
|
assert len(sink.written) >= 1
|
||||||
assert len(progress_calls) >= 1
|
assert len(progress_calls) >= 1
|
||||||
@@ -159,17 +164,21 @@ class TestSynthesizeText:
|
|||||||
def on_progress(pct, etr):
|
def on_progress(pct, etr):
|
||||||
progress_calls.append((pct, etr))
|
progress_calls.append((pct, etr))
|
||||||
|
|
||||||
segments, tokens = synthesize_text(
|
params = SynthParams(
|
||||||
text="Hello world.",
|
|
||||||
tts_context=tts_ctx,
|
tts_context=tts_ctx,
|
||||||
backend=backend,
|
|
||||||
voice="M1",
|
|
||||||
speed=1.0,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=cancel,
|
check_cancel=cancel,
|
||||||
on_progress=on_progress,
|
on_progress=on_progress,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
segments, tokens = synthesize_text(
|
||||||
|
text="Hello world.",
|
||||||
|
params=params,
|
||||||
|
backend=backend,
|
||||||
|
voice="M1",
|
||||||
|
speed=1.0,
|
||||||
|
)
|
||||||
|
|
||||||
# Should stop early due to cancellation
|
# Should stop early due to cancellation
|
||||||
assert segments == 0
|
assert segments == 0
|
||||||
|
|
||||||
@@ -184,19 +193,23 @@ class TestSynthesizeText:
|
|||||||
def on_progress(pct, etr):
|
def on_progress(pct, etr):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
segments, tokens = synthesize_text(
|
params = SynthParams(
|
||||||
text="Hello world.",
|
|
||||||
tts_context=tts_ctx,
|
tts_context=tts_ctx,
|
||||||
backend=backend,
|
|
||||||
voice="M1",
|
|
||||||
speed=1.0,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=cancel,
|
check_cancel=cancel,
|
||||||
on_progress=on_progress,
|
on_progress=on_progress,
|
||||||
chapter_sink=chapter_sink,
|
|
||||||
audio_sink=merged_sink,
|
audio_sink=merged_sink,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
segments, tokens = synthesize_text(
|
||||||
|
text="Hello world.",
|
||||||
|
params=params,
|
||||||
|
backend=backend,
|
||||||
|
voice="M1",
|
||||||
|
speed=1.0,
|
||||||
|
chapter_sink=chapter_sink,
|
||||||
|
)
|
||||||
|
|
||||||
# Both sinks should receive audio
|
# Both sinks should receive audio
|
||||||
assert len(chapter_sink.written) >= 1
|
assert len(chapter_sink.written) >= 1
|
||||||
assert len(merged_sink.written) >= 1
|
assert len(merged_sink.written) >= 1
|
||||||
@@ -210,15 +223,19 @@ class TestSynthesizeText:
|
|||||||
def on_progress(pct, etr):
|
def on_progress(pct, etr):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
segments, tokens = synthesize_text(
|
params = SynthParams(
|
||||||
text="Hello world.",
|
|
||||||
tts_context=tts_ctx,
|
tts_context=tts_ctx,
|
||||||
backend=backend,
|
|
||||||
voice="M1",
|
|
||||||
speed=1.0,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=cancel,
|
check_cancel=cancel,
|
||||||
on_progress=on_progress,
|
on_progress=on_progress,
|
||||||
|
)
|
||||||
|
|
||||||
|
segments, tokens = synthesize_text(
|
||||||
|
text="Hello world.",
|
||||||
|
params=params,
|
||||||
|
backend=backend,
|
||||||
|
voice="M1",
|
||||||
|
speed=1.0,
|
||||||
split_pattern_override=r"\n+",
|
split_pattern_override=r"\n+",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -323,16 +340,11 @@ class TestFullPipeline:
|
|||||||
progress_calls.append((pct, etr))
|
progress_calls.append((pct, etr))
|
||||||
|
|
||||||
# Simulate full pipeline: synthesize → subtitles → finalize
|
# Simulate full pipeline: synthesize → subtitles → finalize
|
||||||
segments, tokens = synthesize_text(
|
params = SynthParams(
|
||||||
text="This is a test sentence. Another sentence here.",
|
|
||||||
tts_context=tts_ctx,
|
tts_context=tts_ctx,
|
||||||
backend=backend,
|
|
||||||
voice="M1",
|
|
||||||
speed=1.0,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=cancel,
|
check_cancel=cancel,
|
||||||
on_progress=on_progress,
|
on_progress=on_progress,
|
||||||
chapter_sink=chapter_sink,
|
|
||||||
audio_sink=merged_sink,
|
audio_sink=merged_sink,
|
||||||
subtitle_mode="Sentence",
|
subtitle_mode="Sentence",
|
||||||
max_subtitle_words=5,
|
max_subtitle_words=5,
|
||||||
@@ -340,6 +352,15 @@ class TestFullPipeline:
|
|||||||
use_spacy_segmentation=False,
|
use_spacy_segmentation=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
segments, tokens = synthesize_text(
|
||||||
|
text="This is a test sentence. Another sentence here.",
|
||||||
|
params=params,
|
||||||
|
backend=backend,
|
||||||
|
voice="M1",
|
||||||
|
speed=1.0,
|
||||||
|
chapter_sink=chapter_sink,
|
||||||
|
)
|
||||||
|
|
||||||
# Process accumulated tokens
|
# Process accumulated tokens
|
||||||
process_and_write_subtitles(
|
process_and_write_subtitles(
|
||||||
tokens,
|
tokens,
|
||||||
@@ -373,16 +394,20 @@ class TestFullPipeline:
|
|||||||
def on_progress(pct, etr):
|
def on_progress(pct, etr):
|
||||||
progress_calls.append((pct, etr))
|
progress_calls.append((pct, etr))
|
||||||
|
|
||||||
segments, tokens = synthesize_text(
|
params = SynthParams(
|
||||||
text="Hello world. " * 100,
|
|
||||||
tts_context=tts_ctx,
|
tts_context=tts_ctx,
|
||||||
backend=backend,
|
|
||||||
voice="M1",
|
|
||||||
speed=1.0,
|
|
||||||
stats=stats,
|
stats=stats,
|
||||||
check_cancel=cancel_fn,
|
check_cancel=cancel_fn,
|
||||||
on_progress=on_progress,
|
on_progress=on_progress,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
segments, tokens = synthesize_text(
|
||||||
|
text="Hello world. " * 100,
|
||||||
|
params=params,
|
||||||
|
backend=backend,
|
||||||
|
voice="M1",
|
||||||
|
speed=1.0,
|
||||||
|
)
|
||||||
|
|
||||||
# Should have stopped before processing all text
|
# Should have stopped before processing all text
|
||||||
assert segments <= 4
|
assert segments <= 4
|
||||||
|
|||||||
Reference in New Issue
Block a user