Spaces:
Sleeping
Sleeping
Fix OpenAI TTS by chunking text to respect 4096 char limit
Browse files- services/podcast_service.py +18 -9
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.
|
| 108 |
try:
|
| 109 |
from openai import OpenAI
|
| 110 |
|
|
@@ -116,16 +116,25 @@ def _synthesize_audio(lines: list[tuple[str, str]], output_path: Path) -> bool:
|
|
| 116 |
|
| 117 |
logger.info("TTS: Generating audio for %d lines (%d chars)", len(lines), len(full_text))
|
| 118 |
|
| 119 |
-
#
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
-
# Write
|
| 127 |
with open(str(output_path), "wb") as f:
|
| 128 |
-
f.write(
|
| 129 |
|
| 130 |
file_size = os.path.getsize(str(output_path))
|
| 131 |
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. Handles 4096 char limit by chunking."""
|
| 108 |
try:
|
| 109 |
from openai import OpenAI
|
| 110 |
|
|
|
|
| 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)
|