最近在帮朋友做外语学习APP时,遇到一个头疼的问题:如何快速生成不同语言的发音示范?试过几个主流TTS服务后,最终锁定了edge-tts这个宝藏工具。它最大的优势是完全免费且支持49种语言/154种声音,连斯瓦希里语这样的冷门语言都能找到对应的语音模型。
对比其他方案,edge-tts有三个杀手级特性:
实测生成1分钟中文语音只需2秒,英文约1.8秒,而且语音自然度明显优于很多收费方案。有次我同时生成中、英、西三语版本的教学内容,整个过程不到10秒就完成了。
建议使用Python 3.8+版本,太老的版本可能会遇到异步IO兼容问题。我这里用conda创建独立环境:
bash复制conda create -n tts python=3.10
conda activate tts
安装核心库只需要一行命令:
bash复制pip install edge-tts
常见踩坑点:
/Applications/Python\ 3.10/Install\ Certificates.command更新证书pip install -i https://pypi.tuna.tsinghua.edu.cn/simple edge-tts新建一个test_voices.py文件:
python复制import asyncio
from edge_tts import VoicesManager
async def list_voices():
voices = await VoicesManager.create()
print(f"共找到{len(voices.voices)}种语音")
asyncio.run(list_voices())
运行后如果看到类似这样的输出,说明环境配置正确:
code复制共找到154种语音
先看最简单的单次转换场景。假设我们要把英文课文转成音频:
python复制import asyncio
import edge_tts
async def text_to_speech():
communicate = edge_tts.Communicate(
text="The quick brown fox jumps over the lazy dog.",
voice="en-US-AriaNeural"
)
await communicate.save("output.mp3")
asyncio.run(text_to_speech())
参数说明:
text: 支持SSML标记语言,可以插入停顿 <break time="500ms"/>voice: 完整的语音ID可以从微软官方文档查询rate/volume/pitch: 分别控制语速、音量和音高这才是edge-tts的精华功能。通过VoicesManager可以智能匹配语音:
python复制async def multi_lang_tts():
voices = await VoicesManager.create()
# 中文女声列表
chinese_female = voices.find(Gender="Female", Language="zh")
# 西班牙语男声(墨西哥口音)
spanish_male = voices.find(Gender="Male", Locale="es-MX")
# 随机选择符合条件的声音
chosen_voice = random.choice(spanish_male)["Name"]
communicate = edge_tts.Communicate(
text="¡Bienvenidos a mi canal!",
voice=chosen_voice
)
await communicate.save("welcome_spanish.mp3")
实用技巧:
Locale比Language更精确,比如zh-CN和zh-TW发音差异很大find()方法返回的是字典列表,每个元素包含Name/Gender/Language等字段voices.voices查看所有可用语音的元数据教育工作者经常需要处理大量课文,这个脚本可以自动化整个流程:
python复制import csv
from pathlib import Path
async def batch_convert():
with open("texts.csv") as f:
reader = csv.DictReader(f)
for row in reader:
output_path = Path(f"output/{row['lang']}_{row['id']}.mp3")
voices = await VoicesManager.create()
voice = random.choice(
voices.find(Language=row['lang'])
)["Name"]
communicate = edge_tts.Communicate(
text=row['content'],
voice=voice
)
await communicate.save(output_path)
配套的CSV文件格式示例:
csv复制id,lang,content
1,en,"Hello world"
2,es,"Hola mundo"
3,fr,"Bonjour le monde"
想让生成的语音更有表现力?试试这些参数组合:
python复制communicate = edge_tts.Communicate(
text="This is <prosody rate='slow'>very</prosody> important!",
voice="en-US-GuyNeural",
rate="+20%", # 整体加速20%
pitch="+10Hz", # 音调提高
volume="+5%" # 音量增大
)
SSML标签妙用:
<prosody rate="fast"> 局部语速调整<emphasis level="strong"> 强调特定词语<break time="1s"/> 插入静音间隔对于需要即时反馈的场景,可以使用流式处理:
python复制async def stream_audio():
communicate = edge_tts.Communicate(
text="正在处理您的请求,请稍候...",
voice="zh-CN-YunxiNeural"
)
with open("stream.mp3", "wb") as f:
async for chunk in communicate.stream():
if chunk["type"] == "audio":
f.write(chunk["data"])
elif chunk["type"] == "WordBoundary":
print(f"当前播报位置: {chunk['offset']}ms")
这个特性特别适合做:
网络服务难免会有波动,健壮的代码应该这样写:
python复制from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
async def robust_tts():
try:
communicate = edge_tts.Communicate(...)
await communicate.save(...)
except Exception as e:
print(f"生成失败: {str(e)}")
raise
常见错误处理:
RuntimeError: Voice not found → 检查语音ID拼写ConnectionError → 检查网络连接asyncio.TimeoutError → 适当增加超时时间