Files
dsProject/dsLightRag/Routes/ttsRoute.py

153 lines
4.8 KiB
Python
Raw Normal View History

2025-09-02 06:55:13 +08:00
import logging
import uuid
from typing import Optional
2025-09-02 07:36:42 +08:00
from fastapi import APIRouter, HTTPException, Query # 添加Query导入
2025-09-02 06:55:13 +08:00
from pydantic import BaseModel
from Util.GengerateAudio import ByteDanceTTS
# 创建声音生成路由
router = APIRouter(prefix="/api/tts", tags=["声音生成"])
# 配置日志
logger = logging.getLogger(__name__)
# 初始化TTS实例
tts_instance = ByteDanceTTS()
class TextToSpeechRequest(BaseModel):
"""文本转语音请求参数"""
text: str
voice_type: Optional[str] = None
speed_ratio: Optional[float] = 1.0
volume_ratio: Optional[float] = 1.0
pitch_ratio: Optional[float] = 1.0
encoding: Optional[str] = "mp3"
class TextToSpeechResponse(BaseModel):
"""文本转语音响应"""
success: bool
message: str
audio_url: Optional[str] = None
audio_size: Optional[float] = None
audio_format: Optional[str] = None
request_id: Optional[str] = None
2025-09-02 07:36:42 +08:00
@router.get("/voice-categories")
2025-09-02 06:55:13 +08:00
async def get_voice_categories():
try:
categories = tts_instance.get_all_categories()
return {
"success": True,
2025-09-02 07:36:42 +08:00
"data": categories, # 恢复为原始的 data 字段
2025-09-02 06:55:13 +08:00
"message": "获取音色分类成功"
}
except Exception as e:
logger.error(f"获取音色分类错误: {e}")
raise HTTPException(
status_code=500,
detail=f"获取音色分类失败: {str(e)}"
)
2025-09-02 07:36:42 +08:00
# 恢复原始的音色列表接口路由
@router.get("/voices")
async def get_voices_by_category(category: str = Query(...)): # 现在Query已定义
2025-09-02 06:55:13 +08:00
try:
voices = tts_instance.get_voices_by_category(category)
if not voices:
return {
"success": False,
"message": f"未找到分类 '{category}' 下的音色"
}
2025-09-02 07:36:42 +08:00
2025-09-02 06:55:13 +08:00
return {
"success": True,
"data": voices,
"message": f"获取分类 '{category}' 下的音色成功"
}
except Exception as e:
logger.error(f"获取分类 '{category}' 下的音色错误: {e}")
raise HTTPException(
status_code=500,
detail=f"获取分类 '{category}' 下的音色失败: {str(e)}"
)
2025-09-02 07:36:42 +08:00
@router.get("/all")
2025-09-02 06:55:13 +08:00
async def get_all_voices():
"""
获取所有音色分类和音色列表接口
返回所有音色分类和每个分类下的音色列表
"""
try:
all_voices = tts_instance.get_all_voices()
return {
"success": True,
"data": all_voices,
"message": "获取所有音色分类和列表成功"
}
except Exception as e:
logger.error(f"获取所有音色分类和列表错误: {e}")
raise HTTPException(
status_code=500,
detail=f"获取所有音色分类和列表失败: {str(e)}"
)
@router.post("/generate", response_model=TextToSpeechResponse)
async def generate_audio(request: TextToSpeechRequest):
"""
文本转语音接口
根据输入文本和语音参数生成音频文件
"""
try:
2025-09-02 07:40:20 +08:00
# 生成唯一文件名
import os
from datetime import datetime
# 确保输出目录存在
output_dir = "static/audio"
os.makedirs(output_dir, exist_ok=True)
# 生成唯一文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
unique_id = str(uuid.uuid4())[:8]
filename = f"tts_{timestamp}_{unique_id}.{request.encoding}"
output_path = os.path.join(output_dir, filename)
2025-09-02 06:55:13 +08:00
# 调用TTS工具生成音频
2025-09-02 07:40:20 +08:00
audio_data = tts_instance.generate_audio(
2025-09-02 06:55:13 +08:00
text=request.text,
voice_type=request.voice_type,
speed_ratio=request.speed_ratio,
volume_ratio=request.volume_ratio,
pitch_ratio=request.pitch_ratio,
2025-09-02 07:40:20 +08:00
encoding=request.encoding,
output_path=output_path
2025-09-02 06:55:13 +08:00
)
2025-09-02 07:40:20 +08:00
if audio_data:
# 构建可访问的URL
audio_url = f"/{output_path}"
2025-09-02 06:55:13 +08:00
return TextToSpeechResponse(
success=True,
message="音频生成成功",
audio_url=audio_url,
audio_format=request.encoding,
request_id=str(uuid.uuid4())
)
else:
return TextToSpeechResponse(
success=False,
message="音频生成失败"
)
except Exception as e:
logger.error(f"文本转语音接口错误: {e}")
raise HTTPException(
status_code=500,
detail=f"音频生成失败: {str(e)}"
)