Happy_language/app/routes/voice_test.py
superlishunqin 28b23647e6 test-api
2025-09-15 00:34:51 +08:00

259 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
语音测试相关路由
"""
import os
import json
import tempfile
from flask import Blueprint, request, jsonify, render_template, current_app
from flask_login import login_required, current_user
from app.services.cosyvoice_service import cosyvoice_service
from werkzeug.utils import secure_filename
import logging
logger = logging.getLogger(__name__)
voice_test_bp = Blueprint('voice_test', __name__)
@voice_test_bp.route('/voice-test')
@login_required
def voice_test_page():
"""语音测试页面"""
return render_template('voice_test/index.html')
@voice_test_bp.route('/api/voice-test/connection', methods=['POST'])
@login_required
def test_connection():
"""测试CosyVoice服务连接"""
try:
result = cosyvoice_service.test_connection()
return jsonify(result)
except Exception as e:
logger.error(f"连接测试失败: {str(e)}")
return jsonify({
"success": False,
"message": f"测试失败: {str(e)}"
})
@voice_test_bp.route('/api/voice-test/voices', methods=['GET'])
@login_required
def get_voices():
"""获取可用音色列表"""
try:
voices = cosyvoice_service.get_available_voices()
return jsonify({
"success": True,
"voices": voices
})
except Exception as e:
logger.error(f"获取音色列表失败: {str(e)}")
return jsonify({
"success": False,
"message": f"获取失败: {str(e)}"
})
@voice_test_bp.route('/api/voice-test/generate/preset', methods=['POST'])
@login_required
def generate_with_preset_voice():
"""使用预训练音色生成语音"""
try:
data = request.get_json()
text = data.get('text', '')
voice = data.get('voice', '中文女')
seed = data.get('seed', 42)
speed = data.get('speed', 1.0)
if not text:
return jsonify({
"success": False,
"message": "请输入要合成的文本"
})
# 生成语音
stream_audio, full_audio = cosyvoice_service.generate_speech_with_preset_voice(
text=text,
voice=voice,
seed=seed,
speed=speed
)
if full_audio:
return jsonify({
"success": True,
"message": "语音生成成功",
"audio_url": full_audio,
"stream_audio_url": stream_audio
})
else:
return jsonify({
"success": False,
"message": "语音生成失败"
})
except Exception as e:
logger.error(f"预训练音色生成失败: {str(e)}")
return jsonify({
"success": False,
"message": f"生成失败: {str(e)}"
})
@voice_test_bp.route('/api/voice-test/generate/natural', methods=['POST'])
@login_required
def generate_with_natural_control():
"""使用自然语言控制生成语音"""
try:
data = request.get_json()
text = data.get('text', '')
instruction = data.get('instruction', '请用温柔甜美的女声朗读')
seed = data.get('seed', 42)
if not text:
return jsonify({
"success": False,
"message": "请输入要合成的文本"
})
# 生成语音
stream_audio, full_audio = cosyvoice_service.generate_speech_with_natural_control(
text=text,
instruction=instruction,
seed=seed
)
if full_audio:
return jsonify({
"success": True,
"message": "语音生成成功",
"audio_url": full_audio,
"stream_audio_url": stream_audio
})
else:
return jsonify({
"success": False,
"message": "语音生成失败"
})
except Exception as e:
logger.error(f"自然语言控制生成失败: {str(e)}")
return jsonify({
"success": False,
"message": f"生成失败: {str(e)}"
})
@voice_test_bp.route('/api/voice-test/upload-audio', methods=['POST'])
@login_required
def upload_audio():
"""上传音频文件用于语音克隆"""
try:
if 'audio' not in request.files:
return jsonify({
"success": False,
"message": "请选择音频文件"
})
file = request.files['audio']
if file.filename == '':
return jsonify({
"success": False,
"message": "请选择音频文件"
})
# 检查文件类型
allowed_extensions = {'wav', 'mp3', 'm4a', 'flac'}
if not ('.' in file.filename and
file.filename.rsplit('.', 1)[1].lower() in allowed_extensions):
return jsonify({
"success": False,
"message": "不支持的音频格式请使用WAV、MP3、M4A或FLAC格式"
})
# 保存文件到临时目录
filename = secure_filename(file.filename)
temp_dir = tempfile.gettempdir()
file_path = os.path.join(temp_dir, f"voice_clone_{current_user.id}_{filename}")
file.save(file_path)
# 尝试识别音频内容
recognized_text = cosyvoice_service.recognize_audio(file_path)
return jsonify({
"success": True,
"message": "音频上传成功",
"file_path": file_path,
"recognized_text": recognized_text
})
except Exception as e:
logger.error(f"音频上传失败: {str(e)}")
return jsonify({
"success": False,
"message": f"上传失败: {str(e)}"
})
@voice_test_bp.route('/api/voice-test/generate/clone', methods=['POST'])
@login_required
def generate_with_voice_cloning():
"""使用语音克隆生成语音"""
try:
data = request.get_json()
text = data.get('text', '')
reference_audio_path = data.get('reference_audio_path', '')
reference_text = data.get('reference_text', '')
seed = data.get('seed', 42)
if not text:
return jsonify({
"success": False,
"message": "请输入要合成的文本"
})
if not reference_audio_path or not os.path.exists(reference_audio_path):
return jsonify({
"success": False,
"message": "请先上传参考音频"
})
# 生成语音
stream_audio, full_audio = cosyvoice_service.generate_speech_with_voice_cloning(
text=text,
reference_audio_path=reference_audio_path,
reference_text=reference_text,
seed=seed
)
if full_audio:
return jsonify({
"success": True,
"message": "语音克隆成功",
"audio_url": full_audio,
"stream_audio_url": stream_audio
})
else:
return jsonify({
"success": False,
"message": "语音克隆失败"
})
except Exception as e:
logger.error(f"语音克隆失败: {str(e)}")
return jsonify({
"success": False,
"message": f"克隆失败: {str(e)}"
})
@voice_test_bp.route('/api/voice-test/random-seed', methods=['GET'])
@login_required
def get_random_seed():
"""获取随机种子"""
try:
seed = cosyvoice_service.generate_random_seed()
return jsonify({
"success": True,
"seed": seed
})
except Exception as e:
logger.error(f"获取随机种子失败: {str(e)}")
return jsonify({
"success": False,
"message": f"获取失败: {str(e)}"
})