Commit ·
b91b3a1
1
Parent(s): a8847b5
refactor: Remove deprecated audio generation progress monitoring and update related methods
Browse files- tests/unit/test_app_audio_state.py +0 -90
- yomitalk/app.py +49 -68
tests/unit/test_app_audio_state.py
CHANGED
|
@@ -159,96 +159,6 @@ class TestPaperPodcastAppAudioRecovery:
|
|
| 159 |
assert "60%" in status
|
| 160 |
assert "復帰" in status
|
| 161 |
|
| 162 |
-
def test_monitor_audio_generation_progress_completed(self):
|
| 163 |
-
"""Test monitoring progress when generation is completed."""
|
| 164 |
-
# Set up completed state
|
| 165 |
-
self.user_session.update_audio_generation_state(
|
| 166 |
-
is_generating=False,
|
| 167 |
-
status="completed",
|
| 168 |
-
progress=1.0,
|
| 169 |
-
streaming_parts=["part1.wav"],
|
| 170 |
-
final_audio_path="final_audio.wav",
|
| 171 |
-
)
|
| 172 |
-
|
| 173 |
-
streaming_audio, final_audio, button_state = (
|
| 174 |
-
self.app.monitor_audio_generation_progress(
|
| 175 |
-
self.user_session, terms_agreed=True, podcast_text="Test script"
|
| 176 |
-
)
|
| 177 |
-
)
|
| 178 |
-
|
| 179 |
-
assert streaming_audio == "part1.wav"
|
| 180 |
-
assert final_audio == "final_audio.wav"
|
| 181 |
-
assert button_state["interactive"] is True
|
| 182 |
-
assert button_state["value"] == "音声を生成"
|
| 183 |
-
|
| 184 |
-
def test_monitor_audio_generation_progress_active(self):
|
| 185 |
-
"""Test monitoring progress when generation is active."""
|
| 186 |
-
# Set up active state
|
| 187 |
-
self.user_session.update_audio_generation_state(
|
| 188 |
-
is_generating=True,
|
| 189 |
-
status="generating",
|
| 190 |
-
progress=0.3,
|
| 191 |
-
streaming_parts=["part1.wav"],
|
| 192 |
-
)
|
| 193 |
-
|
| 194 |
-
streaming_audio, final_audio, button_state = (
|
| 195 |
-
self.app.monitor_audio_generation_progress(
|
| 196 |
-
self.user_session, terms_agreed=True, podcast_text="Test script"
|
| 197 |
-
)
|
| 198 |
-
)
|
| 199 |
-
|
| 200 |
-
# During active generation, audio components should return gr.update() to avoid race conditions
|
| 201 |
-
import gradio as gr
|
| 202 |
-
|
| 203 |
-
assert isinstance(streaming_audio, gr.update().__class__)
|
| 204 |
-
assert isinstance(final_audio, gr.update().__class__)
|
| 205 |
-
assert button_state["interactive"] is False
|
| 206 |
-
assert "30%" in button_state["value"]
|
| 207 |
-
|
| 208 |
-
def test_monitor_audio_generation_progress_terms_not_agreed(self):
|
| 209 |
-
"""Test monitoring progress when terms are not agreed after completion."""
|
| 210 |
-
# Set up completed state
|
| 211 |
-
self.user_session.update_audio_generation_state(
|
| 212 |
-
is_generating=False,
|
| 213 |
-
status="completed",
|
| 214 |
-
progress=1.0,
|
| 215 |
-
streaming_parts=["part1.wav"],
|
| 216 |
-
final_audio_path="final_audio.wav",
|
| 217 |
-
)
|
| 218 |
-
|
| 219 |
-
streaming_audio, final_audio, button_state = (
|
| 220 |
-
self.app.monitor_audio_generation_progress(
|
| 221 |
-
self.user_session, terms_agreed=False, podcast_text="Test script"
|
| 222 |
-
)
|
| 223 |
-
)
|
| 224 |
-
|
| 225 |
-
assert streaming_audio == "part1.wav"
|
| 226 |
-
assert final_audio == "final_audio.wav"
|
| 227 |
-
assert button_state["interactive"] is False
|
| 228 |
-
assert button_state["value"] == "音声を生成(VOICEVOX利用規約に同意が必要です)"
|
| 229 |
-
|
| 230 |
-
def test_monitor_audio_generation_progress_no_text(self):
|
| 231 |
-
"""Test monitoring progress when no text is available after completion."""
|
| 232 |
-
# Set up completed state
|
| 233 |
-
self.user_session.update_audio_generation_state(
|
| 234 |
-
is_generating=False,
|
| 235 |
-
status="completed",
|
| 236 |
-
progress=1.0,
|
| 237 |
-
streaming_parts=["part1.wav"],
|
| 238 |
-
final_audio_path="final_audio.wav",
|
| 239 |
-
)
|
| 240 |
-
|
| 241 |
-
streaming_audio, final_audio, button_state = (
|
| 242 |
-
self.app.monitor_audio_generation_progress(
|
| 243 |
-
self.user_session, terms_agreed=True, podcast_text=""
|
| 244 |
-
)
|
| 245 |
-
)
|
| 246 |
-
|
| 247 |
-
assert streaming_audio == "part1.wav"
|
| 248 |
-
assert final_audio == "final_audio.wav"
|
| 249 |
-
assert button_state["interactive"] is False
|
| 250 |
-
assert button_state["value"] == "音声を生成(トーク原稿が必要です)"
|
| 251 |
-
|
| 252 |
def test_check_and_restore_audio_generation_integration(self):
|
| 253 |
"""Test that audio restoration is properly integrated into connection recovery."""
|
| 254 |
# Set up completed audio state
|
|
|
|
| 159 |
assert "60%" in status
|
| 160 |
assert "復帰" in status
|
| 161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
def test_check_and_restore_audio_generation_integration(self):
|
| 163 |
"""Test that audio restoration is properly integrated into connection recovery."""
|
| 164 |
# Set up completed audio state
|
yomitalk/app.py
CHANGED
|
@@ -1530,16 +1530,6 @@ class PaperPodcastApp:
|
|
| 1530 |
outputs=[generate_btn],
|
| 1531 |
)
|
| 1532 |
|
| 1533 |
-
# 定期的に音声生成の進捗を監視(3秒間隔)
|
| 1534 |
-
# 音声生成中は audio_output の更新を避けてボタン状態のみ監視
|
| 1535 |
-
audio_monitor_timer = gr.Timer(value=3.0, active=True)
|
| 1536 |
-
audio_monitor_timer.tick(
|
| 1537 |
-
fn=self.monitor_audio_generation_progress,
|
| 1538 |
-
inputs=[user_session, terms_checkbox, podcast_text],
|
| 1539 |
-
outputs=[streaming_audio_output, audio_output, generate_btn],
|
| 1540 |
-
show_progress=False, # タイマーイベントでは進捗バーを表示しない
|
| 1541 |
-
)
|
| 1542 |
-
|
| 1543 |
return app
|
| 1544 |
|
| 1545 |
def set_openai_model_name(
|
|
@@ -2098,64 +2088,6 @@ class PaperPodcastApp:
|
|
| 2098 |
|
| 2099 |
return streaming_audio, final_audio, status_message
|
| 2100 |
|
| 2101 |
-
def monitor_audio_generation_progress(
|
| 2102 |
-
self, user_session: UserSession, terms_agreed: bool, podcast_text: str
|
| 2103 |
-
) -> Tuple[Optional[str], Optional[str], Dict[str, Any]]:
|
| 2104 |
-
"""
|
| 2105 |
-
音声生成の進捗を監視し、状態を更新する
|
| 2106 |
-
進捗表示中はaudio_outputの更新を避け、wait_for_audio_completionに任せる
|
| 2107 |
-
|
| 2108 |
-
Args:
|
| 2109 |
-
user_session: ユーザーセッション
|
| 2110 |
-
terms_agreed: VOICEVOX利用規約への同意状態
|
| 2111 |
-
podcast_text: 生成されたトーク原稿
|
| 2112 |
-
|
| 2113 |
-
Returns:
|
| 2114 |
-
Tuple[Optional[str], Optional[str], Dict[str, Any]]:
|
| 2115 |
-
(streaming_audio, final_audio, button_update)
|
| 2116 |
-
"""
|
| 2117 |
-
try:
|
| 2118 |
-
if not user_session.is_audio_generation_active():
|
| 2119 |
-
# 生成が完了または停止している場合のみ、音声コンポーネントを更新
|
| 2120 |
-
if user_session.has_generated_audio():
|
| 2121 |
-
status = user_session.get_audio_generation_status()
|
| 2122 |
-
streaming_parts = status.get("streaming_parts", [])
|
| 2123 |
-
final_audio = status.get("final_audio_path")
|
| 2124 |
-
streaming_audio = streaming_parts[-1] if streaming_parts else None
|
| 2125 |
-
|
| 2126 |
-
button_state = self.update_audio_button_state(
|
| 2127 |
-
terms_agreed, podcast_text
|
| 2128 |
-
)
|
| 2129 |
-
return streaming_audio, final_audio, button_state
|
| 2130 |
-
else:
|
| 2131 |
-
# 音声が生成されていない場合は何も更新しない
|
| 2132 |
-
return (
|
| 2133 |
-
gr.update(), # 現在の値を維持
|
| 2134 |
-
gr.update(), # 現在の値を維持
|
| 2135 |
-
self.update_audio_button_state(terms_agreed, podcast_text),
|
| 2136 |
-
)
|
| 2137 |
-
else:
|
| 2138 |
-
# 音声生成中はaudio_outputの更新を避け、ボタン状態のみを更新
|
| 2139 |
-
# wait_for_audio_completion が進捗バーを管理するため競合を避ける
|
| 2140 |
-
status = user_session.get_audio_generation_status()
|
| 2141 |
-
progress = status.get("progress", 0.0)
|
| 2142 |
-
|
| 2143 |
-
progress_percent = int(progress * 100)
|
| 2144 |
-
button_state = gr.update(
|
| 2145 |
-
interactive=False, value=f"音声生成中... {progress_percent}%"
|
| 2146 |
-
)
|
| 2147 |
-
|
| 2148 |
-
# 音声コンポーネントは更新しない(wait_for_audio_completionに任せる)
|
| 2149 |
-
return gr.update(), gr.update(), button_state
|
| 2150 |
-
|
| 2151 |
-
except Exception as e:
|
| 2152 |
-
logger.error(f"Error monitoring audio generation progress: {e}")
|
| 2153 |
-
return (
|
| 2154 |
-
gr.update(),
|
| 2155 |
-
gr.update(),
|
| 2156 |
-
self.update_audio_button_state(terms_agreed, podcast_text),
|
| 2157 |
-
)
|
| 2158 |
-
|
| 2159 |
def handle_connection_recovery(
|
| 2160 |
self, user_session: UserSession, terms_agreed: bool, podcast_text: str
|
| 2161 |
) -> Tuple[Optional[str], Optional[str], Dict[str, Any]]:
|
|
@@ -2220,6 +2152,55 @@ class PaperPodcastApp:
|
|
| 2220 |
self.update_audio_button_state(terms_agreed, podcast_text),
|
| 2221 |
)
|
| 2222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2223 |
|
| 2224 |
def main() -> None:
|
| 2225 |
"""
|
|
|
|
| 1530 |
outputs=[generate_btn],
|
| 1531 |
)
|
| 1532 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1533 |
return app
|
| 1534 |
|
| 1535 |
def set_openai_model_name(
|
|
|
|
| 2088 |
|
| 2089 |
return streaming_audio, final_audio, status_message
|
| 2090 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2091 |
def handle_connection_recovery(
|
| 2092 |
self, user_session: UserSession, terms_agreed: bool, podcast_text: str
|
| 2093 |
) -> Tuple[Optional[str], Optional[str], Dict[str, Any]]:
|
|
|
|
| 2152 |
self.update_audio_button_state(terms_agreed, podcast_text),
|
| 2153 |
)
|
| 2154 |
|
| 2155 |
+
def monitor_audio_session_state(
|
| 2156 |
+
self, user_session: UserSession
|
| 2157 |
+
) -> Tuple[Dict[str, Any], Optional[str], Optional[str]]:
|
| 2158 |
+
"""
|
| 2159 |
+
Monitor and update audio generation state from user session.
|
| 2160 |
+
|
| 2161 |
+
Note: This method is deprecated and no longer used.
|
| 2162 |
+
Timer-based monitoring was removed to avoid conflicts with progress display.
|
| 2163 |
+
Audio generation now directly updates user_session state in
|
| 2164 |
+
self.generate_podcast_audio_streaming method without timer monitoring.
|
| 2165 |
+
|
| 2166 |
+
Args:
|
| 2167 |
+
user_session: User session containing audio state
|
| 2168 |
+
|
| 2169 |
+
Returns:
|
| 2170 |
+
Tuple[Dict[str, Any], Optional[str], Optional[str]]:
|
| 2171 |
+
(timer_update, streaming_audio_update, final_audio_update)
|
| 2172 |
+
"""
|
| 2173 |
+
try:
|
| 2174 |
+
# Get current audio generation status
|
| 2175 |
+
status = user_session.get_audio_generation_status()
|
| 2176 |
+
|
| 2177 |
+
# Check if audio generation is active
|
| 2178 |
+
if not user_session.is_audio_generation_active():
|
| 2179 |
+
# Stop timer if no active generation
|
| 2180 |
+
logger.debug("No active audio generation - stopping timer")
|
| 2181 |
+
return gr.update(active=False), None, None
|
| 2182 |
+
|
| 2183 |
+
# Update streaming audio if new parts are available
|
| 2184 |
+
streaming_parts = status.get("streaming_parts", [])
|
| 2185 |
+
streaming_audio = streaming_parts[-1] if streaming_parts else None
|
| 2186 |
+
|
| 2187 |
+
# Update final audio if available
|
| 2188 |
+
final_audio = status.get("final_audio_path")
|
| 2189 |
+
|
| 2190 |
+
# Check if generation is completed
|
| 2191 |
+
if status.get("status") == "completed":
|
| 2192 |
+
logger.debug("Audio generation completed - stopping timer")
|
| 2193 |
+
return gr.update(active=False), streaming_audio, final_audio
|
| 2194 |
+
|
| 2195 |
+
# Continue monitoring
|
| 2196 |
+
progress = status.get("progress", 0.0)
|
| 2197 |
+
logger.debug(f"Audio generation progress: {progress:.1%}")
|
| 2198 |
+
|
| 2199 |
+
return gr.update(active=True), streaming_audio, final_audio
|
| 2200 |
+
except Exception as e:
|
| 2201 |
+
logger.error(f"Error monitoring audio session state: {e}")
|
| 2202 |
+
return gr.update(active=False), None, None
|
| 2203 |
+
|
| 2204 |
|
| 2205 |
def main() -> None:
|
| 2206 |
"""
|