2026-06-30 21:00:20 +08:00
|
|
|
import os
|
|
|
|
|
import base64
|
|
|
|
|
import requests
|
|
|
|
|
from io import BytesIO
|
|
|
|
|
|
2026-06-30 23:47:23 +08:00
|
|
|
def synthesize_minimax(text, speed=1.0, pitch=0, volume=1.0, emotion='neutral'):
|
2026-06-30 21:00:20 +08:00
|
|
|
"""调用MiniMax TTS API"""
|
|
|
|
|
api_key = os.getenv('MINIMAX_API_KEY', '')
|
|
|
|
|
if not api_key:
|
|
|
|
|
raise ValueError('MINIMAX_API_KEY未设置')
|
|
|
|
|
|
|
|
|
|
# 将音量映射到0-100
|
|
|
|
|
volume_int = int(volume * 100)
|
|
|
|
|
|
|
|
|
|
url = 'https://api.minimax.chat/v1/t2a_v2'
|
|
|
|
|
headers = {
|
|
|
|
|
'Authorization': f'Bearer {api_key}',
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
payload = {
|
|
|
|
|
'model': 'speech-2.8-hd',
|
|
|
|
|
'text': text,
|
|
|
|
|
'stream': False,
|
|
|
|
|
'voice_setting': {
|
2026-07-02 22:06:37 +08:00
|
|
|
'voice_id': 'lanhao_military_v2',
|
2026-06-30 21:00:20 +08:00
|
|
|
'speed': speed,
|
|
|
|
|
'vol': volume_int,
|
|
|
|
|
'pitch': pitch,
|
2026-06-30 23:47:23 +08:00
|
|
|
'emotion': emotion,
|
2026-06-30 21:00:20 +08:00
|
|
|
},
|
|
|
|
|
'audio_setting': {
|
|
|
|
|
'audio_sample_rate': 32000,
|
|
|
|
|
'bitrate': 128000,
|
|
|
|
|
'format': 'mp3'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response = requests.post(url, json=payload, headers=headers, timeout=60)
|
|
|
|
|
|
2026-07-03 00:23:55 +08:00
|
|
|
if response.status_code == 402:
|
|
|
|
|
raise Exception('MiniMax 余额不足,请联系管理员充值')
|
|
|
|
|
if response.status_code == 401 or response.status_code == 403:
|
|
|
|
|
raise Exception('MiniMax API密钥无效,请联系管理员')
|
|
|
|
|
if response.status_code == 429:
|
|
|
|
|
raise Exception('MiniMax 请求过于频繁,请稍后再试')
|
2026-06-30 21:00:20 +08:00
|
|
|
if response.status_code != 200:
|
2026-07-03 00:23:55 +08:00
|
|
|
raise Exception(f'MiniMax 服务异常({response.status_code}),请稍后再试')
|
2026-06-30 21:00:20 +08:00
|
|
|
|
|
|
|
|
result = response.json()
|
|
|
|
|
|
|
|
|
|
if 'data' in result and 'audio' in result['data']:
|
|
|
|
|
audio_hex = result['data']['audio']
|
|
|
|
|
audio_bytes = bytes.fromhex(audio_hex)
|
|
|
|
|
return audio_bytes
|
|
|
|
|
|
|
|
|
|
raise Exception(f'MiniMax返回格式异常: {result}')
|