大家好!今天我要给大家详细讲解一个使用百度语音识别API的Python代码。这个代码可以将音频文件转换成文字,非常适合做语音转文字的应用。我会从最基础的概念开始讲起,确保没有任何编程基础的朋友也能理解。
翻译
一、代码概览
这段代码主要实现了以下几个功能:
连接百度语音识别API
检查音频文件是否符合要求
将音频文件发送到百度服务器进行识别
返回识别结果
整个代码大约150行,包含了一个主类BaiduASR
和几个辅助函数。下面我会逐部分详细解释。
二、准备工作:导入必要的库
代码开头部分导入了多个Python库:
import os
import time
import json
import wave
import base64
import requests
from config import BAIDU_APP_ID, BAIDU_API_KEY, BAIDU_SECRET_KEY, BAIDU_TOKEN_URL, BAIDU_ASR_URL
让我们一个个来看这些库的作用:
os:用于操作系统相关的功能,比如处理文件路径
time:处理时间相关操作
json:处理JSON格式的数据(JSON是一种常用的数据交换格式)
wave:专门处理WAV格式的音频文件
base64:将二进制数据编码为ASCII字符(因为网络传输需要文本格式)
requests:发送HTTP请求到百度服务器
config:从自定义配置文件导入百度API的认证信息
三、BaiduASR类详解
整个代码的核心是BaiduASR
类,它封装了所有与百度语音识别相关的功能。
1. 初始化方法 init:
def __init__(self):
self.app_id = BAIDU_APP_ID
self.api_key = BAIDU_API_KEY
self.secret_key = BAIDU_SECRET_KEY
self.token_url = BAIDU_TOKEN_URL
self.asr_url = BAIDU_ASR_URL
self.access_token = None
self.token_expires_time = 0
这里设置了百度API所需的各种参数:
app_id
:应用IDapi_key
:API密钥secret_key
:密钥token_url
:获取访问令牌的URLasr_url
:语音识别的API地址access_token
:访问令牌(初始为None)token_expires_time
:令牌过期时间(初始为0)
这些参数中,前五个都是从config.py文件中导入的,这样做的好处是可以保护敏感信息,避免直接写在代码中。
2. 获取访问令牌 get_access_token
def get_access_token(self):
"""获取百度API访问令牌"""
current_time = time.time()
# 如果token未过期,直接返回
if self.access_token and current_time < self.token_expires_time:
return self.access_token
# 获取新的access_token
params = {
'grant_type': 'client_credentials',
'client_id': self.api_key,
'client_secret': self.secret_key
}
try:
response = requests.post(self.token_url, params=params, timeout=10)
result = response.json()
if 'access_token' in result:
self.access_token = result['access_token']
# token有效期一般为30天,这里设置为29天后过期
self.token_expires_time = current_time + result.get('expires_in', 2592000) - 86400
return self.access_token
else:
return None
except Exception as e:
return None
这部分代码负责获取访问百度API所需的令牌(token)。百度API使用OAuth2.0认证,需要先获取token才能使用其他服务。
这部分代码负责获取访问百度API所需的令牌(token)。百度API使用OAuth2.0认证,需要先获取token才能使用其他服务。
详细解释:
首先检查当前是否有有效的token(未过期),如果有就直接返回
如果没有有效token,就准备请求参数:
grant_type
:固定为'client_credentials'client_id
:API Keyclient_secret
:Secret Key
使用requests库发送POST请求到token_url
解析返回的JSON数据
如果获取成功,保存token并设置过期时间(提前1天过期,避免临界点问题)
返回token或None(失败时)
3. 验证音频文件 validate_audio
def validate_audio(self, file_path):
"""验证音频文件格式"""
try:
with wave.open(file_path, 'rb') as wf:
nchannels = wf.getnchannels()
sampwidth = wf.getsampwidth()
framerate = wf.getframerate()
nframes = wf.getnframes()
valid = True
if nchannels != 1:
valid = False
if sampwidth != 2:
valid = False
# 百度API只支持特定采样率
supported_rates = [8000, 16000]
if framerate not in supported_rates:
valid = False
duration = nframes / float(framerate)
if duration < 0.3:
valid = False
elif duration > 60:
valid = False
if valid:
return True, framerate, duration
return False, None, None
except Exception as e:
return False, None, None
这个方法检查音频文件是否符合百度API的要求:
使用wave模块打开WAV文件
获取音频参数:
nchannels
:声道数(百度要求单声道)sampwidth
:采样宽度(百度要求16bit,即2字节)framerate
:采样率(百度支持8000或16000Hz)nframes
:总帧数
检查音频时长是否在0.3-60秒之间
返回检查结果、采样率和时长
4. 语音识别主函数 recognize_audio
这是最核心的方法,负责实际的语音识别工作:
def recognize_audio(self, file_path):
"""语音识别主函数"""
# 验证音频格式
is_valid, sample_rate, duration = self.validate_audio(file_path)
if not is_valid:
return "音频格式不符合要求~"
# 获取access_token
access_token = self.get_access_token()
if not access_token:
return "获取访问令牌失败,请检查API密钥~"
首先验证音频文件并获取token,这两步是前置条件检查。
接下来是处理音频数据:
# 读取音频文件并编码
try:
with open(file_path, 'rb') as f:
audio_data = f.read()
# base64编码
audio_base64 = base64.b64encode(audio_data).decode('utf-8')
# 确定音频格式
file_ext = os.path.splitext(file_path)[1].lower()
if file_ext == '.wav':
format_type = 'wav'
elif file_ext == '.pcm':
format_type = 'pcm'
elif file_ext == '.amr':
format_type = 'amr'
elif file_ext == '.m4a':
format_type = 'm4a'
else:
format_type = 'wav' # 默认wav格式
这部分代码:
读取音频文件的二进制数据
使用base64编码(因为HTTP传输需要文本数据)
根据文件扩展名确定格式类型
然后是准备请求参数:
# 修复:确保采样率为整数,并根据百度API要求进行规范化
if sample_rate == 16000:
api_rate = 16000
elif sample_rate == 8000:
api_rate = 8000
else:
# 如果采样率不是标准值,使用最接近的标准值
api_rate = 16000 if sample_rate > 12000 else 8000
# 构建请求数据 - 注意:百度ASR使用POST请求,参数放在body中
data = {
'format': format_type,
'rate': api_rate, # 确保使用标准采样率
'channel': 1,
'speech': audio_base64,
'len': len(audio_data),
'cuid': 'python_client_v3', # 修改cuid
'token': access_token,
'dev_pid':80001 # 改为普通话(纯中文识别),如果还有问题可以尝试15372
}
这里构建了发送给百度API的请求数据,包括:
音频格式
采样率
声道数(固定为1)
base64编码的音频数据
音频数据长度
客户端ID
访问令牌
语言模型ID(80001表示普通话纯中文识别)
接下来发送请求并处理响应
# 设置请求头
headers = {
'Content-Type': 'application/json; charset=utf-8'
}
# 发送识别请求 - 注意:所有参数都在body中,不使用URL参数
response = requests.post(
self.asr_url,
data=json.dumps(data),
headers=headers,
timeout=30
)
# 打印响应状态码和内容,用于调试
result = response.json()
# 处理识别结果
if result.get('err_no') == 0:
# 识别成功
if 'result' in result and result['result']:
recognized_text = ''.join(result['result'])
print(f"{recognized_text}")
return recognized_text
else:
return "识别不到内容~"
else:
# 识别失败
error_msg = result.get('err_msg', '未知错误')
# 提供更详细的错误信息
if result.get('err_no') == 3311:
return f"采样率参数错误~ 请确保音频采样率为8000Hz或16000Hz"
elif result.get('err_no') == 3300:
return f"输入参数不正确~ 请检查音频格式"
elif result.get('err_no') == 3301:
return f"音频质量问题~ 请检查音频文件是否损坏"
else:
return f"识别失败~ 错误信息: {error_msg}"
这部分代码:
设置HTTP请求头,指定内容类型为JSON
发送POST请求到百度语音识别API
解析返回的JSON数据
根据返回的错误码处理不同情况:
成功时返回识别结果
失败时返回相应的错误信息
异常处理
except FileNotFoundError: return "找不到音频文件喵~" except requests.exceptions.RequestException as e: return "网络请求失败喵~" except Exception as e: return "识别过程发生异常喵~"
捕获了三种可能的异常:
文件不存在
网络请求失败
其他未知异常
四、单例模式实现
代码后面部分实现了单例模式,确保整个应用中只有一个BaiduASR实例:
# 全局ASR实例
_asr_instance = None
def get_asr_instance():
"""获取ASR实例(单例模式)"""
global _asr_instance
if _asr_instance is None:
_asr_instance = BaiduASR()
return _asr_instance
单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。这样做的好处是:
避免重复创建对象
节省系统资源
保持全局一致性
五、对外接口函数
为了方便使用,代码提供了两个简单的对外函数:
def validate_audio(file_path):
"""验证音频文件格式(保持原有函数名)"""
asr = get_asr_instance()
is_valid, _, _ = asr.validate_audio(file_path)
return is_valid
def recognize_audio(file_path):
"""语音识别函数(保持原有函数名和功能)"""
asr = get_asr_instance()
return asr.recognize_audio(file_path)
这样外部代码只需要调用这两个函数即可,不需要关心内部的复杂实现。
六、本地调试入口
最后是一个简单的测试代码:
# 本地调试入口
if __name__ == "__main__":
file_path = "../input.wav"
recognize_audio(file_path)
当直接运行这个Python文件时(而不是被导入为模块),会尝试识别"../input.wav"文件。
七、总结
这个百度语音识别的Python实现包含了以下几个关键点:
认证机制:使用OAuth2.0获取访问令牌
音频验证:确保音频格式符合API要求
数据编码:使用base64编码二进制音频数据
API请求:构建正确的HTTP请求并处理响应
错误处理:全面考虑各种可能的错误情况
设计模式:使用单例模式管理实例
通过这样的封装,外部代码可以非常简单地进行语音识别,而不用关心内部复杂的实现细节。
希望这篇详细的解释能帮助你理解这段代码的工作原理!如果有任何不明白的地方,欢迎留言讨论。