1. 腾讯云语音识别API接入实战
最近在开发一个需要语音转文字功能的小工具,调研了几家云服务商后选择了腾讯云的语音识别API。他们的"一句话识别"接口特别适合处理60秒以内的短语音,准确率不错,接入也相对简单。下面分享我的完整接入过程,包含你可能遇到的所有坑和解决方案。
2. 准备工作与环境配置
2.1 腾讯云账号与密钥获取
首先需要登录腾讯云控制台(如果没有账号需要先注册),在访问管理页面创建API密钥:
- 点击"新建密钥"按钮生成SecretId和SecretKey
- 务必妥善保管SecretKey,它只会在创建时显示一次
- 建议为不同项目创建独立的子账号密钥,不要使用主账号密钥
注意:密钥泄露可能导致资源被滥用产生费用,建议设置使用限额并开启操作保护。
2.2 开通语音识别服务
在产品页面开通语音识别服务:
- 选择"一句话识别"服务
- 查看免费额度(新用户通常有每月一定时长的免费额度)
- 确认计费方式(按调用次数或时长计费)
2.3 Python环境准备
代码需要Python 3.6+环境,主要依赖两个库:
bash复制pip install requests python-dotenv
建议使用virtualenv创建隔离环境:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
3. 核心代码实现解析
3.1 基础请求类封装
我创建了一个TencentAsr类来封装所有API调用逻辑,下面是逐步解析:
python复制class TencentAsr(object):
def __init__(self):
# 从环境变量读取密钥更安全
self.secret_id = os.getenv('TENCENT_SECRET_ID')
self.secret_key = os.getenv('TENCENT_SECRET_KEY')
# API固定参数
self.service = "asr"
self.host = f"{self.service}.tencentcloudapi.com"
self.endpoint = f"https://{self.host}"
self.action = "SentenceRecognition"
self.version = "2019-06-14"
self.region = "ap-shanghai" # 根据实际选择区域
self.timestamp = int(time.time())
实操技巧:不要将密钥硬编码在代码中!使用环境变量或配置文件管理敏感信息。
3.2 音频文件处理
API支持两种音频输入方式:
- 直接上传Base64编码的音频数据
- 提供可公开访问的音频URL
python复制def file_to_base64(self, file_path):
"""检查并转换音频文件为Base64"""
# 检查文件大小
file_size = os.path.getsize(file_path) / (1024 * 1024) # MB
if file_size > 3:
raise ValueError("音频文件不能超过3MB")
# 检查时长(简单估算,1MB≈1分钟16k采样率音频)
if file_size > 1 and "16k" in self.engine_model:
print("警告:音频可能超过60秒限制")
with open(file_path, "rb") as f:
return base64.b64encode(f.read()).decode('utf-8')
音频格式支持情况:
| 格式 | 支持情况 | 备注 |
|---|---|---|
| MP3 | ✅ | 最常用 |
| WAV | ✅ | 需16bit PCM编码 |
| AMR | ✅ | 需窄带8kHz |
| OGG | ❌ | 不支持 |
3.3 签名生成机制详解
腾讯云使用TC3-HMAC-SHA256签名算法,这是最复杂的部分:
python复制def get_authorization(self, params):
# 步骤1:拼接规范请求串
canonical_request = (
"POST\n/\n\n" # 方法 + URI + 查询字符串
f"content-type:application/json; charset=utf-8\n"
f"host:{self.host}\n"
f"x-tc-action:{self.action.lower()}\n\n"
"content-type;host;x-tc-action\n"
f"{hashlib.sha256(json.dumps(params).encode()).hexdigest()}"
)
# 步骤2:拼接待签名字符串
date = datetime.utcfromtimestamp(self.timestamp).strftime("%Y-%m-%d")
credential_scope = f"{date}/{self.service}/tc3_request"
string_to_sign = (
"TC3-HMAC-SHA256\n"
f"{self.timestamp}\n"
f"{credential_scope}\n"
f"{hashlib.sha256(canonical_request.encode()).hexdigest()}"
)
# 步骤3:计算签名
def sign(key, msg):
return hmac.new(key, msg.encode(), hashlib.sha256).digest()
secret_date = sign(f"TC3{self.secret_key}".encode(), date)
secret_service = sign(secret_date, self.service)
secret_signing = sign(secret_service, "tc3_request")
signature = hmac.new(secret_signing, string_to_sign.encode(), hashlib.sha256).hexdigest()
# 步骤4:拼接Authorization
return (
f"TC3-HMAC-SHA256 Credential={self.secret_id}/{credential_scope}, "
f"SignedHeaders=content-type;host;x-tc-action, Signature={signature}"
)
签名常见问题排查:
- 时间戳误差超过5分钟 → 同步服务器时间
- 密钥错误 → 检查SecretId/Key是否正确
- 区域不匹配 → 确认region参数与服务开通区域一致
4. 完整API调用流程
4.1 构造请求参数
python复制def getSentenceRecognition(self, audio_path=None, audio_url=None):
if not (audio_path or audio_url):
raise ValueError("必须提供音频文件路径或URL")
payload = {
"EngSerViceType": "16k_zh",
"VoiceFormat": "mp3",
"FilterDirty": 1, # 开启脏词过滤
"FilterModal": 1 # 开启语气词过滤
}
if audio_path:
payload.update({
"SourceType": 1,
"Data": self.file_to_base64(audio_path)
})
else:
payload.update({
"SourceType": 0,
"Url": audio_url
})
参数说明:
EngSerViceType:引擎模型8k_zh:电话场景(8kHz采样率)16k_zh:通用场景(16kHz)16k_en:英语识别
4.2 发送请求与处理响应
python复制headers = {
"Content-Type": "application/json",
"Authorization": self.get_authorization(payload),
"X-TC-Action": self.action,
"X-TC-Timestamp": str(self.timestamp),
"X-TC-Version": self.version,
"X-TC-Region": self.region
}
response = requests.post(
self.endpoint,
headers=headers,
data=json.dumps(payload, separators=(',', ':'))
)
if response.status_code != 200:
error = response.json().get("Response", {}).get("Error", {})
raise Exception(f"API错误: {error.get('Code')} - {error.get('Message')}")
return response.json().get("Response", {}).get("Result")
5. 实战技巧与性能优化
5.1 音频预处理建议
- 降噪处理:使用sox或ffmpeg预处理音频
bash复制ffmpeg -i input.mp3 -af "highpass=f=300,lowpass=f=3000" output.mp3 - 格式转换:统一转换为16kHz采样率
bash复制
ffmpeg -i input.wav -ar 16000 -ac 1 output.wav - 音量标准化:
bash复制ffmpeg -i input.mp3 -af "loudnorm=I=-16" output.mp3
5.2 错误处理与重试机制
python复制MAX_RETRIES = 3
RETRY_DELAY = 1
for attempt in range(MAX_RETRIES):
try:
result = tencent_asr.getSentenceRecognition(audio_path="test.mp3")
break
except requests.exceptions.RequestException as e:
if attempt == MAX_RETRIES - 1:
raise
time.sleep(RETRY_DELAY * (attempt + 1))
常见错误码处理:
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| AuthFailure | 鉴权失败 | 检查密钥和时间戳 |
| InvalidParameter | 参数错误 | 验证音频格式和大小 |
| RequestLimitExceeded | 配额不足 | 调整调用频率或扩容 |
5.3 批量处理实现
对于大量音频文件,可以使用线程池提高效率:
python复制from concurrent.futures import ThreadPoolExecutor
def batch_process(files):
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(lambda f: tencent_asr.getSentenceRecognition(f), files))
return results
注意:腾讯云API有QPS限制(默认5次/秒),超出会报错,需要控制并发量。
6. 进阶应用场景
6.1 实时语音流识别
虽然一句话识别适合短语音,但通过分块也可以实现准实时识别:
python复制import pyaudio
CHUNK = 16000 # 每次发送1秒的音频(16kHz)
FORMAT = pyaudio.paInt16
CHANNELS = 1
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT, channels=CHANNELS,
rate=16000, input=True,
frames_per_buffer=CHUNK)
while True:
data = stream.read(CHUNK)
# 将data转换为base64并发送
# 注意需要处理中间结果拼接
6.2 与其它服务集成示例
将识别结果自动保存到数据库:
python复制import sqlite3
def save_to_db(text):
conn = sqlite3.connect('speech.db')
c = conn.cursor()
c.execute("INSERT INTO transcripts (content) VALUES (?)", (text,))
conn.commit()
conn.close()
result = tencent_asr.getSentenceRecognition("meeting.mp3")
save_to_db(result)
6.3 准确率优化技巧
- 使用领域热词表(需申请工单开通)
- 开启智能标点(添加
HotwordId参数) - 对于专业术语,提供自定义词库
- 调整
FilterPunc参数控制标点输出
我在实际使用中发现,对于带有口音的语音,先用16k_zh-general模型初筛,再对低置信度部分用8k_zh电话模型重试,准确率能提升15%左右。