📌 关键要点
本文档记录阿里云paraformer-v1异步ASR的完整调试过程,重点解决API调用方式、请求头配置、transcription_url解析等关键问题。
- 核心问题1:必须添加
X-DashScope-Async: enable请求头- 核心问题2:返回的是transcription_url而非直接文本,需二次请求
- 核心问题3:JSON结构为
transcripts[0].text,非result.sentences
阿里云ASR测试页面:https://byp.com.cn/ping/ali-asr-test/
参考已有的Whisper测试页面:
- 路由:/ping/whisper-test/
- 文件:whisper_test.py + whisper_test.html
- 特点:紫色主题,本地模型识别
阿里云ASR测试页:
- 路由:/ping/ali-asr-test/
- 文件:ali_asr_test.py + ali_asr_test.html
- 特点:蓝色主题,云端API识别
{
"code": "AccessDenied",
"message": "current user api does not support synchronous calls"
}
误以为可以使用SDK的同步调用方式,尝试了:
- Recognition.call(temp_wav_path) - 失败
- Recognition(callback=None) - 失败
阿里云ASR的paraformer-v1只支持异步调用,必须: 1. 提交任务获取task_id 2. 轮询任务状态 3. 获取识别结果
改用HTTP API + file_urls方式,但这次仍然失败...
同样的错误再次出现:
{
"code": "AccessDenied",
"message": "current user api does not support synchronous calls"
}
对比voice_handler.py的成功案例,发现关键差异:
# ❌ 错误的代码(缺少请求头)
headers = {
'Authorization': f'Bearer {DASHSCOPE_API_KEY}',
'Content-Type': 'application/json'
}
# ✅ 正确的代码(必须添加X-DashScope-Async)
headers = {
'Authorization': f'Bearer {DASHSCOPE_API_KEY}',
'Content-Type': 'application/json',
'X-DashScope-Async': 'enable' # 关键!启用异步调用
}
⚠️ 阿里云ASR HTTP API必须添加 X-DashScope-Async: enable 请求头,否则返回AccessDenied!
日志显示识别成功,但返回空文本:
🔄 开始阿里云 paraformer-v1 识别...
📤 开始阿里云 ASR 识别,音频大小: 71400 bytes
✅ 阿里云 ASR 识别成功 (1.18秒):
✅ 阿里云 ASR 识别成功 (1.40秒):
前端显示: - ⏱️ 耗时: 1.4秒 - 🤖 模型: paraformer-v1 - 📦 大小: 69.7KB - 但是没有识别文字!
添加调试日志打印完整返回结果:
print(f"📋 完整返回结果: {query_result}")
日志输出:
{
"request_id": "1d70fb51-3464-9802-930f-0b2015af767b",
"output": {
"task_id": "06afea4a-43ca-429a-b523-6bb9b5a82197",
"task_status": "SUCCEEDED",
"results": [{
"file_url": "https://byp.com.cn/static/audio/asr_1779109299_bc3f2387.wav",
"transcription_url": "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/...",
"subtask_status": "SUCCEEDED"
}]
}
}
⚠️ 阿里云返回的不是transcription文本,而是transcription_url!需要再次请求这个URL获取识别结果!
第一次尝试解析(错误):
# ❌ 错误:假设是result.sentences结构
sentences = trans_data.get('result', {}).get('sentences', [])
transcription = ' '.join([s.get('text', '') for s in sentences])
结果:仍然为空
trans_data = trans_resp.json()
print(f"📋 transcription JSON: {trans_data}")
{
"file_url": "https://byp.com.cn/static/audio/asr_1779109552_62ab6ef1.wav",
"properties": {
"channels": [],
"original_sampling_rate": 16000,
"original_duration_in_milliseconds": 3900
},
"transcripts": [
{
"channel_id": 0,
"content_duration_in_milliseconds": 3518,
"text": "今天是星期一。",
"sentences": [...]
}
]
}
⚠️ JSON结构是 transcripts[0].text,不是 result.sentences!
# ✅ 正确的解析方式
transcripts = trans_data.get('transcripts', [])
if transcripts and len(transcripts) > 0:
transcription = transcripts[0].get('text', '')
def ali_asr_transcribe(audio_data, session_id=''):
"""阿里云 paraformer-v1 异步 ASR 识别"""
# 1. 转换音频格式(WebM → WAV)
wav_data = _convert_webm_to_wav(audio_data)
# 2. 保存到static/audio目录
wav_save_path = os.path.join(static_dir, 'audio', filename)
shutil.copy2(temp_wav_path, wav_save_path)
# 3. 生成HTTP URL
audio_url = f'https://byp.com.cn/static/audio/{filename}'
# 4. 提交ASR任务(关键:X-DashScope-Async)
submit_url = 'https://dashscope.aliyuncs.com/api/v1/services/audio/asr/transcription'
headers = {
'Authorization': f'Bearer {DASHSCOPE_API_KEY}',
'Content-Type': 'application/json',
'X-DashScope-Async': 'enable' # 必须!
}
payload = {
'model': 'paraformer-v1',
'input': {'file_urls': [audio_url]},
'parameters': {'format': 'wav', 'sample_rate': 16000}
}
response = req.post(submit_url, headers=headers, json=payload)
task_id = response.json()['output']['task_id']
# 5. 轮询任务状态
while time.time() - start_time < 60:
query_url = f'https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}'
query_result = req.get(query_url, headers=auth_header).json()
if query_result['output']['task_status'] == 'SUCCEEDED':
# 6. 获取transcription_url
transcription_url = query_result['output']['results'][0]['transcription_url']
# 7. 请求transcription_url获取识别文本
trans_data = req.get(transcription_url).json()
# 8. 解析JSON:transcripts[0].text
transcription = trans_data['transcripts'][0]['text']
return transcription, None
| 问题 | 错误做法 | 正确做法 |
|---|---|---|
| 调用方式 | SDK同步调用 | HTTP API异步调用 |
| 请求头 | 缺少X-DashScope-Async | 必须添加 X-DashScope-Async: enable |
| 音频提交 | 直接传二进制 | 必须传HTTP URL(file_urls) |
| 返回结果 | 直接获取transcription | 获取transcription_url再请求 |
| JSON解析 | result.sentences |
transcripts[0].text |
查看 app/ping/voice_handler.py 第228-232行:
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json',
'X-DashScope-Async': 'enable' # 必须
}
关键:voice_handler.py从一开始就使用了正确的请求头!
在本地Windows开发时,即使代码正确也会失败,因为:
https://byp.com.cn/static/audio/xxx.wav⚠️ 阿里云ASR必须部署到服务器上测试,本地无法测试!
app/ping/ali_asr_test.py - 阿里云ASR测试路由(246行)app/ping/templates/ping/ali_asr_test.html - 测试页面模板(695行)app/ping/__init__.py - 注册路由| 对比项 | Whisper测试 | 阿里云ASR测试 |
|---|---|---|
| 路由 | /ping/whisper-test/ |
/ping/ali-asr-test/ |
| 颜色主题 | 紫色 | 蓝色 |
| 识别方式 | 本地模型 | 云端API |
| 需要ffmpeg | ✅ | ✅ |
| 需要联网 | ❌ | ✅ |
| 识别速度 | ~2-3秒 | ~1-2秒 |
| 准确率 | ~85-90% | ~95-98% |
| 成本 | 免费 | ¥0.02/分钟 |
新建的测试页容易遗漏
transcription_url二次请求
多一次网络请求
JSON结构transcripts[0].text
app/ping/voice_handler.py - 成功案例参考/note/extern/人工智能/语音技术/语音识别ASR技术.html - ASR技术总览📝 创建:2026-05-18
🔄 记录完整的4次错误调试过程