当前位置: 首页 > ops >正文

AI 应用 图文 解说 (二) -- 百度智能云 ASR LIM TTS 语音AI助手源码

 文章的目的为了记录AI应用学习的经历,降低AI的入门难度。同时记录开发流程和要点有些记忆模糊,防止忘记。也希望可以给看到文章的朋友带来一些收获。


相关链接:
AI 应用 图文 解说 (一) -- 百度智能云 实现 语音 聊天-CSDN博客
AI 应用 图文 解说 (二) -- 百度智能云 ASR LIM TTS 语音AI助手程序 -CSDN博客

推荐链接:

开源 python 应用 开发(一)python、pip、pyAutogui、python opencv安装-CSDN博客

开源 python 应用 开发(二)基于pyautogui、open cv 视觉识别的工具自动化-CSDN博客

开源 python 应用 开发(三)python语法介绍-CSDN博客

开源 python 应用 开发(四)python文件和系统综合应用-CSDN博客

开源 python 应用 开发(五)python opencv之目标检测-CSDN博客

开源 python 应用 开发(六)网络爬虫-CSDN博客

开源 python 应用 开发(七)数据可视化-CSDN博客

开源 python 应用 开发(八)图片比对-CSDN博客

开源 python 应用 开发(九)目标跟踪-CSDN博客

开源 python 应用 开发(十)音频压缩-CSDN博客

开源 python 应用 开发(十一)AI应用--百度智能云ASR短语音转文本-CSDN博客

开源 python 应用 开发(十二)AI应用--百度智能云Agent聊天-CSDN博客

开源 python 应用 开发(十三)AI应用--百度智能云TTS语音合成-CSDN博客

开源 python 应用 开发(十四)python快速建设网站-CSDN博客

 推荐链接:

开源 Arkts 鸿蒙应用 开发(一)工程文件分析-CSDN博客

开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-CSDN博客

开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-CSDN博客

开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-CSDN博客

开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-CSDN博客

 推荐链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客

​​​​​​开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

主要内容:一个完整的语音AI助手程序,使用Python实现录音、语音识别、AI对话和语音合成的功能。

目录:

1.主要功能

2.源码分析

3.所有源码

4.显示效果

一、主要功能

音频录制:使用sounddevice库录制16kHz单声道音频

语音识别:通过百度语音识别API将音频转换为文本

AI对话:使用AppBuilder AI模型进行智能对话

语音合成:通过百度语音合成API将文本转换为语音

音频播放:使用多种方式播放生成的语音回复

二、源码分析

2.1  类定义和初始化 (VoiceAIAssistant)
初始化录音配置参数(采样率、声道数等)

设置API密钥和认证信息

初始化各个组件(pygame音频、AppBuilder客户端)

2.2  音频处理功能
start_recording(): 开始录制音频

stop_recording(): 停止录制并保存

audio_callback(): 音频流回调函数,收集音频数据

save_to_wav(): 使用wave模块保存WAV文件

2.3  API调用功能
get_access_token(): 获取百度API访问令牌

speech_to_text(): 调用百度语音识别API

text_to_speech(): 调用百度语音合成API

call_ai_model(): 调用AppBuilder AI模型

2.4  辅助功能
play_audio(): 使用多种方式播放音频文件

process_audio(): 完整的音频处理流程

keyboard_listener(): 键盘监听主循环

5. 工具函数
check_dependencies(): 检查所需Python库是否已安装

main(): 程序主函数

三、所有源码

import sounddevice as sd
import numpy as np
import wave
import keyboard
import time
import os
import base64
import urllib
import requests
import json
import pygame
import tempfile
import threading
import subprocess
from pydub import AudioSegment
import appbuilderclass VoiceAIAssistant:def __init__(self):# 录音配置self.is_recording = Falseself.frames = []self.sample_rate = 16000self.channels = 1self.audio_filename = "test.wav"self.response_filename = "response.wav"# API配置 - 请替换为您的实际密钥self.api_key = ""self.secret_key = ""self.app_token = ""self.app_id = ""# 设置环境变量os.environ["APPBUILDER_TOKEN"] = self.app_token# 初始化组件self.init_components()def init_components(self):"""初始化各个组件"""try:# 初始化pygame音频pygame.mixer.init()print("✅ Pygame音频初始化成功")except Exception as e:print(f"❌ Pygame初始化失败: {e}")try:# 初始化AppBuilder客户端self.app_builder_client = appbuilder.AppBuilderClient(self.app_id)self.conversation_id = self.app_builder_client.create_conversation()print("✅ AppBuilder客户端初始化成功")except Exception as e:print(f"❌ AppBuilder初始化失败: {e}")self.app_builder_client = Nonedef start_recording(self):"""开始录制音频"""if self.is_recording:print("已经在录制中...")returnself.is_recording = Trueself.frames = []print("开始录制16K音频... (按空格键停止并保存)")try:# 直接使用16K采样率录制self.stream = sd.InputStream(samplerate=self.sample_rate,channels=self.channels,callback=self.audio_callback,dtype='int16')self.stream.start()return Trueexcept Exception as e:print(f"开始录制失败: {e}")self.is_recording = Falsereturn Falsedef stop_recording(self):"""停止录制并保存"""if not self.is_recording:print("当前没有在录制")return Falseself.is_recording = Falseprint("停止录制,正在保存16K WAV文件...")try:self.stream.stop()self.stream.close()return self.save_to_wav()except Exception as e:print(f"停止录制失败: {e}")return Falsedef audio_callback(self, indata, frames, time, status):"""音频回调函数"""if status:print(f"音频流状态: {status}")if self.is_recording:self.frames.append(indata.copy())def save_to_wav(self):"""使用wave模块保存WAV文件"""if not self.frames:print("没有音频数据可保存")return Falsetry:# 合并所有音频帧audio_data = np.concatenate(self.frames, axis=0)audio_data = audio_data.flatten()# 确保数据在16位范围内audio_data = np.clip(audio_data, -32768, 32767)audio_data = audio_data.astype(np.int16)# 使用wave模块保存with wave.open(self.audio_filename, 'wb') as wav_file:wav_file.setnchannels(self.channels)wav_file.setsampwidth(2)  # 16位 = 2字节wav_file.setframerate(self.sample_rate)wav_file.writeframes(audio_data.tobytes())print(f"✅ 成功保存16K WAV文件: {self.audio_filename}")return Trueexcept Exception as e:print(f"保存文件时出错: {e}")return Falsedef get_file_content_as_base64(self, path, urlencoded=False):"""获取文件base64编码"""try:with open(path, "rb") as f:content = base64.b64encode(f.read()).decode("utf8")if urlencoded:content = urllib.parse.quote_plus(content)return contentexcept Exception as e:print(f"读取文件错误: {e}")return Nonedef get_access_token(self):"""获取百度API访问令牌"""try:url = "https://aip.baidubce.com/oauth/2.0/token"params = {"grant_type": "client_credentials", "client_id": self.api_key, "client_secret": self.secret_key}response = requests.post(url, params=params)response.raise_for_status()result = response.json()access_token = result.get("access_token")if access_token:print("✅ 成功获取access_token")return access_tokenelse:print(f"获取access_token失败: {result}")return Noneexcept Exception as e:print(f"获取access_token错误: {e}")return Nonedef speech_to_text(self):"""语音识别:将音频转换为文本"""try:if not os.path.exists(self.audio_filename):print(f"错误:文件不存在 - {self.audio_filename}")return Nonefile_size = os.path.getsize(self.audio_filename)url = "https://vop.baidu.com/server_api"access_token = self.get_access_token()if not access_token:return Nonepayload = json.dumps({"format": "wav","rate": 16000,"channel": 1,"cuid": "voice_assistant_cuid","token": access_token,"speech": self.get_file_content_as_base64(self.audio_filename, False),"len": file_size}, ensure_ascii=False)headers = {'Content-Type': 'application/json','Accept': 'application/json'}response = requests.post(url, headers=headers, data=payload.encode("utf-8"))if response.status_code == 200:result = response.json()if result.get("err_no") == 0:text = result.get("result", [""])[0]print(f"✅ 识别结果: {text}")return textelse:print(f"语音识别失败: {result.get('err_msg')}")return Noneelse:print(f"请求失败,状态码: {response.status_code}")return Noneexcept Exception as e:print(f"语音识别错误: {e}")return Nonedef text_to_speech(self, text):"""文本转语音:将文本转换为音频"""try:url = "https://tsn.baidu.com/text2audio"access_token = self.get_access_token()if not access_token:return Noneencoded_text = urllib.parse.quote(text)params = {'tex': encoded_text,'tok': access_token,'cuid': 'voice_assistant_cuid','ctp': 1,'lan': 'zh','spd': 5,'pit': 5,'vol': 5,'per': 0,'aue': 6  # WAV格式}headers = {'Content-Type': 'application/x-www-form-urlencoded','Accept': 'audio/wav'}response = requests.post(url, data=params, headers=headers)if response.status_code == 200:# 保存音频文件with open(self.response_filename, 'wb') as f:f.write(response.content)print(f"✅ 语音合成完成,保存为: {self.response_filename}")return self.response_filenameelse:print(f"语音合成失败,状态码: {response.status_code}")return Noneexcept Exception as e:print(f"语音合成错误: {e}")return Nonedef call_ai_model(self, text):"""调用AI大模型处理文本"""if not self.app_builder_client:print("❌ AppBuilder客户端未初始化")return "抱歉,AI服务暂时不可用。"try:print(f"🤖 向AI模型提问: {text}")resp = self.app_builder_client.run(self.conversation_id, text)answer = resp.content.answerprint(f"🤖 AI回复: {answer}")return answerexcept Exception as e:print(f"调用AI模型错误: {e}")return "抱歉,我暂时无法处理您的请求。"def play_audio(self, audio_file):"""播放音频文件"""if not os.path.exists(audio_file):print(f"错误:音频文件不存在 - {audio_file}")return Falsetry:# 方法1: 使用winsound播放(最简单)import winsoundprint("🔊 正在播放音频...")winsound.PlaySound(audio_file, winsound.SND_FILENAME)print("✅ 播放完成")return Trueexcept Exception as e:print(f"winsound播放失败: {e}")try:# 方法2: 使用pygame播放pygame.mixer.music.load(audio_file)pygame.mixer.music.play()print("🔊 正在播放音频...")# 等待播放完成while pygame.mixer.music.get_busy():pygame.time.wait(100)print("✅ 播放完成")return Trueexcept Exception as e:print(f"pygame播放失败: {e}")try:# 方法3: 使用系统命令播放if os.name == 'nt':  # Windowsos.startfile(audio_file)else:  # Linux/Macsubprocess.run(['aplay', audio_file])print("✅ 使用系统播放器播放")return Trueexcept Exception as e:print(f"系统播放失败: {e}")return Falsedef process_audio(self):"""完整处理流程:录音->识别->AI->语音合成->播放"""print("=" * 60)print("开始处理音频...")print("=" * 60)# 1. 语音识别print("🎤 正在识别语音...")recognized_text = self.speech_to_text()if not recognized_text:print("❌ 语音识别失败")return False# 2. 调用AI模型print("🧠 正在调用AI模型...")ai_response = self.call_ai_model(recognized_text)# 3. 语音合成print("🔊 正在合成语音...")audio_file = self.text_to_speech(ai_response)if not audio_file:print("❌ 语音合成失败")return False# 4. 播放音频print("▶️ 正在播放回复...")return self.play_audio(audio_file)def keyboard_listener(self):"""键盘监听主循环"""print("=" * 60)print("语音AI助手已启动")print("按空格键开始/停止录制")print("按ESC键退出程序")print("=" * 60)recording_started = Falsewhile True:# 检测空格键if keyboard.is_pressed('space'):if not recording_started:if not self.is_recording:# 开始录制if self.start_recording():print("⏺️ 录制中... (再次按空格停止)")else:# 停止录制并处理if self.stop_recording():# 在新线程中处理音频,避免阻塞键盘监听processing_thread = threading.Thread(target=self.process_audio)processing_thread.daemon = Trueprocessing_thread.start()recording_started = Truetime.sleep(0.5)  # 防抖else:recording_started = False# 检测ESC键退出if keyboard.is_pressed('esc'):if self.is_recording:self.stop_recording()print("👋 程序退出")breaktime.sleep(0.1)def check_dependencies():"""检查所需依赖"""required_libs = ['sounddevice', 'numpy', 'keyboard', 'requests', 'pygame', 'pydub', 'appbuilder']missing_libs = []for lib in required_libs:try:if lib == 'appbuilder':import appbuilderelif lib == 'pydub':from pydub import AudioSegmentelse:__import__(lib)print(f"✅ {lib} 已安装")except ImportError:print(f"❌ {lib} 未安装")missing_libs.append(lib)if missing_libs:print(f"\n请安装缺失的库: pip install {' '.join(missing_libs)}")return Falsereturn Truedef main():"""主函数"""# 检查依赖if not check_dependencies():return# 创建语音助手实例try:assistant = VoiceAIAssistant()# 启动键盘监听assistant.keyboard_listener()except KeyboardInterrupt:print("\n👋 程序被用户中断")except Exception as e:print(f"❌ 程序运行错误: {e}")if __name__ == "__main__":main()

四、使用效果

使用python IDE 运行或双击.py文件,代码会检查所需要的库,如果没有安装,使用pip安装就行。

如果报错 Appbuilder问题,可以进行升级。

pip install --upgrade appbuilder-sdk -i https://mirrors.aliyun.com/pypi/simple/

程序不再报错后,按下空格开始录音,会音频提交到智能云,与AI对话,最后返回合成的语音。音频文件为.wav存放在桌面。

http://www.xdnf.cn/news/19253.html

相关文章:

  • 自定义AXI_PWM_v1.0——ZYNQ学习笔记15
  • Spring Task快速上手
  • Maven学习笔记01
  • 【stm32】对射式红外传感器计次以及旋转编码器计次
  • SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
  • 用产品经理的思维,重构AI时代的增长Playbook
  • 企业数据湖:从混沌到秩序的分层设计与治理策略
  • 11.1.5 实现文件删除,共享和共享下载排行榜
  • 分布式测试平台ITP:让自动化测试更高效、更稳定
  • SW - 用装配图的方式组合多个子零件然后转换成为零件,可维护性好
  • 组件通信终极指南:从Props Drilling到Context API
  • react-virtualized React 应用中高效渲染大型列表和表格数据的库
  • 扣子(coze)实践指南进阶篇——创建工作流,并将工作流接入智能体
  • 2025年8月个人工作生活总结
  • [Windows] 某音下载工具——自用
  • Selenium 等待机制:编写稳定可靠的自动化脚本
  • Kubernetes中kubeadm、kubectl、kubelet的区别与作用
  • 动态规划入门(三):一些经典动态规划模型
  • arnold图像加密(猫脸变换)
  • 一个从7zip中分离出来的高压缩比文本压缩工具ppmd
  • 文件系统深度解析:从核心概念到代码实践
  • 【MLLM】多模态理解Ovis2.5模型和训练流程(更新中)
  • 手写MyBatis第43弹:插件拦截原理与四大可拦截对象详解
  • Shell脚本编程入门:从基础语法到流程控制
  • USB4 vs USB3.0:一场接口技术的革命性飞跃
  • 鸿蒙ArkTS 核心篇-14-条件表达式(三目运算符)
  • 如何提高微型导轨的生产效率?
  • 使用 Visio Viewer 查看 Visio 绘图文件
  • 语义分割一站式到底怎么玩?
  • 中级统计师-统计实务-第三章 国民经济核算