idacosta commited on
Commit
2e4ee45
·
1 Parent(s): 8bfad73

Fix podcast playback: valid MP3 output, Gradio file route, and TTS input cap

Browse files
Files changed (2) hide show
  1. pages/artifacts.py +1 -0
  2. services/podcast_service.py +18 -18
pages/artifacts.py CHANGED
@@ -60,6 +60,7 @@ def _render_artifact_content(artifact) -> str:
60
  f'border-radius:10px;">'
61
  f'<div style="font-size:0.82rem; color:#8090d0; margin-bottom:8px;">🎧 Podcast Audio</div>'
62
  f'<audio controls style="width:100%; border-radius:6px;">'
 
63
  f'<source src="/file={artifact.audio_path}" type="audio/mpeg">'
64
  f'Your browser does not support the audio element.'
65
  f'</audio>'
 
60
  f'border-radius:10px;">'
61
  f'<div style="font-size:0.82rem; color:#8090d0; margin-bottom:8px;">🎧 Podcast Audio</div>'
62
  f'<audio controls style="width:100%; border-radius:6px;">'
63
+ f'<source src="/gradio_api/file={artifact.audio_path}" type="audio/mpeg">'
64
  f'<source src="/file={artifact.audio_path}" type="audio/mpeg">'
65
  f'Your browser does not support the audio element.'
66
  f'</audio>'
services/podcast_service.py CHANGED
@@ -104,7 +104,7 @@ def _tts_request(text: str, token: str) -> bytes | None:
104
 
105
 
106
  def _synthesize_audio(lines: list[tuple[str, str]], output_path: Path) -> bool:
107
- """Synthesize audio via OpenAI TTS. Handles 4096 char limit by chunking."""
108
  try:
109
  from openai import OpenAI
110
 
@@ -115,26 +115,26 @@ def _synthesize_audio(lines: list[tuple[str, str]], output_path: Path) -> bool:
115
  full_text = "\n".join([f"{speaker}: {text}" for speaker, text in lines])
116
 
117
  logger.info("TTS: Generating audio for %d lines (%d chars)", len(lines), len(full_text))
118
-
119
- # OpenAI TTS has 4096 character limit, so chunk the text
120
- MAX_CHARS = 4000 # Leave buffer for safety
121
- chunks = _chunk_text(full_text, MAX_CHARS)
122
- logger.info("Split into %d chunks for TTS", len(chunks))
123
-
124
- # Generate audio for each chunk and collect them
125
- audio_data = b""
126
- for i, chunk in enumerate(chunks):
127
- logger.info("TTS chunk %d/%d (%d chars)", i + 1, len(chunks), len(chunk))
128
- response = client.audio.speech.create(
129
- model="tts-1",
130
- voice="alloy", # neutral voice
131
- input=chunk,
132
  )
133
- audio_data += response.content
134
 
135
- # Write combined audio to file
 
 
 
 
 
 
136
  with open(str(output_path), "wb") as f:
137
- f.write(audio_data)
138
 
139
  file_size = os.path.getsize(str(output_path))
140
  logger.info("Podcast audio saved to %s (%d bytes)", output_path, file_size)
 
104
 
105
 
106
  def _synthesize_audio(lines: list[tuple[str, str]], output_path: Path) -> bool:
107
+ """Synthesize audio via OpenAI TTS and save a valid MP3 file."""
108
  try:
109
  from openai import OpenAI
110
 
 
115
  full_text = "\n".join([f"{speaker}: {text}" for speaker, text in lines])
116
 
117
  logger.info("TTS: Generating audio for %d lines (%d chars)", len(lines), len(full_text))
118
+
119
+ max_chars = 4000
120
+ if len(full_text) > max_chars:
121
+ trimmed = _chunk_text(full_text, max_chars)[0]
122
+ logger.warning(
123
+ "TTS input exceeded limit; trimming from %d to %d chars",
124
+ len(full_text),
125
+ len(trimmed),
 
 
 
 
 
 
126
  )
127
+ full_text = trimmed
128
 
129
+ # Generate a single MP3 response and write it directly.
130
+ response = client.audio.speech.create(
131
+ model="tts-1",
132
+ voice="alloy",
133
+ input=full_text,
134
+ )
135
+
136
  with open(str(output_path), "wb") as f:
137
+ f.write(response.content)
138
 
139
  file_size = os.path.getsize(str(output_path))
140
  logger.info("Podcast audio saved to %s (%d bytes)", output_path, file_size)