- 语音
- 音频
- AI 应用
【免费下载链接】edge-tts
Use Microsoft Edge's online text-to-speech service from Python WITHOUT needing Microsoft Edge or Windows or an API key
edge-tts是一个纯 Python 实现的开源语音合成(TTS)模块,它直接复用微软 Edge 浏览器内置的在线文本转语音服务:无需安装 Edge 浏览器、无需 Windows 系统、更不需要申请任何 API Key,只需联网即可把文本合成为 MP3 音频,并可选生成 SRT 字幕。本文以仓库根目录的 README.md 为主线,结合 src/edge_tts/util.py、src/edge_tts/communicate.py、src/edge_tts/voices.py 等源码与 examples 示例,系统讲解安装、命令行使用、参数调节、Python 模块调用与底层实现原理,读完即可在自己的项目里落地使用。
一、edge-tts 是什么
按照项目说明,edge-tts是一个 Python 模块,允许你在自己的 Python 代码中,或通过项目自带的edge-tts与edge-playback两个命令行工具,直接使用微软 Edge 的在线文本转语音服务。它有几个鲜明的特点:
- 零依赖浏览器:不需要安装或启动 Microsoft Edge 浏览器本身;
- 跨平台:不要求 Windows,在 Linux、macOS 等系统上同样可用;
- 免 API Key:不涉及微软云语音服务的账号、鉴权与计费,代码内部模拟 Edge 浏览器的请求流程;
- 双入口:既可作为
edge-tts/edge-playback命令使用,也可作为 Python 库(edge_tts)在代码中调用。
从源码看,edge-tts的对外 API 十分精简(见 src/edge_tts/init.py),核心导出为Communicate(负责与合成服务通信)、SubMaker(负责生成 SRT 字幕)、VoicesManager/list_voices(负责查询与筛选音色)以及exceptions异常模块,此外还暴露了__version__供程序识别版本。
二、安装与依赖
1. 通过 pip 安装(Python 库 + 命令行)
$ pip install edge-tts安装后同时获得:
- Python 模块
edge_tts(可在代码中import edge_tts); - 命令行程序
edge-tts与edge-playback(入口分别定义于 src/edge_tts/main.py 与 src/edge_playback/main.py)。
2. 只想用命令行?推荐 pipx
如果你仅仅需要使用edge-tts和edge-playback两个命令,而不打算在项目里import edge_tts,官方建议使用pipx安装,这样可以将工具隔离在独立环境中,避免污染全局 Python 环境:
$ pipx install edge-tts3. edge-playback 的额外依赖:mpv
edge-playback命令用于“边合成边播放”。注意:除 Windows 外,使用edge-playback需要系统已安装 mpv 命令行播放器。项目代码在启动时会用which检查mpv是否在 PATH 中,若缺失会直接报错退出(见 src/edge_playback/main.py)。Windows 上则默认走系统自带播放能力(src/edge_playback/win32_playback.py),不强制要求 mpv。
三、命令行快速上手
1. 基本用法:合成并落盘
最简单的用法是给出一段文本,合成 MP3 音频,并可同时输出 SRT 字幕:
$ edge-tts --text "Hello, world!" --write-media hello.mp3 --write-subtitles hello.srt执行完毕后,当前目录会生成hello.mp3(语音音频)与hello.srt(带时间轴的字幕文件)。其中字幕是根据合成过程中的词边界/句边界事件由SubMaker组装出来的(实现见 src/edge_tts/submaker.py)。
2. 即时播放:edge-playback
如果希望合成后立即播放,并同步显示字幕,可直接使用edge-playback:
$ edge-playback --text "Hello, world!"edge-playback内部的工作方式是:先调用edge-tts命令把音频与字幕写入临时文件,再交给mpv(Windows 上使用系统播放器)播放,结束后自动清理临时文件(见 src/edge_playback/main.py)。它还支持通过环境变量控制调试信息与临时文件保留:设置EDGE_PLAYBACK_DEBUG打印临时文件路径,设置EDGE_PLAYBACK_KEEP_TEMP保留临时文件,EDGE_PLAYBACK_MP3_FILE与EDGE_PLAYBACK_SRT_FILE可指定外部输出文件。
需要注意的是:edge-playback兼容所有edge-tts参数,唯独--write-media、--write-subtitles、--list-voices三个选项除外(播放器场景下文件由命令自行管理,音色列表也无需播放)。
3. CLI 完整参数一览(源自源码)
以下参数与默认值均来自 src/edge_tts/util.py 中argparse的实际定义:
| 参数 | 别名 | 说明 | 默认值 |
|---|---|---|---|
--text | -t | 要合成语音的文本 | 必选其一 |
--file | -f | 从文件读取文本(-或/dev/stdin表示从标准输入读取) | 必选其一 |
--list-voices | -l | 列出所有可用音色后退出 | 无 |
--voice | -v | 指定音色 | en-US-EmmaMultilingualNeural |
--rate | — | 语速,如+10%、-50% | +0% |
--volume | — | 音量,如-50% | +0% |
--pitch | — | 音高,如-50Hz、+20Hz | +0Hz |
--write-media | — | 音频输出到指定文件(缺省时输出到标准输出) | 无 |
--write-subtitles | — | 字幕输出到指定文件(缺省时输出到 stderr) | 无 |
--proxy | — | 为合成请求与音色列表请求设置代理 | 无 |
--version | — | 输出版本号 | 无 |
其中--text、--file、--list-voices三者构成互斥组,必须且只能提供其一。默认音色en-US-EmmaMultilingualNeural定义于 src/edge_tts/constants.py。
四、切换语音:--voice 与 --list-voices
1. 查看全部可用音色
$ edge-tts --list-voices输出为一个按音色名(ShortName)排序的表格,包含四列:Name(音色名)、Gender(性别)、ContentCategories(内容类别)、VoicePersonalities(音色风格),例如:
Name Gender ContentCategories VoicePersonalities --------------------------------- -------- --------------------- -------------------------------------- af-ZA-AdriNeural Female General Friendly, Positive af-ZA-WillemNeural Male General Friendly, Positive am-ET-AmehaNeural Male General Friendly, Positive am-ET-MekdesNeural Female General Friendly, Positive ar-AE-FatimaNeural Female General Friendly, Positive ar-AE-HamdanNeural Male General Friendly, Positive ar-BH-AliNeural Male General Friendly, Positive ar-BH-LailaNeural Female General Friendly, Positive ar-DZ-AminaNeural Female General Friendly, Positive ar-DZ-IsmaelNeural Male General Friendly, Positive ar-EG-SalmaNeural Female General Friendly, Positive ...(列表较长,此处仅展示开头部分。)该表格由 src/edge_tts/util.py 中的_print_voices生成:先调用list_voices()拉取全量音色,再按ShortName排序,并用tabulate输出。
2. 指定音色合成
通过--voice传入音色名即可指定说话人。例如用阿拉伯语音色ar-EG-SalmaNeural合成阿拉伯语文本:
$ edge-tts --voice ar-EG-SalmaNeural --text "مرحبا كيف حالك؟" --write-media hello_in_arabic.mp3 --write-subtitles hello_in_arabic.srt音色名形如语言-地区-名称Neural(如en-GB-SoniaNeural、zh-CN-XiaoxiaoNeural类)。底层在发送请求前会把短名称规范化成服务端要求的完整格式Microsoft Server Speech Text to Speech Voice (语言-地区, 名称),这一转换在 TTSConfig 的初始化校验中完成。
3. 默认音色与音色查询实现
- 默认音色:
en-US-EmmaMultilingualNeural(见 src/edge_tts/constants.py),不传--voice时即使用它。 - 查询实现:
list_voices()会向微软语音平台的音色列表接口发起请求(URL 定义于 src/edge_tts/constants.py),解析返回的 JSON,并为每个音色补齐VoiceTag下的ContentCategories与VoicePersonalities字段(见 src/edge_tts/voices.py)。请求同样会附带Sec-MS-GEC防伪参数,遇到 403 响应时还会调用 DRM 模块修正后重试一次。
五、关于自定义 SSML:已被移除的限制
README 明确指出:自定义 SSML 的支持已经被移除。原因是微软禁止使用任何无法由 Edge 浏览器自身生成的 SSML——服务端只允许在 SSML 中包含单个<voice>标签、其中仅含单个<prosody>标签。因此,任何需要“定制 SSML”的场景(例如拼接多语音、插入特殊标签)都无法得到服务端支持。
好消息是:<prosody>标签内所有可用的自定义选项(语速、音量、音高)都已经通过库参数与命令行参数(--rate、--volume、--pitch)暴露出来,开发者无需手写 SSML。这一点在源码中得到了印证:communicate.py 的mkssml()函数生成的 SSML 恰好就是“<speak>→ 单个<voice>→ 单个<prosody>(内含 pitch/rate/volume)→ 转义后的文本”这一固定结构。
六、调节语速、音量与音高
1. 三个参数的取值规则
| 参数 | 取值格式 | 示例 |
|---|---|---|
--rate | 百分比,如+10%、-50% | 语速提高/降低 |
--volume | 百分比,如-50%、+20% | 音量降低/提高 |
--pitch | 频率值,如-50Hz、+30Hz | 音高降低/提高 |
底层校验非常严格:TTSConfig要求rate与volume必须匹配正则^[+-]\d+%$(正负号 + 整数 + 百分号),pitch必须匹配^[+-]\d+Hz$,否则会直接抛出ValueError(见 src/edge_tts/data_classes.py)。
2. 负值参数的关键易错点
当使用负值时,必须写成--[选项]=-50%的形式,而不能写成--[选项] -50%——否则-50%会被命令行解析器误认为另一个选项,导致解析失败。
3. 实战示例
$ edge-tts --rate=-50% --text "Hello, world!" --write-media hello_with_rate_lowered.mp3 --write-subtitles hello_with_rate_lowered.srt $ edge-tts --volume=-50% --text "Hello, world!" --write-media hello_with_volume_lowered.mp3 --write-subtitles hello_with_volume_lowered.srt $ edge-tts --pitch=-50Hz --text "Hello, world!" --write-media hello_with_pitch_lowered.mp3 --write-subtitles hello_with_pitch_lowered.srt这三个值最终会被塞进 SSML 的<prosody pitch='...' rate='...' volume='...'>中随请求发往服务端(见 src/edge_tts/communicate.py)。
七、在 Python 代码中使用 edge-tts
README 指出edge-tts可以脱离命令行直接作为 Python 模块使用,并给出了两个入口:项目自带的 examples 示例目录,以及 src/edge_tts/util.py(命令行背后的实现,可视为标准用法范本)。
1. 核心类:Communicate
Communicate是与合成服务打交道的核心类(src/edge_tts/communicate.py),构造参数如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
text | 必填 | 要合成的文本(str) |
voice | en-US-EmmaMultilingualNeural | 音色名 |
rate | "+0%" | 语速 |
volume | "+0%" | 音量 |
pitch | "+0Hz" | 音高 |
boundary | "SentenceBoundary" | 字幕边界事件类型,可选"WordBoundary"/"SentenceBoundary" |
connector | None | 自定义 aiohttp 连接器(如限流、复用连接池) |
proxy | None | 代理地址 |
connect_timeout | 10 | 连接超时(秒) |
receive_timeout | 60 | 接收超时(秒) |
2. 流式合成:stream() + SubMaker 生成字幕
stream()是一个异步生成器,逐块产出{"type": "audio", "data": ...}音频块与{"type": "WordBoundary" | "SentenceBoundary", ...}边界元数据。配合SubMaker即可边收音频边积累字幕。参考 examples/async_audio_streaming_with_predefined_voice_and_subtitles.py:
import asyncio import edge_tts TEXT = "Hello World!" VOICE = "en-GB-SoniaNeural" OUTPUT_FILE = "test.mp3" SRT_FILE = "test.srt" async def amain() -> None: communicate = edge_tts.Communicate(TEXT, VOICE) submaker = edge_tts.SubMaker() with open(OUTPUT_FILE, "wb") as file: async for chunk in communicate.stream(): if chunk["type"] == "audio": file.write(chunk["data"]) elif chunk["type"] in ("WordBoundary", "SentenceBoundary"): submaker.feed(chunk) with open(SRT_FILE, "w", encoding="utf-8") as file: file.write(submaker.get_srt()) if __name__ == "__main__": asyncio.run(amain())SubMaker.feed()会把每条边界消息(偏移量 offset、时长 duration、文本 text)换算成 SRT 条目(见 src/edge_tts/submaker.py),get_srt()再统一排版输出(src/edge_tts/submaker.py)。
3. 一站式落盘:save() / save_sync()
如果不需要逐块处理,直接用save()一步到位写文件,还支持把边界元数据以 JSONL 形式落盘:
import asyncio import edge_tts TEXT = "Hello World!" VOICE = "en-GB-SoniaNeural" OUTPUT_FILE = "test.mp3" async def amain() -> None: communicate = edge_tts.Communicate(TEXT, VOICE) await communicate.save(OUTPUT_FILE) if __name__ == "__main__": asyncio.run(amain())对于不喜欢async/await的同步场景,Communicate同样提供了同步接口stream_sync()与save_sync()(实现见 src/edge_tts/communicate.py,内部用事件循环 + 线程队列封装异步逻辑)。同步写法可参考 examples/sync_audio_gen_with_predefined_voice.py:
import edge_tts TEXT = "Hello World!" VOICE = "en-GB-SoniaNeural" OUTPUT_FILE = "test.mp3" def main() -> None: communicate = edge_tts.Communicate(TEXT, VOICE) communicate.save_sync(OUTPUT_FILE) if __name__ == "__main__": main()4. 按属性动态选音色:VoicesManager
音色很多时,可以借助VoicesManager按语言、地区、性别、风格等属性筛选。参考 examples/async_audio_gen_with_dynamic_voice_selection.py:
import asyncio import random import edge_tts from edge_tts import VoicesManager TEXT = "Hoy es un buen día." OUTPUT_FILE = "spanish.mp3" async def amain() -> None: voices = await VoicesManager.create() voice = voices.find(Gender="Male", Language="es") # 也支持按地区筛选: # voice = voices.find(Gender="Female", Locale="es-AR") communicate = edge_tts.Communicate(TEXT, random.choice(voice)["Name"]) await communicate.save(OUTPUT_FILE) if __name__ == "__main__": asyncio.run(amain())使用要点(对应 src/edge_tts/voices.py):
- 必须先
await VoicesManager.create()拉取音色列表,之后才能调用find(),否则抛出RuntimeError; find()支持Gender、Language、Locale等任意音色属性键值组合,返回满足全部条件的音色列表;- 每个音色条目自带
Name字段,直接传给Communicate即可。
5. 命令行内部如何组合这些能力
命令行edge-tts的完整执行逻辑(src/edge_tts/util.py)恰好演示了标准集成流程:
- 构造
Communicate(text, voice, rate=..., volume=..., pitch=..., proxy=...); - 构造
SubMaker; - 循环消费
communicate.stream():audio块写入媒体文件(--write-media缺省时写到标准输出),边界事件喂给SubMaker; - 结束时把
submaker.get_srt()写入字幕文件(--write-subtitles缺省时写到 stderr); - 若提供了
--file,会先读取文本内容,-或/dev/stdin表示从标准输入读取(src/edge_tts/util.py)。
八、底层实现原理浅析
1. 与微软在线服务的 WebSocket 会话
合成请求并非简单的 HTTP POST,而是通过 WebSocket 长连接完成:客户端连上speech.platform.bing.com的合成端点(WSS_URL),先发送一段speech.config命令请求(声明输出格式audio-24khz-48kbitrate-mono-mp3,并开启句子/词边界元数据),再发送携带 SSML 的合成请求,随后逐帧接收二进制音频与文本元数据(见 src/edge_tts/communicate.py)。
2. 长文本的 4096 字节切分
Communicate初始化时会把文本做remove_incompatible_characters()清洗(剔除 OCR 文档里常见的垂直制表符等服务端不支持的字符),然后以4096 字节为上限切成多个小段(src/edge_tts/communicate.py)。切分逻辑(split_text_by_byte_length,src/edge_tts/communicate.py)会优先在换行或空格处断开,同时保证不切断多字节 UTF-8 字符、不把&这类 XML 实体拦腰截断。stream()会按顺序逐段请求合成,因此长文本也能稳定出音频。
3. 输出格式与字幕时间轴补偿
服务端返回的是48 kbps 恒定码率(CBR)的 MP3。为了在多段长文本间让字幕时间轴不漂移,代码统计每段实际收到的音频字节数,按字节数 × 8 × 10_000_000 / 48_000换算成 100 纳秒级 tick 的偏移补偿值(见 __compensate_offset 与 constants.py 中的TICKS_PER_SECOND/MP3_BITRATE_BPS常量)。
4. 防伪与异常自愈
连接 URL 上会附带TrustedClientToken以及Sec-MS-GEC、Sec-MS-GEC-Version两个防伪参数(版本号随 Chromium 版本生成,见 src/edge_tts/constants.py)。当服务端返回 403(常见原因是本地时钟偏差导致令牌失效)时,代码会调用 DRM 模块更新参数后自动重试一次(见 src/edge_tts/communicate.py 与 src/edge_tts/voices.py),提高了稳定性。
九、注意事项与常见问题
1. edge-playback 不支持的选项
edge-playback会透传除--write-media、--write-subtitles、--list-voices之外的全部edge-tts参数(见 src/edge_playback/main.py 的参数解析与 src/edge_playback/main.py 的调用逻辑)。
2. 输出到终端时的安全提示
当--write-media未指定、且标准输入输出均连接终端时,CLI 会打印警告并等待按回车确认,防止把二进制音频直接灌进终端(见 src/edge_tts/util.py)。脚本化使用时请务必指定--write-media或重定向输出。
3. 代理支持
网络受限环境可通过--proxy(命令行)或Communicate(proxy=...)(Python)为合成请求与音色列表请求指定代理。
4. 服务可用性与合规提示
本项目依赖微软 Edge 在线服务,属于“借用”而非官方开放 API 的行为,服务端的限制(如禁止自定义 SSML、参数格式约束)会直接影响可用能力;服务接口若有调整,程序行为可能随之变化。请结合自身场景评估使用范围与合规性。
5. 社区生态参考
README 还列举了若干基于edge-tts构建的社区项目,可作为集成思路参考:例如 Home Assistant 的语音合成插件(hass-edge-tts)、播客内容自动生成工具(Podcastfy),以及一个汇集了各音色 mp3 试听样例的音色挑选辅助项目(tts-samples),方便你在为项目挑选音色时先听为快。此外,仓库内的 examples 目录覆盖了“异步/同步 × 生成音频/流式播放/动态选音色/字幕输出到标准输出”等组合场景,几乎每一种使用形态都能找到可直接运行的范本。
- 语音
- 音频
- AI 应用
【免费下载链接】edge-tts
Use Microsoft Edge's online text-to-speech service from Python WITHOUT needing Microsoft Edge or Windows or an API key
相关推荐
Edge TTS:无需Edge浏览器也能使用的微软语音合成神器
Edge TTS:无需Edge浏览器也能使用的微软语音合成神器 还在寻找简单易用的文本转语音解决方案吗?Edge TTS让你在Python中直接调用微软Edge
语音音频AI 应用Edge TTS:5分钟掌握微软语音合成技术,无需Windows和Edge浏览器
Edge TTS:5分钟掌握微软语音合成技术,无需Windows和Edge浏览器 还在为文本转语音功能而烦恼吗?想在不安装Windows系统的情况下使用微软高质
语音音频AI 应用Edge TTS完全指南:无需微软Edge浏览器实现高质量文本转语音
Edge TTS完全指南:无需微软Edge浏览器实现高质量文本转语音 还在为复杂的文本转语音配置而烦恼吗?今天我要向你介绍一个颠覆性的Python解决方案——E
语音音频AI 应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考