-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtts.py
More file actions
executable file
·140 lines (118 loc) · 3.63 KB
/
Copy pathtts.py
File metadata and controls
executable file
·140 lines (118 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python3
"""
火山引擎 TTS Skill for OpenClaw
"""
import sys
import json
import os
import requests
import base64
import uuid
from pathlib import Path
def load_config():
"""加载配置文件"""
script_dir = Path(__file__).parent
config_path = script_dir / "config.json"
if not config_path.exists():
print("❌ 配置文件不存在,请先创建 config.json")
print(f"参考: {script_dir / 'config.example.json'}")
sys.exit(1)
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
def synthesize(text, voice=None, speed=None, volume=None, format=None, output=None):
"""合成语音"""
config = load_config()
# 使用默认值
voice = voice or config.get("default_voice")
speed = speed or config.get("default_speed", 1.0)
volume = volume or config.get("default_volume", 1.0)
format = format or config.get("default_format", "mp3")
# 构建请求
headers = {
"Authorization": f"Bearer;{config['access_token']}",
"Content-Type": "application/json"
}
payload = {
"app": {
"appid": config["appid"],
"token": "access_token",
"cluster": "volcano_tts"
},
"user": {
"uid": "openclaw_user"
},
"audio": {
"voice_type": voice,
"encoding": format,
"speed_ratio": float(speed),
"loudness_ratio": float(volume),
"rate": 24000
},
"request": {
"reqid": str(uuid.uuid4()),
"text": text,
"operation": "query"
}
}
# 发送请求
api_url = config.get("api_url", "https://openspeech.bytedance.com/api/v1/tts")
response = requests.post(api_url, headers=headers, json=payload, timeout=30)
if response.status_code != 200:
return {
"success": False,
"error": f"HTTP {response.status_code}: {response.text}"
}
result = response.json()
if result.get("code") != 3000:
return {
"success": False,
"error": f"错误码 {result.get('code')}: {result.get('message')}"
}
# 解码音频
audio_data = base64.b64decode(result["data"])
# 保存文件
if not output:
output = f"tts_output_{uuid.uuid4().hex[:8]}.{format}"
output_path = Path(output)
with open(output_path, "wb") as f:
f.write(audio_data)
duration = result.get("addition", {}).get("duration", "未知")
return {
"success": True,
"file": str(output_path.absolute()),
"duration_ms": duration,
"voice": voice,
"text": text
}
def main():
"""命令行入口"""
if len(sys.argv) < 2:
print("用法: python tts.py <文本> [--voice 音色] [--speed 语速] [--volume 音量] [--format 格式] [--output 输出文件]")
sys.exit(1)
# 解析参数
text = sys.argv[1]
args = {}
i = 2
while i < len(sys.argv):
if sys.argv[i].startswith("--"):
key = sys.argv[i][2:]
if i + 1 < len(sys.argv):
args[key] = sys.argv[i + 1]
i += 2
else:
i += 1
else:
i += 1
# 合成
result = synthesize(
text=text,
voice=args.get("voice"),
speed=args.get("speed"),
volume=args.get("volume"),
format=args.get("format"),
output=args.get("output")
)
# 输出结果
print(json.dumps(result, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()