跳到主要内容Qwen3-TTS 与 Whisper ASR 构建双向语音对话系统 | 极客日志PythonAI算法
Qwen3-TTS 与 Whisper ASR 构建双向语音对话系统
介绍基于 Qwen3-TTS 和 Whisper ASR 构建双向语音对话系统的完整流程。涵盖环境配置、模型加载、语音合成与识别实现、系统集成及大语言模型接入。同时提供性能优化策略与常见问题排查指南,助力开发者快速搭建智能语音交互应用。
雪落无声0 浏览 Qwen3-TTS 与 Whisper ASR 构建双向语音对话系统
本文介绍如何使用 Qwen3-TTS 和 Whisper ASR 构建双向语音对话系统。从基础部署开始,到最终实现一个能听会说的双向对话系统。
1. 准备工作与环境搭建
在开始之前,我们先来了解一下今天要用到的两个核心工具。
Qwen3-TTS 是一个强大的文本转语音模型。它最吸引人的地方在于,它支持 10 种主要语言,包括中文、英文、日文等,还能生成多种方言和语音风格。更厉害的是,它能理解你文本里的情感和意图,自动调整说话的语调、语速,让生成的声音听起来特别自然。
Whisper ASR 则是 OpenAI 开源的语音识别模型,它的识别准确率非常高,支持多种语言,而且对带口音、有噪声的语音也有很好的处理能力。
把这两个模型组合起来,一个负责'听'(Whisper),一个负责'说'(Qwen3-TTS),一个完整的语音对话闭环就形成了。
1.1 基础环境要求
- 操作系统:推荐使用 Linux(如 Ubuntu 20.04+)或 macOS。Windows 系统也可以,但可能需要额外配置。
- Python 版本:Python 3.8 或更高版本。
- 内存:至少 16GB RAM。如果要用到更大的模型或进行批量处理,建议 32GB 以上。
- 存储空间:预留 10-20GB 空间用于存放模型和依赖库。
- GPU(可选但推荐):虽然 CPU 也能运行,但有 NVIDIA GPU(显存 8GB 以上)会快很多。
1.2 快速安装依赖
首先,创建一个独立的 Python 环境是个好习惯,这样可以避免不同项目之间的依赖冲突:
python -m venv voice_chat_env
source voice_chat_env/bin/activate
voice_chat_env\Scripts\activate
环境激活后,你会看到命令行前面多了个环境名。接下来安装核心依赖:
pip install --upgrade pip
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install torch torchvision torchaudio
pip install transformers
pip install soundfile librosa pydub
pip install gradio streamlit
安装过程可能需要几分钟,取决于你的网速。如果遇到网络问题,可以尝试使用国内的镜像源,比如清华源:
pip install transformers -i https://pypi.tuna.tsinghua.edu.cn/simple
2. Qwen3-TTS 模型部署与初体验
环境准备好后,我们先来部署和测试 Qwen3-TTS 模型。这是整个系统的'嘴巴',负责把文字变成声音。
2.1 下载与加载 Qwen3-TTS 模型
Qwen3-TTS 模型可以通过 Hugging Face 平台获取。这里我们使用代码直接加载:
from transformers import AutoModelForTextToSpeech, AutoTokenizer
import torch
model_name = "Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign"
print("正在加载 Qwen3-TTS 模型,这可能需要几分钟...")
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForTextToSpeech.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
)
print("模型加载完成!")
第一次运行这段代码时,它会从网上下载模型文件,文件大小约 3-4GB,所以需要一些时间和足够的磁盘空间。下载完成后,后续使用就会快很多。
2.2 你的第一次语音合成
def text_to_speech(text, language="中文", voice_description="亲切的女声"):
"""
将文本转换为语音
参数:
text: 要转换的文本
language: 语言类型,支持中文、英文、日文等
voice_description: 音色描述,如'亲切的女声'、'沉稳的男声'
"""
input_text = f"{language}|{voice_description}|{text}"
inputs = tokenizer(input_text, return_tensors="pt")
if torch.cuda.is_available():
inputs = {k: v.cuda() for k, v in inputs.items()}
with torch.no_grad():
speech = model.generate(**inputs)
speech = speech.cpu().numpy()
return speech
test_text = "你好,我是 Qwen3-TTS,很高兴为你服务。"
audio_data = text_to_speech(test_text, language="中文", voice_description="亲切的女声")
print(f"语音生成完成!音频数据形状:{audio_data.shape}")
运行成功后,你会得到一个 numpy 数组,这就是音频的原始数据。但光有数据还不行,我们得把它保存成能播放的音频文件。
2.3 保存和播放生成的语音
生成音频数据后,我们需要把它保存为常见的音频格式,比如 WAV 或 MP3:
import soundfile as sf
import numpy as np
def save_audio(audio_data, filename="output.wav", sample_rate=24000):
"""
保存音频数据为文件
参数:
audio_data: 音频数据(numpy 数组)
filename: 保存的文件名
sample_rate: 采样率,Qwen3-TTS 默认是 24000Hz
"""
if len(audio_data.shape) > 1:
audio_data = audio_data[0]
if audio_data.max() > 1.0 or audio_data.min() < -1.0:
audio_data = audio_data / np.max(np.abs(audio_data))
sf.write(filename, audio_data, sample_rate)
print(f"音频已保存为:{filename}")
save_audio(audio_data, "first_speech.wav")
现在,你可以在当前文件夹下找到 first_speech.wav 文件,用任何音频播放器打开它,就能听到 Qwen3-TTS 生成的声音了!
2.4 探索不同的语音风格
Qwen3-TTS 的强大之处在于它的灵活性。我们可以通过改变参数来调整生成语音的风格:
test_cases = [
{"text": "Hello, welcome to our AI voice system.", "language": "英文", "voice": "专业的女声"},
{"text": "こんにちは、AI 音声システムへようこそ。", "language": "日文", "voice": "可爱的女声"},
{"text": "今天天气真好,我们出去散步吧。", "language": "中文", "voice": "欢快的女声"},
{"text": "请注意,系统将在 5 分钟后进行维护。", "language": "中文", "voice": "严肃的男声"},
]
for i, case in enumerate(test_cases):
print(f"生成中:{case['text']}")
audio = text_to_speech(case["text"], case["language"], case["voice"])
save_audio(audio, f"test_{i+1}.wav")
print(f"已保存:test_{i+1}.wav")
运行这段代码,你会得到 4 个不同风格的声音文件。听听看,是不是每种风格都有明显的区别?这就是 Qwen3-TTS 的上下文理解能力在起作用——它能根据文本内容和你的描述,自动调整语音的情感色彩。
3. Whisper ASR 模型部署与测试
现在我们的系统有了'嘴巴',接下来要给它装上'耳朵'。Whisper ASR 就是我们的语音识别引擎,负责把你说的话转换成文字。
3.1 加载 Whisper 模型
Whisper 有多个版本,从最小的 tiny 到最大的 large。模型越大,识别准确率越高,但需要的计算资源也越多。对于大多数应用场景,base 或 small 版本已经足够用了。
from transformers import WhisperProcessor, WhisperForConditionalGeneration
import librosa
model_size = "base"
print(f"正在加载 Whisper-{model_size} 模型...")
processor = WhisperProcessor.from_pretrained(f"openai/whisper-{model_size}")
asr_model = WhisperForConditionalGeneration.from_pretrained(f"openai/whisper-{model_size}")
if torch.cuda.is_available():
asr_model = asr_model.cuda()
print("Whisper 模型加载完成!")
3.2 实现语音识别功能
有了模型,我们就可以实现一个函数,把音频文件转换成文字:
def speech_to_text(audio_path, language="zh"):
"""
将音频文件转换为文本
参数:
audio_path: 音频文件路径
language: 语言代码,zh=中文,en=英文,ja=日文等
"""
audio, sr = librosa.load(audio_path, sr=16000)
input_features = processor(
audio, sampling_rate=sr, return_tensors="pt"
).input_features
if torch.cuda.is_available():
input_features = input_features.cuda()
predicted_ids = asr_model.generate(input_features)
transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
return transcription
try:
text = speech_to_text("test_voice.wav", language="zh")
print(f"识别结果:{text}")
except FileNotFoundError:
print("找不到测试音频文件,请先录制一段语音保存为 test_voice.wav")
3.3 实时语音识别
上面的例子是从文件识别,但在实际对话系统中,我们更需要实时识别。下面是一个简单的实时识别示例:
import pyaudio
import numpy as np
import wave
from queue import Queue
import threading
class RealTimeASR:
def __init__(self, model_size="base"):
"""初始化实时语音识别"""
self.processor = WhisperProcessor.from_pretrained(f"openai/whisper-{model_size}")
self.model = WhisperForConditionalGeneration.from_pretrained(f"openai/whisper-{model_size}")
if torch.cuda.is_available():
self.model = self.model.cuda()
self.CHUNK = 1024
self.FORMAT = pyaudio.paInt16
self.CHANNELS = 1
self.RATE = 16000
self.audio_queue = Queue()
self.is_recording = False
def record_audio(self):
"""录制音频"""
p = pyaudio.PyAudio()
stream = p.open(
format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
frames_per_buffer=self.CHUNK
)
print("开始录音...(按 Ctrl+C 停止)")
self.is_recording = True
try:
while self.is_recording:
data = stream.read(self.CHUNK)
self.audio_queue.put(data)
except KeyboardInterrupt:
print("\n录音停止")
finally:
stream.stop_stream()
stream.close()
p.terminate()
self.is_recording = False
def transcribe_audio(self, audio_data):
"""转录音频数据"""
audio_array = np.frombuffer(audio_data, dtype=np.int16).astype(np.float32) / 32768.0
input_features = self.processor(
audio_array, sampling_rate=self.RATE, return_tensors="pt"
).input_features
if torch.cuda.is_available():
input_features = input_features.cuda()
predicted_ids = self.model.generate(input_features)
transcription = self.processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
return transcription
这个实时识别类可以持续监听麦克风输入,适合构建交互式应用。不过要注意,实时识别对计算资源要求较高,如果感觉卡顿,可以尝试使用更小的模型(如 tiny)。
4. 构建双向语音对话系统
现在,我们已经有了独立的'听'和'说'功能,是时候把它们组合起来,创建一个真正的双向对话系统了。
4.1 系统架构设计
用户说话 → Whisper 识别为文字 → 处理文字(可以接入大语言模型) → Qwen3-TTS 转换为语音 → 播放给用户
这个流程形成了一个完整的交互闭环。中间的'处理文字'环节很灵活,可以是一个简单的规则引擎,也可以接入像 ChatGPT 这样的大语言模型,让对话更智能。
4.2 基础对话系统实现
我们先实现一个基础版本,它会把用户说的话直接重复一遍:
import time
from pydub import AudioSegment
from pydub.playback import play
import tempfile
class SimpleVoiceChat:
def __init__(self, tts_model_name="Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign", asr_model_size="base"):
"""初始化简单语音聊天系统"""
print("初始化语音对话系统...")
self.tts_tokenizer = AutoTokenizer.from_pretrained(
tts_model_name, trust_remote_code=True
)
self.tts_model = AutoModelForTextToSpeech.from_pretrained(
tts_model_name,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
)
self.asr_processor = WhisperProcessor.from_pretrained(
f"openai/whisper-{asr_model_size}"
)
self.asr_model = WhisperForConditionalGeneration.from_pretrained(
f"openai/whisper-{asr_model_size}"
)
if torch.cuda.is_available():
self.asr_model = self.asr_model.cuda()
print("系统初始化完成!")
def listen(self, audio_path):
"""听:语音转文字"""
try:
audio, sr = librosa.load(audio_path, sr=16000)
input_features = self.asr_processor(
audio, sampling_rate=sr, return_tensors="pt"
).input_features
if torch.cuda.is_available():
input_features = input_features.cuda()
predicted_ids = self.asr_model.generate(input_features)
text = self.asr_processor.batch_decode(
predicted_ids, skip_special_tokens=True
)[0]
return text
except Exception as e:
print(f"语音识别失败:{e}")
return ""
def think(self, user_text):
"""思考:处理用户输入(这里简单重复)"""
response = f"你说的是:{user_text}"
return response
def speak(self, text, language="中文", voice="友好的助手"):
"""说:文字转语音并播放"""
try:
input_text = f"{language}|{voice}|{text}"
inputs = self.tts_tokenizer(input_text, return_tensors="pt")
if torch.cuda.is_available():
inputs = {k: v.cuda() for k, v in inputs.items()}
with torch.no_grad():
speech = self.tts_model.generate(**inputs)
speech = speech.cpu().numpy()
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
temp_path = tmp.name
if len(speech.shape) > 1:
speech = speech[0]
sf.write(temp_path, speech, 24000)
audio = AudioSegment.from_wav(temp_path)
play(audio)
return True
except Exception as e:
print(f"语音合成失败:{e}")
return False
def chat(self, user_audio_path):
"""完整的对话流程"""
print("正在聆听...")
user_text = self.listen(user_audio_path)
if not user_text:
print("没有识别到有效语音")
return
print(f"你说:{user_text}")
response_text = self.think(user_text)
print(f"我回答:{response_text}")
print("正在生成语音回复...")
self.speak(response_text)
这个基础版本虽然简单,但已经实现了完整的语音对话流程。你可以对着麦克风说句话,保存为音频文件,然后让系统处理,它会用语音重复你的话。
4.3 接入大语言模型增强对话能力
上面的例子只是简单重复,没什么实际用处。要让对话真正智能起来,我们需要接入一个大语言模型。这里以使用 OpenAI API 为例(你也可以使用其他开源模型):
import openai
class SmartVoiceChat(SimpleVoiceChat):
def __init__(self, openai_api_key, **kwargs):
"""初始化智能语音聊天系统"""
super().__init__(**kwargs)
openai.api_key = openai_api_key
self.conversation_history = []
def think(self, user_text):
"""思考:使用 GPT 生成回复"""
self.conversation_history.append({"role": "user", "content": user_text})
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "你是一个友好的语音助手,回答要简洁自然,适合用语音表达。"}
] + self.conversation_history[-6:],
max_tokens=150,
temperature=0.7
)
assistant_reply = response.choices[0].message.content
self.conversation_history.append({"role": "assistant", "content": assistant_reply})
return assistant_reply
except Exception as e:
print(f"GPT 调用失败:{e}")
return "抱歉,我现在无法处理你的请求。"
def reset_conversation(self):
"""重置对话历史"""
self.conversation_history = []
print("对话历史已重置")
这样,你的语音助手就真正'智能'起来了。它可以回答各种问题,进行多轮对话,而且回复内容自然流畅。
4.4 创建 Web 界面(可选)
如果你想让更多人方便地使用这个系统,可以创建一个简单的 Web 界面。这里用 Gradio 库来实现:
import gradio as gr
def create_web_interface():
"""创建 Web 界面"""
chat_system = SimpleVoiceChat()
def process_audio(audio_file):
"""处理上传的音频文件"""
if audio_file is None:
return "请上传音频文件", None
user_text = chat_system.listen(audio_file)
if not user_text:
return "没有识别到语音", None
response = f"我听到你说:{user_text}"
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
temp_path = tmp.name
input_text = f"中文 | 友好的助手|{response}"
inputs = chat_system.tts_tokenizer(input_text, return_tensors="pt")
if torch.cuda.is_available():
inputs = {k: v.cuda() for k, v in inputs.items()}
with torch.no_grad():
speech = chat_system.tts_model.generate(**inputs)
speech = speech.cpu().numpy()
if len(speech.shape) > 1:
speech = speech[0]
sf.write(temp_path, speech, 24000)
return response, temp_path
interface = gr.Interface(
fn=process_audio,
inputs=gr.Audio(type="filepath", label="上传你的语音"),
outputs=[
gr.Textbox(label="识别结果"),
gr.Audio(label="语音回复", type="filepath")
],
title="语音对话系统",
description="上传语音文件,系统会识别并回复"
)
return interface
运行这段代码后,会启动一个本地 Web 服务器。打开浏览器访问显示的地址,就能看到一个简单的界面,可以上传音频文件,系统会自动识别并回复。
5. 优化技巧与常见问题
到这里,一个基本的双向语音对话系统已经搭建完成了。但在实际使用中,你可能会遇到一些问题。下面是一些优化技巧和常见问题的解决方法。
5.1 性能优化建议
1. 模型量化 量化可以显著减少模型大小和内存占用,加快推理速度:
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(
load_in_8bit=True,
llm_int8_threshold=6.0
)
model = AutoModelForTextToSpeech.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign",
quantization_config=quantization_config,
device_map="auto",
trust_remote_code=True
)
2. 使用更小的模型 如果不需要最高质量,可以使用更小的模型变体:
model_sizes = {
"最快": "tiny",
"平衡": "base",
"准确": "small",
"高质量": "medium",
"最佳质量": "large"
}
selected_size = model_sizes["平衡"]
3. 批处理 如果需要处理多个音频,使用批处理可以提高效率:
def batch_speech_to_text(audio_paths):
"""批量语音识别"""
audios = []
for path in audio_paths:
audio, sr = librosa.load(path, sr=16000)
audios.append(audio)
input_features = processor(
audios, sampling_rate=16000, return_tensors="pt", padding=True
).input_features
predicted_ids = model.generate(input_features)
transcriptions = processor.batch_decode(predicted_ids, skip_special_tokens=True)
return transcriptions
5.2 常见问题与解决
问题 1:内存不足
症状:程序崩溃,提示 CUDA out of memory 或内存错误。
解决:
- 使用更小的模型
- 启用模型量化
- 减少批处理大小
- 使用 CPU 模式(速度会慢很多)
问题 2:语音识别不准
症状:Whisper 识别结果错误很多。
解决:
- 确保音频质量良好,背景噪声小
- 尝试更大的 Whisper 模型
- 指定正确的语言参数
- 对音频进行预处理(降噪、归一化)
问题 3:语音合成不自然
症状:Qwen3-TTS 生成的声音机械、不连贯。
解决:
- 检查输入文本格式是否正确
- 尝试不同的音色描述
- 调整文本的标点和停顿
- 确保使用最新版本的模型
问题 4:延迟太高
症状:从说话到听到回复等待时间太长。
解决:
- 使用 Qwen3-TTS 的流式生成模式
- 在本地部署而不是通过 API 调用
- 优化代码,减少不必要的计算
- 使用 GPU 加速
5.3 实际应用建议
- Whisper 模型:
base 或 small
- Qwen3-TTS:默认配置
- 回复风格:简洁、友好
- 最佳语言:根据使用环境选择
- Whisper 模型:
small 或 medium
- Qwen3-TTS:使用专业、清晰的音色
- 回复风格:正式、准确
- 建议功能:多语言支持、情绪检测
- Whisper 模型:
medium(需要高准确率)
- Qwen3-TTS:清晰、有表现力的音色
- 回复风格:耐心、详细
- 建议功能:发音评估、学习进度跟踪
6. 总结与下一步
通过这篇教程,我们完成了一个从零开始搭建双向语音对话系统的完整旅程。让我们回顾一下关键步骤:
- 环境准备:安装了必要的 Python 库和依赖
- Qwen3-TTS 部署:学会了如何加载和使用这个强大的文本转语音模型
- Whisper ASR 部署:实现了准确的语音识别功能
- 系统集成:将两个模型组合成完整的对话系统
- 功能增强:通过接入大语言模型让对话更智能
- 界面创建:构建了 Web 界面方便使用
你现在拥有的不仅仅是一个能听会说的程序,而是一个可以扩展的平台。基于这个基础,你可以:
- 添加更多功能:比如语音唤醒、多轮对话管理、情感分析等
- 优化用户体验:减少延迟、提高识别准确率、增加个性化设置
- 部署到实际应用:集成到网站、移动应用或智能设备中
- 探索新模型:随着 AI 技术的发展,不断尝试更新的语音模型
语音交互是人工智能最自然的接口之一。随着技术的进步,这样的系统会变得越来越普及。你今天学到的技能,正是构建未来智能应用的重要基础。
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- RSA密钥对生成器
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
- Mermaid 预览与可视化编辑
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online