公司动态
Python实战:调用腾讯云语音识别API实现音频文件转文字
1. 腾讯云语音识别API快速入门第一次接触语音识别技术时我盯着手机里的语音备忘录发愁——几十条会议录音要整理成文字手动转录简直让人崩溃。直到发现腾讯云的语音识别API用Python脚本5分钟就能把音频变文字工作效率直接翻倍。这个服务特别适合需要处理采访录音、会议记录、课程录音的朋友技术小白也能轻松上手。腾讯云的语音识别服务支持多种音频格式包括常见的PCM、WAV、MP3等。我实测下来16k采样率的单声道PCM文件识别准确率最高特别适合中文语音场景。他们的引擎经过微信、QQ等海量语音数据训练对带口音的普通话识别效果也很不错。下面我就手把手带你走通整个流程。2. 环境准备与SDK安装2.1 开通语音识别服务首先登录腾讯云官网在控制台搜索语音识别。开通服务后会赠送一定的免费额度足够我们测试使用。重点要保存好这三个东西SecretId类似用户名SecretKey类似密码AppID你的账户标识我建议新建一个config.py文件专门存放这些敏感信息后面代码直接引用避免密钥泄露。就像这样# config.py TENCENT_APPID 你的AppID TENCENT_SECRET_ID 你的SecretId TENCENT_SECRET_KEY 你的SecretKey2.2 安装Python SDK打开终端运行这两条命令pip install tencentcloud-sdk-python pip install websocket-client0.48这里有个坑要注意websocket-client必须指定0.48版本新版可能不兼容。我当初没注意版本调试了半天一直报错后来查文档才发现这个问题。安装完成后可以跑个简单测试验证环境from tencentcloud.common import credential cred credential.Credential(临时SecretId, 临时SecretKey) print(cred.secret_id) # 应该能正常打印3. 音频文件预处理实战3.1 选择合适的音频格式腾讯云支持多种音频格式但不同格式识别效果差异很大。经过多次测试我总结出这些经验最佳选择16kHz采样率、单声道的PCM文件兼容格式WAV需包含PCM编码、MP3码率≥128kbps避坑指南避免使用AAC等有损压缩格式可能影响识别准确率用Audacity等工具可以查看和转换音频格式。如果是手机录音建议导出时选择WAV(PCM)格式采样率设为16000Hz。3.2 Base64编码处理API要求音频数据必须经过Base64编码。Python标准库就能搞定import base64 def audio_to_base64(file_path): with open(file_path, rb) as audio_file: audio_data audio_file.read() return base64.b64encode(audio_data).decode(utf-8) # 使用示例 base64_str audio_to_base64(meeting.pcm) print(f编码后长度{len(base64_str)}) # 可以检查数据是否正常这里有个实用技巧先读取文件二进制内容再进行Base64编码。直接对文件路径编码会导致错误这是我踩过的坑。4. 完整API调用流程4.1 创建识别任务先看完整代码后面我会拆解每个关键部分from tencentcloud.common import credential from tencentcloud.common.profile.client_profile import ClientProfile from tencentcloud.common.profile.http_profile import HttpProfile from tencentcloud.asr.v20190614 import asr_client, models import json def create_rec_task(audio_base64): try: # 1. 初始化认证对象 cred credential.Credential( TENCENT_SECRET_ID, TENCENT_SECRET_KEY ) # 2. 配置HTTP参数 http_profile HttpProfile() http_profile.endpoint asr.tencentcloudapi.com # 3. 创建客户端配置 client_profile ClientProfile() client_profile.httpProfile http_profile # 4. 初始化客户端 client asr_client.AsrClient(cred, ap-shanghai, client_profile) # 5. 构造请求参数 req models.CreateRecTaskRequest() params { EngineModelType: 16k_zh_video, # 中文通用模型 ChannelNum: 1, # 单声道 ResTextFormat: 0, # 识别结果文本格式 SourceType: 1, # 本地音频文件 Data: audio_base64 # Base64编码的音频 } req.from_json_string(json.dumps(params)) # 6. 发送请求 resp client.CreateRecTask(req) return json.loads(resp.to_json_string()) except Exception as err: print(fAPI调用出错{err}) return None关键参数说明EngineModelType推荐用16k_zh_video对中文语音优化最好ChannelNum1表示单声道2表示立体声但立体声识别效果反而可能下降ResTextFormat0返回纯文本1返回带时间戳的JSON适合做字幕4.2 查询识别结果识别是异步过程提交任务后会返回一个TaskId用于查询结果def get_rec_result(task_id): try: cred credential.Credential(TENCENT_SECRET_ID, TENCENT_SECRET_KEY) http_profile HttpProfile() http_profile.endpoint asr.tencentcloudapi.com client_profile ClientProfile() client_profile.httpProfile http_profile client asr_client.AsrClient(cred, ap-shanghai, client_profile) req models.DescribeTaskStatusRequest() params {TaskId: task_id} req.from_json_string(json.dumps(params)) resp client.DescribeTaskStatus(req) return json.loads(resp.to_json_string()) except Exception as err: print(f查询结果出错{err}) return None实际使用时需要轮询查询直到状态变为successimport time def wait_for_result(task_id, interval2, timeout60): start_time time.time() while time.time() - start_time timeout: result get_rec_result(task_id) if result[Data][Status] 2: # 2表示成功 return result[Data][Result] elif result[Data][Status] 3: # 3表示失败 raise Exception(识别失败) time.sleep(interval) raise TimeoutError(识别超时)5. 实战技巧与性能优化5.1 错误处理最佳实践在实际项目中我发现这些错误最常见QPS超限免费版QPS限制为10次/秒解决方案是加延迟音频格式错误先用ffmpeg检查格式Base64编码异常确保读取的是二进制模式(rb)改进后的健壮版代码def safe_create_task(audio_path, retry3): for i in range(retry): try: base64_str audio_to_base64(audio_path) if len(base64_str) 100: raise ValueError(音频文件过小或读取异常) result create_rec_task(base64_str) if not result: raise Exception(API返回空结果) return result[TaskId] except Exception as e: print(f第{i1}次尝试失败{str(e)}) if i retry - 1: raise time.sleep(1) # 延迟1秒重试5.2 大文件分片处理超过5MB的音频文件建议分片处理。这是我常用的分片函数import os from pydub import AudioSegment def split_audio(file_path, chunk_size5*1024*1024): # 5MB分片 file_size os.path.getsize(file_path) if file_size chunk_size: return [file_path] audio AudioSegment.from_file(file_path) duration_ms len(audio) chunk_duration int(duration_ms * (chunk_size / file_size)) chunks [] for i in range(0, duration_ms, chunk_duration): chunk audio[i:ichunk_duration] chunk_path f{file_path}_part{i//chunk_duration}.wav chunk.export(chunk_path, formatwav) chunks.append(chunk_path) return chunks使用示例large_audio long_meeting.wav for chunk in split_audio(large_audio): task_id safe_create_task(chunk) result wait_for_result(task_id) print(result)6. 高级功能拓展6.1 实时语音识别除了文件识别腾讯云还提供实时语音识别API。基于WebSocket协议适合直播字幕等场景from tencentcloud.asr.v20190614.asr_client import AsrClient from tencentcloud.asr.v20190614 import models def start_realtime_recognition(callback_func): cred credential.Credential(TENCENT_SECRET_ID, TENCENT_SECRET_KEY) client AsrClient(cred, ap-shanghai) req models.SentenceRecognitionRequest() req.ProjectId 0 req.SubServiceType 2 req.EngineModelType 16k_zh_video req.VoiceFormat wav req.UsrAudioKey user-123 def response_callback(resp): callback_func(resp.Result) client.StartSentenceRecognition(req, response_callback)6.2 自定义热词表针对专业术语如医学术语、产品名称可以上传热词表提升识别准确率def upload_hot_words(hot_words): cred credential.Credential(TENCENT_SECRET_ID, TENCENT_SECRET_KEY) client AsrClient(cred, ap-shanghai) req models.CreateAsrVocabRequest() req.Name 我的热词表 req.Description 专业术语增强 req.WordWeights [{Word: word, Weight: 10} for word in hot_words] resp client.CreateAsrVocab(req) return resp.VocabId使用热词表时在识别请求中添加VocabId参数即可params { EngineModelType: 16k_zh_video, VocabId: 热词表ID, # 其他参数... }7. 常见问题解决方案在实际项目中我整理了几个典型问题的解决方法问题1识别结果出现乱码检查音频采样率是否为16k/8k确认没有错误地将二进制数据当作文本读取尝试更换EngineModelType参数问题2长音频识别超时使用分片处理每片控制在5分钟以内增加查询结果的timeout参数检查网络连接是否稳定问题3特定术语识别不准使用热词表功能提升关键词权重尝试使用16k_zh_medical等专业模型在音频质量允许的情况下降低语速性能优化建议批量处理音频时使用线程池但注意QPS限制本地缓存已识别结果避免重复处理对识别结果建立全文检索索引from concurrent.futures import ThreadPoolExecutor def batch_process(audio_files, max_workers5): with ThreadPoolExecutor(max_workers) as executor: tasks {executor.submit(process_single, f): f for f in audio_files} for future in as_completed(tasks): file tasks[future] try: result future.result() save_result(file, result) except Exception as e: log_error(file, str(e))