Takosaga commited on
Commit
7f0a02a
Β·
1 Parent(s): 9796129

feat: wire TTS into Phase 2 pipeline with voice design mode

Browse files
Files changed (1) hide show
  1. core/pipeline.py +33 -10
core/pipeline.py CHANGED
@@ -1,14 +1,14 @@
1
  """EuropaLex Pipeline β€” Phase 2 orchestration.
2
 
3
  Receives English texts generated in Phase 1 and produces translated
4
- CardData objects via tiny-aya-water translation engine.
5
-
6
- Images and audio are not yet wired β€” those fields remain empty.
7
  """
8
 
9
  from __future__ import annotations
10
 
11
  import logging
 
12
  from typing import Iterator
13
 
14
  from core.engine import EnginePool
@@ -22,11 +22,14 @@ def generate_phase2(
22
  scenario: str,
23
  cefr_level: CEFRLevel,
24
  batch_size: int,
 
 
25
  ) -> Iterator[tuple[int, str, list[CardData]]]:
26
- """Generate Latvian translations for Phase 1 English texts.
27
 
28
  Orchestrates the translation pipeline: gets the tiny-aya engine,
29
- calls generate with retry validation, and yields CardData objects.
 
30
 
31
  Yields (progress_percent, phase_label, cards) at each step.
32
 
@@ -35,11 +38,15 @@ def generate_phase2(
35
  scenario: Original scenario/topic description.
36
  cefr_level: CEFR proficiency level.
37
  batch_size: Number of translations expected.
 
 
38
 
39
  Yields:
40
  (20, "Preparing translation...", []) β€” before engine call
41
- (60, "Translating...", []) β€” during generation
42
- (100, "Translation complete!", cards) β€” with final CardData list
 
 
43
 
44
  Raises:
45
  ValidationError: If translation fails after max retries.
@@ -68,15 +75,31 @@ def generate_phase2(
68
  except ValidationError:
69
  raise
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  cards = [
72
  CardData(
73
  text=text,
74
  translation=translation,
75
- audio_path=None,
76
  image_path=None,
77
  cefr_level=cefr_level,
78
  )
79
- for text, translation in zip(texts, translations)
80
  ]
81
 
82
- yield 100, "Translation complete!", cards
 
 
 
 
1
  """EuropaLex Pipeline β€” Phase 2 orchestration.
2
 
3
  Receives English texts generated in Phase 1 and produces translated
4
+ CardData objects via tiny-aya-water translation engine, with optional
5
+ TTS audio generation using OmniVoice voice design mode.
 
6
  """
7
 
8
  from __future__ import annotations
9
 
10
  import logging
11
+ from pathlib import Path
12
  from typing import Iterator
13
 
14
  from core.engine import EnginePool
 
22
  scenario: str,
23
  cefr_level: CEFRLevel,
24
  batch_size: int,
25
+ target_language: str = "Latvian",
26
+ include_audio: bool = False,
27
  ) -> Iterator[tuple[int, str, list[CardData]]]:
28
+ """Generate translations and optional TTS audio for Phase 1 English texts.
29
 
30
  Orchestrates the translation pipeline: gets the tiny-aya engine,
31
+ calls generate with retry validation, optionally generates TTS audio
32
+ for all translations via OmniVoice (voice design mode), and yields CardData objects.
33
 
34
  Yields (progress_percent, phase_label, cards) at each step.
35
 
 
38
  scenario: Original scenario/topic description.
39
  cefr_level: CEFR proficiency level.
40
  batch_size: Number of translations expected.
41
+ target_language: Target language name for TTS (e.g., "Latvian"). Used to improve synthesis quality.
42
+ include_audio: If True, generate TTS audio for all translations after translation completes.
43
 
44
  Yields:
45
  (20, "Preparing translation...", []) β€” before engine call
46
+ (15-70, "Translating... (N/total)", []) β€” during per-sentence translation
47
+ (70, "Generating audio...", []) β€” before TTS starts (if include_audio=True)
48
+ (95, "Audio complete!", cards) β€” after TTS batch (if include_audio=True)
49
+ (100, "Translation and audio complete!", cards) β€” with final CardData list
50
 
51
  Raises:
52
  ValidationError: If translation fails after max retries.
 
75
  except ValidationError:
76
  raise
77
 
78
+ audio_paths: list[str | None] = [None] * len(translations)
79
+
80
+ if include_audio:
81
+ yield 70, "Generating audio...", []
82
+ try:
83
+ tts_engine = pool.get_tts_engine()
84
+ output_dir = Path(config.models_dir) / "output" / "audio"
85
+ audio_result = tts_engine.synthesize(translations, output_dir, language=target_language)
86
+ audio_paths = audio_result.audio_paths
87
+ except Exception as e:
88
+ logger.error("TTS generation failed: %s", e, exc_info=True)
89
+ # Continue with None audio paths β€” cards still render with translations
90
+
91
  cards = [
92
  CardData(
93
  text=text,
94
  translation=translation,
95
+ audio_path=audio_paths[i] if include_audio else None,
96
  image_path=None,
97
  cefr_level=cefr_level,
98
  )
99
+ for i, (text, translation) in enumerate(zip(texts, translations))
100
  ]
101
 
102
+ if include_audio:
103
+ yield 100, "Translation and audio complete!", cards
104
+ else:
105
+ yield 100, "Translation complete!", cards