Task 19: Update TTS generation endpoint to accept edited scripts
- Modified TTSRequest to accept optional segments array - Updated generate_audiobook endpoint to use segments if provided - Added generate_audiobook_from_segments method to TTSService - Ensured backward compatibility with text-based generation - Added comprehensive tests for segment-based generation - All tests passing (7/7) Requirements: 15.7
This commit is contained in:
@@ -56,7 +56,8 @@ class RoleVoiceMapping(BaseModel):
|
||||
|
||||
class TTSRequest(BaseModel):
|
||||
"""Request model for TTS generation endpoint."""
|
||||
text: str = Field(..., description="Text to convert to speech")
|
||||
segments: Optional[List[ScriptSegment]] = Field(None, description="Optional edited script segments")
|
||||
text: Optional[str] = Field(None, description="Text to convert to speech (used if segments not provided)")
|
||||
lang: str = Field(..., description="Language code (a, b, f, j)")
|
||||
roles: List[RoleVoiceMapping] = Field(..., description="Role to voice mappings")
|
||||
speed: Optional[float] = Field(1.0, description="Playback speed (0.5-1.5)")
|
||||
@@ -253,11 +254,24 @@ async def generate_audiobook(request: TTSRequest):
|
||||
"""
|
||||
logger.info(
|
||||
f"Audio generation requested: lang={request.lang}, "
|
||||
f"roles={len(request.roles)}, speed={request.speed}"
|
||||
f"roles={len(request.roles)}, speed={request.speed}, "
|
||||
f"segments={len(request.segments) if request.segments else 0}"
|
||||
)
|
||||
|
||||
# Validate required fields (Pydantic handles basic validation)
|
||||
if not request.text or not request.text.strip():
|
||||
# Validate that either segments or text is provided
|
||||
if not request.segments and not request.text:
|
||||
logger.error("Neither segments nor text provided")
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content={
|
||||
"error": "ValidationError",
|
||||
"message": "Either segments or text must be provided",
|
||||
"details": {"fields": ["segments", "text"]}
|
||||
}
|
||||
)
|
||||
|
||||
# Validate text if provided and no segments
|
||||
if not request.segments and request.text and not request.text.strip():
|
||||
logger.error("Empty text provided")
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
@@ -316,13 +330,23 @@ async def generate_audiobook(request: TTSRequest):
|
||||
role_voice_map = {role.id: role.voice for role in request.roles}
|
||||
|
||||
try:
|
||||
# Generate audiobook
|
||||
audio_bytes = await tts_service.generate_audiobook(
|
||||
text=request.text,
|
||||
lang=request.lang,
|
||||
role_voice_map=role_voice_map,
|
||||
speed=request.speed
|
||||
)
|
||||
# Generate audiobook using segments if provided, otherwise use text
|
||||
if request.segments:
|
||||
logger.info(f"Generating audiobook from {len(request.segments)} edited segments")
|
||||
audio_bytes = await tts_service.generate_audiobook_from_segments(
|
||||
segments=[(seg.speaker, seg.text) for seg in request.segments],
|
||||
lang=request.lang,
|
||||
role_voice_map=role_voice_map,
|
||||
speed=request.speed
|
||||
)
|
||||
else:
|
||||
logger.info("Generating audiobook from text with automatic segmentation")
|
||||
audio_bytes = await tts_service.generate_audiobook(
|
||||
text=request.text,
|
||||
lang=request.lang,
|
||||
role_voice_map=role_voice_map,
|
||||
speed=request.speed
|
||||
)
|
||||
|
||||
# Create streaming response with proper headers
|
||||
return StreamingResponse(
|
||||
|
||||
Reference in New Issue
Block a user