Edge-TTS 安装使用完整教程
1. Edge-TTS 简介
Edge-TTS 是一个 Python 库,它允许你直接调用微软 Edge 浏览器的在线文本转语音服务,无需安装 Edge 浏览器,无需 Windows 系统,也无需 API 密钥,即可免费使用微软的神经网络语音合成技术。它本质上是调用微软 Azure 认知服务的神经语音合成接口,但通过开源封装规避了付费限制,支持 60 余种语言,可生成接近真人发音的高质量语音。
主要优势:
- 完全免费,无需注册或申请 API Key
- 支持多种语言和语音角色(包括普通话、粤语、英语等)
- 生成的语音自然度高,基于深度学习模型
- 支持语速、音量、音调等参数调节
- 支持流式输出,适合实时交互场景
使用限制:
- 不建议将输出语音用于商业售卖(如制作有声书出售)
- 单日调用次数建议控制在 5 万次以内,避免触发风控
- 需要网络连接(调用微软在线服务)
2. 环境准备与安装
2.1 前置条件
确保系统已安装Python 3.8 或更高版本,可通过以下命令检查:
python--version2.2 安装 Edge-TTS
使用 pip 安装:
pipinstalledge-tts如果只打算在命令行中使用(不嵌入 Python 项目),推荐使用 pipx 安装,避免污染全局环境:
pipxinstalledge-tts2.3 验证安装
安装完成后,验证是否成功:
edge-tts --list-voices|grep"zh-CN"如果能看到中文语音列表,说明安装成功。
3. 命令行基础使用
3.1 最简单的语音合成
edge-tts--text"你好,这是Edge TTS语音合成测试。"--write-media output.mp33.2 指定语音角色
edge-tts--voicezh-CN-YunxiNeural--text"大家好,欢迎使用Edge TTS"--write-media hello_cn.mp33.3 查看所有可用语音
edge-tts --list-voices>voices.json常用中文语音角色:
| 语音名 | 说明 |
|---|---|
| zh-CN-XiaoxiaoNeural | 女声(自然流畅) |
| zh-CN-YunxiNeural | 男声(中气十足) |
| zh-CN-YunjianNeural | 男声(成熟稳重) |
| zh-CN-XiaoyiNeural | 女声(温柔型) |
| zh-HK-HiuGaaiNeural | 粤语(香港)女声 |
| zh-TW-HsiaoChenNeural | 台湾普通话女声 |
3.4 调整语速、音量和音调
# 语速减慢50%edge-tts--rate=-50%--text"Hello, world!"--write-media slow.mp3# 音量降低50%edge-tts--volume=-50%--text"Hello, world!"--write-media quiet.mp3# 音调降低50Hzedge-tts--pitch=-50Hz--text"Hello, world!"--write-media low_pitch.mp3参数格式说明:
- rate:语速调整,如
+20%表示加快 20%,-10%表示减慢 10% - volume:音量调整,如
+50%表示增大 50% - pitch:音调调整,如
+5Hz表示升高 5Hz,-10Hz表示降低 10Hz
3.5 从文件读取文本
edge-tts --text-file input.txt --write-media output.mp33.6 生成字幕文件
edge-tts--text"Hello world"--write-media output.mp3 --write-subtitles output.srt4. Python 项目中的详细使用
4.1 同步调用(快速上手)
对于简单的脚本,可以使用save_sync方法进行同步调用:
importedge_tts text="大家好,欢迎关注语音之家。"voice="zh-CN-YunxiNeural"communicate=edge_tts.Communicate(text=text,voice=voice)communicate.save_sync("output.mp3")这是最简洁的调用方式,适合快速验证和简单场景。
4.2 异步调用(推荐)
Edge-TTS 原生是异步库,在异步项目中使用await communicate.save()是更高效的方式:
importasyncioimportedge_ttsasyncdefmain():text="大家好,这是异步方式生成的语音。"voice="zh-CN-XiaoxiaoNeural"communicate=edge_tts.Communicate(text,voice)awaitcommunicate.save("output.mp3")asyncio.run(main())如果你已经在异步框架(如 FastAPI、aiohttp)中,直接在协程内await即可:
asyncdefgenerate_speech(text:str,output_path:str):communicate=edge_tts.Communicate(text,"zh-CN-YunxiNeural")awaitcommunicate.save(output_path)注意:Edge-TTS 是异步库,无法直接在非异步上下文中使用await。如果必须在同步代码中调用,可以通过事件循环包装:
importasynciodefsync_generate(text,voice,output):loop=asyncio.new_event_loop()asyncio.set_event_loop(loop)communicate=edge_tts.Communicate(text,voice)loop.run_until_complete(communicate.save(output))loop.close()4.3 流式获取音频数据
communicate.stream()方法以流式方式返回音频数据块,适合需要实时处理音频的场景(如边生成边播放、实时对话系统):
importasyncioimportedge_ttsasyncdefstream_audio(text,voice="zh-CN-XiaoxiaoNeural"):communicate=edge_tts.Communicate(text,voice)audio_bytes=b""asyncforchunkincommunicate.stream():ifchunk["type"]=="audio":audio_bytes+=chunk["data"]returnaudio_bytes每个 chunk 的结构包含type和data两个字段。当type == "audio"时,data是音频二进制数据;还可能出现type == "WordBoundary"的 chunk,包含单词边界信息,可用于生成字幕。
4.4 获取单词边界时间戳
流式处理时,WordBoundary 类型的 chunk 提供了每个词的精确时间信息:
asyncdefget_word_timings(text,voice="zh-CN-XiaoxiaoNeural"):communicate=edge_tts.Communicate(text,voice)timings=[]asyncforchunkincommunicate.stream():ifchunk["type"]=="WordBoundary":timings.append({"text":chunk["text"],"offset":chunk["offset"],# 100纳秒单位"duration":chunk["duration"]# 100纳秒单位})returntimings这些时间戳可以用于生成 SRT 字幕或实现卡拉 OK 效果。
5. 参数详解与高级调优
5.1 Communicate 构造参数
communicate=edge_tts.Communicate(text="要合成的文本",voice="zh-CN-XiaoxiaoNeural",rate="+0%",# 语速,默认 +0%volume="+0%",# 音量,默认 +0%pitch="+0Hz",# 音调,默认 +0Hz)5.2 不同场景的参数推荐
| 场景 | rate | pitch | 效果 |
|---|---|---|---|
| 正常播报 | +0% | +0Hz | 标准语速和音调 |
| 快速播报(新闻) | +15%~+25% | +0Hz | 节奏紧凑 |
| 温柔叙述(有声书) | -5%~-10% | -3Hz~+3Hz | 舒缓自然 |
| 活泼角色 | +10%~+20% | +5Hz~+15Hz | 年轻有活力 |
| 低沉角色 | -5%~-10% | -10Hz~-20Hz | 成熟稳重 |
| 紧张/惊恐 | +20%~+30% | +8Hz~+15Hz | 急促高亢 |
5.3 使用 SSML 精细控制
Edge-TTS 支持 SSML(语音合成标记语言),可以通过文本内容传入 SSML 来实现更精细的控制:
importasyncioimportedge_ttsasyncdefspeak_with_ssml():ssml="""<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="zh-CN"> <voice name="zh-CN-YunxiNeural"> <prosody rate="+15%" pitch="+5Hz"> 这是通过SSML控制的语音合成示例。 </prosody> </voice> </speak>"""communicate=edge_tts.Communicate(ssml,"zh-CN-YunxiNeural")awaitcommunicate.save("ssml_output.mp3")asyncio.run(speak_with_ssml())当文本以<speak>开头时,Edge-TTS 会自动识别为 SSML 格式。
6. 多角色批量合成实战
在实际项目中,经常需要为对话文本生成多角色语音。以下是一个完整的批量合成示例:
importasyncioimportedge_tts# 角色-语音映射表VOICE_MAP={"旁白":"zh-CN-YunjianNeural","女主":"zh-CN-XiaoxiaoNeural","男主":"zh-CN-YunxiNeural","老人":"zh-CN-YunjianNeural",}# 角色-参数映射(语速、音调)PARAM_MAP={"旁白":{"rate":"-5%","pitch":"+0Hz"},"女主":{"rate":"+5%","pitch":"+5Hz"},"男主":{"rate":"+0%","pitch":"-3Hz"},"老人":{"rate":"-15%","pitch":"-10Hz"},}asyncdefsynthesize_dialogue(dialogue_list:list,output_dir:str="./output"):""" dialogue_list: [(角色, 文本), ...] """importos os.makedirs(output_dir,exist_ok=True)fori,(speaker,text)inenumerate(dialogue_list):voice=VOICE_MAP.get(speaker,"zh-CN-XiaoxiaoNeural")params=PARAM_MAP.get(speaker,{})rate=params.get("rate","+0%")pitch=params.get("pitch","+0Hz")communicate=edge_tts.Communicate(text,voice,rate=rate,pitch=pitch)filename=f"{output_dir}/{i+1:03d}_{speaker}.mp3"awaitcommunicate.save(filename)print(f"已生成:{filename}")asyncdefmain():dialogue=[("旁白","在一个风和日丽的下午,故事开始了。"),("女主","你今天怎么来得这么晚?"),("男主","路上堵车了,抱歉让你久等。"),("老人","年轻人啊,时间不等人,要珍惜每一天。"),]awaitsynthesize_dialogue(dialogue)asyncio.run(main())如果需要将多段音频合并为一段完整的语音,可以使用pydub进行拼接:
frompydubimportAudioSegmentimportosdefmerge_audio_files(file_list,output_path):combined=AudioSegment.empty()forfinfile_list:audio=AudioSegment.from_mp3(f)combined+=audio combined+=AudioSegment.silent(duration=300)# 每段后加300ms停顿combined.export(output_path,format="mp3")7. 在 Web 框架中集成
7.1 FastAPI 示例
fromfastapiimportFastAPI,HTTPExceptionfromfastapi.responsesimportFileResponseimportedge_ttsimporttempfileimportos app=FastAPI()@app.post("/tts")asyncdeftext_to_speech(text:str,voice:str="zh-CN-XiaoxiaoNeural"):try:communicate=edge_tts.Communicate(text,voice)withtempfile.NamedTemporaryFile(delete=False,suffix=".mp3")astmp:tmp_path=tmp.nameawaitcommunicate.save(tmp_path)returnFileResponse(tmp_path,media_type="audio/mpeg",filename="speech.mp3")exceptExceptionase:raiseHTTPException(status_code=500,detail=str(e))7.2 带重试机制的健壮版本
网络请求可能偶发失败,建议加入重试逻辑:
asyncdefsynthesize_with_retry(text,voice,output_path,max_retries=5,delay=1):forattemptinrange(max_retries):try:communicate=edge_tts.Communicate(text,voice)awaitcommunicate.save(output_path)returnTrueexceptExceptionase:print(f"第{attempt+1}次尝试失败:{e}")ifattempt<max_retries-1:awaitasyncio.sleep(delay*(attempt+1))returnFalse8. 常见问题与注意事项
Q:报错RuntimeError: asyncio.run() cannot be called from a running event loop?
说明你已经在异步环境中调用了asyncio.run()。在异步框架中直接await communicate.save()即可,不要嵌套asyncio.run()。
Q:生成的语音不完整或中断?
通常是网络波动导致。建议加入重试机制,或使用流式方式逐块获取后自行拼接。
Q:命令行参数报错--rate -50%?
命令行中使用带负号的参数值时,需要写成--rate=-50%的形式,等号不能省略。
Q:如何选择合适的语音角色?
先运行edge-tts --list-voices查看全部可用语音,中文语音可以按zh-CN过滤。建议通过试听小段文本来确定最合适的音色。
Q:能否完全离线使用?
不能。Edge-TTS 调用的是微软在线服务,需要网络连接。如需完全离线,可以考虑 Coqui TTS 或 pyttsx3 等方案。