'commit'
This commit is contained in:
Binary file not shown.
@@ -1,23 +1,23 @@
|
||||
import logging
|
||||
import uuid
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query # 添加Query导入
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
from typing import Optional
|
||||
import os
|
||||
import uuid
|
||||
import time
|
||||
from Util.ObsUtil import ObsUploader
|
||||
from Config.Config import OBS_BUCKET, OBS_SERVER
|
||||
# 导入TTS生成类
|
||||
from Util.GengerateAudio import ByteDanceTTS
|
||||
|
||||
# 创建声音生成路由
|
||||
router = APIRouter(prefix="/api/tts", tags=["声音生成"])
|
||||
|
||||
# 配置日志
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 初始化TTS实例
|
||||
router = APIRouter(prefix="/api/tts", tags=["文生音频"])
|
||||
# 初始化TTS实例(全局单例,避免重复创建)
|
||||
tts_instance = ByteDanceTTS()
|
||||
|
||||
class TextToSpeechRequest(BaseModel):
|
||||
"""文本转语音请求参数"""
|
||||
text: str
|
||||
voice_type: Optional[str] = None
|
||||
speed_ratio: Optional[float] = 1.0
|
||||
@@ -26,16 +26,6 @@ class TextToSpeechRequest(BaseModel):
|
||||
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
|
||||
|
||||
|
||||
@router.get("/voice-categories")
|
||||
async def get_voice_categories():
|
||||
try:
|
||||
@@ -52,6 +42,7 @@ async def get_voice_categories():
|
||||
detail=f"获取音色分类失败: {str(e)}"
|
||||
)
|
||||
|
||||
|
||||
# 恢复原始的音色列表接口路由
|
||||
@router.get("/voices")
|
||||
async def get_voices_by_category(category: str = Query(...)): # 现在Query已定义
|
||||
@@ -62,7 +53,7 @@ async def get_voices_by_category(category: str = Query(...)): # 现在Query已
|
||||
"success": False,
|
||||
"message": f"未找到分类 '{category}' 下的音色"
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"data": voices,
|
||||
@@ -93,61 +84,62 @@ async def get_all_voices():
|
||||
logger.error(f"获取所有音色分类和列表错误: {e}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"获取所有音色分类和列表失败: {str(e)}"
|
||||
)
|
||||
detail=f"获取所有音色分类和列表失败: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/generate", response_model=TextToSpeechResponse)
|
||||
async def generate_audio(request: TextToSpeechRequest):
|
||||
"""
|
||||
文本转语音接口
|
||||
根据输入文本和语音参数生成音频文件
|
||||
"""
|
||||
@router.post("/generate")
|
||||
async def generate_audio(request: TextToSpeechRequest, background_tasks: BackgroundTasks):
|
||||
try:
|
||||
# 生成唯一文件名
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# 确保输出目录存在
|
||||
# 1. 生成唯一文件名和路径
|
||||
timestamp = int(time.time())
|
||||
filename = f"tts_{uuid.uuid4().hex[:8]}_{timestamp}.mp3"
|
||||
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)
|
||||
|
||||
# 调用TTS工具生成音频
|
||||
|
||||
# 2. 使用ByteDanceTTS生成音频文件
|
||||
# ------------------- TTS生成逻辑开始 -------------------
|
||||
audio_data = tts_instance.generate_audio(
|
||||
text=request.text,
|
||||
output_path=output_path,
|
||||
voice_type=request.voice_type,
|
||||
speed_ratio=request.speed_ratio,
|
||||
volume_ratio=request.volume_ratio,
|
||||
pitch_ratio=request.pitch_ratio,
|
||||
encoding=request.encoding,
|
||||
output_path=output_path
|
||||
encoding=request.encoding
|
||||
)
|
||||
|
||||
if audio_data:
|
||||
# 构建可访问的URL
|
||||
audio_url = f"/{output_path}"
|
||||
|
||||
return TextToSpeechResponse(
|
||||
success=True,
|
||||
message="音频生成成功",
|
||||
audio_url=audio_url,
|
||||
audio_format=request.encoding,
|
||||
request_id=str(uuid.uuid4())
|
||||
)
|
||||
else:
|
||||
return TextToSpeechResponse(
|
||||
success=False,
|
||||
message="音频生成失败"
|
||||
)
|
||||
|
||||
if not audio_data:
|
||||
raise HTTPException(status_code=500, detail="TTS音频生成失败")
|
||||
# ------------------- TTS生成逻辑结束 -------------------
|
||||
|
||||
# 3. 上传到OBS
|
||||
obs_uploader = ObsUploader()
|
||||
obs_object_key = f"HuangHai/tts/{filename}"
|
||||
upload_success, upload_result = obs_uploader.upload_file(obs_object_key, output_path)
|
||||
|
||||
if not upload_success:
|
||||
# 上传失败,清理文件并抛出异常
|
||||
background_tasks.add_task(os.remove, output_path) if os.path.exists(output_path) else None
|
||||
raise HTTPException(status_code=500, detail=f"OBS上传失败: {upload_result.get('errorMessage', '未知错误')}")
|
||||
|
||||
# 4. 构造OBS访问URL
|
||||
obs_url = f"https://{OBS_BUCKET}.{OBS_SERVER}/{obs_object_key}"
|
||||
|
||||
# 5. 安排后台任务删除本地文件
|
||||
background_tasks.add_task(os.remove, output_path) if os.path.exists(output_path) else None
|
||||
|
||||
# 6. 返回OBS URL
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "音频生成并上传成功",
|
||||
"audio_url": obs_url, # 确保此处没有添加任何引号或反引号
|
||||
"filename": filename,
|
||||
"audio_size": len(audio_data) / 1024 # 音频大小(KB)
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"文本转语音接口错误: {e}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"音频生成失败: {str(e)}"
|
||||
)
|
||||
# 捕获所有异常并清理文件
|
||||
if 'output_path' in locals() and os.path.exists(output_path):
|
||||
background_tasks.add_task(os.remove, output_path)
|
||||
raise HTTPException(status_code=500, detail=f"处理失败: {str(e)}")
|
||||
|
@@ -64,7 +64,7 @@ app.add_middleware(
|
||||
)
|
||||
|
||||
# 挂载静态文件目录
|
||||
app.mount("/static", StaticFiles(directory="Static"), name="static")
|
||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
|
||||
# 加载路由
|
||||
app.include_router(zuowen_router) # 作文批阅路由
|
||||
|
BIN
dsLightRag/static/audio/tts_20250902_074150_a7eb0d9a.mp3
Normal file
BIN
dsLightRag/static/audio/tts_20250902_074150_a7eb0d9a.mp3
Normal file
Binary file not shown.
BIN
dsLightRag/static/audio/tts_20250902_074443_0df4889a.mp3
Normal file
BIN
dsLightRag/static/audio/tts_20250902_074443_0df4889a.mp3
Normal file
Binary file not shown.
BIN
dsLightRag/static/audio/tts_20250902_074755_81ca2382.mp3
Normal file
BIN
dsLightRag/static/audio/tts_20250902_074755_81ca2382.mp3
Normal file
Binary file not shown.
BIN
dsLightRag/static/audio/tts_20250902_075228_90ccd2a8.mp3
Normal file
BIN
dsLightRag/static/audio/tts_20250902_075228_90ccd2a8.mp3
Normal file
Binary file not shown.
@@ -486,11 +486,14 @@
|
||||
const data = await response.json();
|
||||
console.log('音频生成结果:', data);
|
||||
|
||||
if (data.success) {
|
||||
if (data.status==='success') {
|
||||
// 显示成功消息
|
||||
showSuccess('语音生成成功');
|
||||
|
||||
// 设置音频播放器
|
||||
if(data.audio_url){
|
||||
console.log('音频文件地址:', data.audio_url)
|
||||
}
|
||||
audioPlayer.src = data.audio_url;
|
||||
audioResult.style.display = 'block';
|
||||
|
||||
|
Reference in New Issue
Block a user