import os import uuid import requests import base64 def synthesize_doubao(text, speed=1.0, pitch=0, volume=1.0, emotion='neutral'): """调用火山引擎豆包 Seed-ICL 2.0 语音合成 API""" api_key = os.getenv('DOUBAO_API_KEY', '') if not api_key: raise ValueError('DOUBAO_API_KEY未设置') url = 'https://openspeech.bytedance.com/api/v1/tts' headers = { 'x-api-key': api_key, 'Content-Type': 'application/json', 'X-Api-Resource-Id': 'seed-icl-2.0' } payload = { 'app': { 'cluster': 'volcano_icl' }, 'user': { 'uid': 'military_tech_voice' }, 'audio': { 'voice_type': 'S_LK0j18H72', 'encoding': 'mp3', 'speed_ratio': speed, 'pitch_ratio': max(0.1, min(3.0, 1.0 + pitch / 12)), # 前端-12~12映射到0.1~3.0 'volume_ratio': max(0.1, min(3.0, volume)), # 前端0~10,API 0.1~3.0 'bitrate': 128000, }, 'request': { 'reqid': str(uuid.uuid4()), 'text': text, 'operation': 'query', 'model_type': 4, # ICL 2.0 模型 } } response = requests.post(url, json=payload, headers=headers, timeout=60) if response.status_code != 200: raise Exception(f'豆包API错误: {response.status_code} - {response.text}') result = response.json() # 豆包返回格式: {"code": 3000, "data": "base64编码的音频"} if result.get('code') == 3000 and result.get('data'): audio_bytes = base64.b64decode(result['data']) return audio_bytes # 错误处理 error_msg = result.get('message', '未知错误') error_code = result.get('code', 'unknown') raise Exception(f'豆包返回错误 [{error_code}]: {error_msg}')