在人工智能技术飞速发展的今天,语音合成(TTS)已成为智能客服、有声读物、视频配音等场景的核心技术。本文将带你深入了解如何通过开源项目EdgeTTS,在本地搭建支持多方言、可调节参数的语音合成系统,并实现可视化操作界面与API服务。
一、EdgeTTS:免费开源的语音合成利器
EdgeTTS是基于微软Edge浏览器语音服务的开源项目(项目地址可搜索GitHub仓库),其核心优势在于:
-
零成本:完全免费使用微软的云端语音合成服务
-
多语言支持:覆盖40+语言、318种音色,包括普通话、粤语、陕西方言等特色发音(具体音色列表可通过命令行查询)
-
灵活调节:支持语速(±50%)、音量(±70%)、音高(±50Hz)等参数微调(参数范围参考官方文档)
通过本地部署,用户无需依赖在线服务即可实现高质量的语音生成,特别适合需要数据隐私保护的场景。下面的数字人配音就是用Edege-tts生成。
二、快速部署指南
1. 环境安装
仅需两行命令完成基础环境配置:
pip install edge-tts torchaudio
2. 音色查询
查看支持的所有音色(以粤语为例):
edge-tts --list-voices |grep HK
输出示例:
Name: zh-HK-WanLungNeural (粤语男声)Name: zh-HK-HiuMaanNeural (粤语女声)
三、从命令行到代码:三种生成方式
方式1:命令行一键生成
生成周星驰经典台词(粤语版):
edge-tts --voice zh-HK-WanLungNeural --text "曾经有一份真诚的爱情..."--write-media output.mp3 --rate "-30%" --volume "+20%"
参数说明(根据项目文档整理):
-
--rate
:语速调节(±百分比) -
--volume
:音量调节(±百分比) -
--pitch
:音高调节(±Hz值)
方式2:Python代码调用
import edge_ttstext ="欢迎使用EdgeTTS,这是一段自定义语音示例"communicate = edge_tts.Communicate( text=text, voice="zh-CN-YunyangNeural", rate="-20%", # 语速减慢20% volume="+30%", # 音量提升30% pitch="+40Hz"# 音调升高40Hz)communicate.save_sync("custom_voice.mp3")
方式3:Gradio可视化界面
通过以下代码搭建交互式操作界面:
import gradio as gr
import edge_tts
def generate_voice(text, voice, rate, volume):
communicate = edge_tts.Communicate(
text=text,
voice=voice,
rate=f"{rate}%",
volume=f"{volume}%"
)
communicate.save_sync("output.mp3")
return "output.mp3"
iface = gr.Interface(
fn=generate_voice,
inputs=[
gr.Textbox(label="输入文本", lines=5),
gr.Dropdown(
choices=["zh-CN-YunyangNeural", "zh-HK-WanLungNeural", "zh-TW-HsiaoYuNeural"],
label="选择音色"
),
gr.Slider(-50, 50, value=0, label="语速调节(%)"),
gr.Slider(-70, 70, value=0, label="音量调节(%)")
],
outputs=gr.Audio(label="生成结果"),
title="EdgeTTS语音合成工具"
)
iface.launch()
四、进阶应用:构建API服务
通过开源社区项目(可搜索openai-edge-tts获取),可快速搭建兼容OpenAI接口的TTS服务:
1. Docker部署
git clone https://github.com/travisvn/openai-edge-tts.gitcd openai-edge-ttsdocker compose up --build
2. API调用示例
import requestsurl ="http://localhost:5050/v1/audio/speech"headers ={ "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY"}data ={ "input": "你好,我是AI语音助手", "voice": "zh-CN-YunyangNeural", "response_format": "mp3", "speed": 1.2}response = requests.post(url, headers=headers, json=data)withopen("output.mp3", "wb") as f: f.write(response.content)
五、镜像分享
1.一行命令部署镜像
下面是我制作好的docker镜像,使用下面的命令就可以一键启动运行
sudo docker run -d --name edge-tts-ui --restart=always -p 7868:7864 edge-tts-ui:3.0 bash -c "python3 /home/tts_api.py"
镜像地址:
https://cloud.189.cn/web/share?code=nInEVfJ3EFre(访问码:8m7t)
2.Gradio和FastAPI 一键启动
运行下面的代码,就可以直接在一个接口使用graido界面的应用,并提供api功能
#tts_api.py
from fastapi import FastAPI, HTTPException, File, UploadFile
from fastapi.responses import FileResponse
import edge_tts
import os
import time
import asyncio
import uvicorn
from pydantic import BaseModel
from webui import iface
import gradio as gr
app = FastAPI()
async def save_audio_async(audio_data, filename):
await audio_data.save(filename)
class AudioRequest(BaseModel):
text: str
lang: str = 'zh-CN-XiaoyiNeural'
speed: str = '-4%'
volume: str = '+3%'
async def generate_audio(request: AudioRequest):
'''
Name: zh-CN-YunxiNeural
Gender: Male
Name: zh-CN-YunxiaNeural
Gender: Male
Name: zh-CN-YunyangNeural
Gender: Male
Name: zh-CN-liaoning-XiaobeiNeural
Gender: Female
Name: zh-CN-shaanxi-XiaoniNeural
Gender: Female
'''
timestamp = int(time.time())
speed = request.speed.strip()
volume = request.volume.strip()
try:
audio_data = edge_tts.Communicate(request.text, voice=request.lang, rate=speed, volume=volume)
except ValueError as e:
print(f"{e}")
raise HTTPException(status_code=400, detail=str(e))
filename = f"/home/mp3/{timestamp}.mp3"
await save_audio_async(audio_data, filename)
return {'filename': f"{timestamp}.mp3"}
def download_audio(filename: str):
file_path = f"/home/mp3/{filename}"
if os.path.exists(file_path):
return FileResponse(file_path, media_type='application/octet-stream', filename=filename)
else:
raise HTTPException(status_code=404, detail="File not found")
def delete_audio(filename: str):
file_path = f"/home/mp3/{filename}"
if os.path.exists(file_path):
os.remove(file_path)
return {'message': f'{filename} has been deleted'}
else:
return {'message': 'File not found'}
app=gr.mount_gradio_app(app,iface,path="/tts")
if __name__ == '__main__':
uvicorn.run(app, host="0.0.0.0", port=7864)