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

【AIGC】使用Python实现科大讯飞语音服务ASR转录功能:完整指南

文章目录

  • 讯飞ASR转写API完整指南
    • 1. 引言
    • 2. 讯飞ASR API介绍
    • 3. API参数说明
      • 3.1 认证参数
      • 3.2 上传参数
      • 3.3 查询结果参数
      • 3.4 orderResult 字段
      • 3.5 Lattice 字段
      • 3.6 json_1best 字段
      • 3.7 st 字段
    • 4. Python代码实现
      • 4.1 生成签名
      • 4.2 上传音频文件
      • 4.3 获取转写结果
      • 4.4 解析转写结果
    • 5. 请求与返回示例
      • 5.1 成功返回示例
      • 5.4 异步回调
        • 1. 转写结束异步回调状态
    • 6. 文档地址
    • 7. 结论

讯飞ASR转写API完整指南

1. 引言

在这篇博客中,我们将详细解析如何使用讯飞ASR(自动语音识别)API进行音频转写,包括上传音频、查询转写结果及解析返回数据。本文将涵盖API的参数说明,并提供完整的Python代码,确保代码能够顺利执行。

2. 讯飞ASR API介绍

讯飞ASR API提供了一整套音频转写的解决方案,主要流程如下:

  1. 生成签名 - 认证请求的合法性。
  2. 上传音频 - 通过URL方式或本地文件上传音频。
  3. 查询结果 - 轮询转写结果,等待识别完成。
  4. 解析结果 - 处理返回的JSON数据,提取文本和说话人信息。

3. API参数说明

3.1 认证参数

参数名说明
appId讯飞开发者平台分配的应用ID
secret_key用于生成签名的密钥
ts时间戳,单位为秒
signa认证签名,由appId、ts和secret_key计算得出

3.2 上传参数

参数名说明
fileName音频文件名称
fileSize文件大小(若使用URL方式可随意填写)
duration音频时长(单位秒,可随机填写)
language语言(cn代表中文)
audioMode上传模式(urlLink 代表通过URL上传)
audioUrl音频文件的URL(需要URL编码)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3.3 查询结果参数

参数名说明
orderId订单ID,用于查询转写结果
resultType返回结果类型(transfer 表示最终转写文本)

成功

{
 "code": "000000",
 "descInfo": "success",
 "content": {
  "orderId": "DKHJQ202209021522090215490FAAE7DD0008C",
  "taskEstimateTime": 28000
 }
}

失败

{
 "code": "26600",
 "descInfo": "转写业务通用错误"
}

3.4 orderResult 字段

参数名类型说明
latticeList做顺滑功能的识别结果
lattice2List未做顺滑功能的识别结果,当开启顺滑和后语规整后 orderResult 才返回 lattice2 字段(需要开通权限)
labelObject转写结果标签信息,用于补充转写结果相关信息,标记转写结果角色和声道的对应关系

3.5 Lattice 字段

参数名类型说明
json_1bestString单个 VAD 的结果的 JSON 内容

3.6 json_1best 字段

参数名类型说明
stObject单个句子的结果对象

3.7 st 字段

参数名类型说明
bgString单个句子的开始时间,单位毫秒
edString单个句子的结束时间,单位毫秒
rlString分离的角色编号,取值正整数,需开启角色分离的功能才返回对应的分离角色编号
rtList输出词语识别结果集合

4. Python代码实现

4.1 生成签名

在这里插入图片描述

def generate_signa(self):
    """
    生成签名
    :return: 签名字符串
    """
    appid = self.appid
    ts = self.ts
    base_string = appid + ts
    
    md5 = hashlib.md5()
    md5.update(base_string.encode('utf-8'))
    base_string_md5 = md5.hexdigest()
    
    key = self.secret_key.encode('utf-8')
    message = base_string_md5.encode('utf-8')
    hmac_obj = hmac.new(key, message, hashlib.sha1)
    signa = base64.b64encode(hmac_obj.digest()).decode('utf-8')
    
    return signa

4.2 上传音频文件

1、文件上传
#概述
首先调用文件上传接口,上传待转写音频文件的基本信息(文件名、大小等)和相关的可配置参数。
调用成功,返回订单ID(orderId,用于查询结果或者联调排查问题时使用),是后续接口的必传参数。
#请求示例

https://raasr.xfyun.cn/v2/api/upload?duration=200&signa=Je5YsBvPcsbB4qy8Qvzd367fiv0%3D&fileName=%E9%98%B3%E5%85%89%E6%80%BB%E5%9C%A8%E9%A3%8E%E9%9B%A8%E5%90%8E.speex-wb&fileSize=11895&sysDicts=uncivilizedLanguage&appId=3e79d91c&ts=1662101767

#URL

 POST https: //raasr.xfyun.cn/v2/api/upload

#请求头

Content-Type: application/json; charset=UTF-8,Chunked: false

#signa生成

def upload(self):
    """
    上传音频文件
    :return: 上传响应结果
    """
    try:
        file_name = os.path.basename(urllib.parse.unquote(self.audio_url))
        param_dict = {
            "appId": self.appid,
            "signa": self.signa,
            "ts": self.ts,
            "fileName": file_name,
            "fileSize": "10000",
            "duration": "200",
            "language": "cn",
            "audioMode": "urlLink",
            "audioUrl": urllib.parse.quote(self.audio_url, safe='')
        }
        url = lfasr_host + api_upload + "?" + urllib.parse.urlencode(param_dict)
        response = requests.post(url, headers={"Content-Type": "application/json; charset=UTF-8"})
        result = json.loads(response.text)
        
        if str(result.get('code', '')) != '000000':
            return None
        
        return result
    except Exception as e:
        return None

4.3 获取转写结果

status == 4

def get_result(self):
    """
    获取转写结果
    :return: 转写结果
    """
    uploadresp = self.upload()
    if not uploadresp:
        return None
    
    try:
        orderId = uploadresp['content']['orderId']
        param_dict = {
            "appId": self.appid,
            "signa": self.signa,
            "ts": self.ts,
            "orderId": orderId,
            'roleType':1,
            'roleNum':2,
            "resultType": "transfer"
        }
        
        url = lfasr_host + api_get_result + "?" + urllib.parse.urlencode(param_dict)
        status = 3
        while status == 3:
            response = requests.post(url, headers={"Content-Type": "application/json; charset=UTF-8"})
            result = json.loads(response.text)
            
            if str(result.get('code', '')) != '000000':
                continue
                
            status = result['content']['orderInfo']['status']
            if status == 4:
                return result
            time.sleep(5)
        
        return None
    except Exception as e:
        return None

查询结构返回数据

{
 "code": "000000",
 "descInfo": "success",
 "content": {
  "orderInfo": {
   "orderId": "DKHJQ2022090510220905100562536FEF00062",
   "failType": 0,
   "status": 4,
   "originalDuration": 200,
   "realDuration": 1878
  },
  "orderResult": "{\"lattice\":[{\"json_1best\":\"{\\\"st\\\":{\\\"sc\\\":\\\"0.86\\\",\\\"pa\\\":\\\"0\\\",\\\"rt\\\":[{\\\"ws\\\":[{\\\"cw\\\":[{\\\"w\\\":\\\"\\\",\\\"wp\\\":\\\"n\\\",\\\"wc\\\":\\\"1.0000\\\"}],\\\"wb\\\":1,\\\"we\\\":16},{\\\"cw\\\":[{\\\"w\\\":\\\"\\\",\\\"wp\\\":\\\"n\\\",\\\"wc\\\":\\\"1.0000\\\"}],\\\"wb\\\":17,\\\"we\\\":36},{\\\"cw\\\":[{\\\"w\\\":\\\"\\\",\\\"wp\\\":\\\"n\\\",\\\"wc\\\":\\\"1.0000\\\"}],\\\"wb\\\":37,\\\"we\\\":52},{\\\"cw\\\":[{\\\"w\\\":\\\"\\\",\\\"wp\\\":\\\"n\\\",\\\"wc\\\":\\\"1.0000\\\"}],\\\"wb\\\":53,\\\"we\\\":80},{\\\"cw\\\":[{\\\"w\\\":\\\"测试\\\",\\\"wp\\\":\\\"n\\\",\\\"wc\\\":\\\"1.0000\\\"}],\\\"wb\\\":81,\\\"we\\\":116},{\\\"cw\\\":[{\\\"w\\\":\\\"音频\\\",\\\"wp\\\":\\\"n\\\",\\\"wc\\\":\\\"1.0000\\\"}],\\\"wb\\\":117,\\\"we\\\":172},{\\\"cw\\\":[{\\\"w\\\":\\\"\\\",\\\"wp\\\":\\\"p\\\",\\\"wc\\\":\\\"0.0000\\\"}],\\\"wb\\\":172,\\\"we\\\":172},{\\\"cw\\\":[{\\\"w\\\":\\\"\\\",\\\"wp\\\":\\\"g\\\",\\\"wc\\\":\\\"0.0000\\\"}],\\\"wb\\\":172,\\\"we\\\":172}]}],\\\"bg\\\":\\\"50\\\",\\\"rl\\\":\\\"0\\\",\\\"ed\\\":\\\"1840\\\"}}\"}],\"lattice2\":[{\"lid\":\"0\",\"end\":\"1840\",\"begin\":\"50\",\"json_1best\":{\"st\":{\"sc\":\"0.86\",\"pa\":\"0\",\"rt\":[{\"nb\":\"1\",\"nc\":\"1.0\",\"ws\":[{\"cw\":[{\"w\":\"\",\"wp\":\"n\",\"wc\":\"1.0000\"}],\"wb\":1,\"we\":16},{\"cw\":[{\"w\":\"\",\"wp\":\"n\",\"wc\":\"1.0000\"}],\"wb\":17,\"we\":36},{\"cw\":[{\"w\":\"\",\"wp\":\"n\",\"wc\":\"1.0000\"}],\"wb\":37,\"we\":52},{\"cw\":[{\"w\":\"\",\"wp\":\"n\",\"wc\":\"1.0000\"}],\"wb\":53,\"we\":80},{\"cw\":[{\"w\":\"测试\",\"wp\":\"n\",\"wc\":\"1.0000\"}],\"wb\":81,\"we\":116},{\"cw\":[{\"w\":\"音频\",\"wp\":\"n\",\"wc\":\"1.0000\"}],\"wb\":117,\"we\":172},{\"cw\":[{\"w\":\"\",\"wp\":\"p\",\"wc\":\"0.0000\"}],\"wb\":172,\"we\":172},{\"cw\":[{\"w\":\"\",\"wp\":\"g\",\"wc\":\"0.0000\"}],\"wb\":172,\"we\":172}]}],\"pt\":\"reserved\",\"bg\":\"50\",\"si\":\"0\",\"rl\":\"0\",\"ed\":\"1840\"}},\"spk\":\"段落-0\"}]}",
  "taskEstimateTime": 0
 }

4.4 解析转写结果

def parse_result(self, result_json):
    """
    解析转写结果,按说话人分组
    """
    try:
        result = json.loads(result_json)
        speakers = {}
        if 'lattice2' in result:
            for item in result['lattice2']:
                speaker = item.get('spk', '未知')
                json_1best = json.loads(item['json_1best'])
                text = "".join(cw['w'] for rt in json_1best.get('st', {}).get('rt', []) for ws in rt.get('ws', []) for cw in ws.get('cw', []) if 'w' in cw)
                speakers.setdefault(speaker, []).append(text)
        return speakers
    except Exception as e:
        return None
        

5. 请求与返回示例

5.1 成功返回示例

{
 "code": "000000",
 "descInfo": "success",
 "content": {
  "orderId": "DKHJQ202209021522090215490FAAE7DD0008C",
  "taskEstimateTime": 28000
 }
}

5.4 异步回调

1. 转写结束异步回调状态

当订单转写流程结束时会回调用户(如果录音文件转写接口 upload 传了callbackUrl),会把订单号和订单状态返回,具体的格式和参数说明如下: 回调地址示例:

GET http://ip:prot/server/xxx?orderId=DKHJQ202004291620042916580FBC96690001F&status=1

在这里插入图片描述

6. 文档地址

讯飞ASR文档

7. 结论

本文详细讲解了讯飞ASR API的使用流程,包括如何生成签名、上传音频、查询结果并解析返回数据。希望这篇文章对你有所帮助!如果对你有帮助,帮忙给个一键三连,求求了,各位吴彦祖,刘亦菲们

相关文章:

  • ow rank decomposition如何用于矩阵的分解
  • 【CPP面经】大厂CPP后台开发面试经历
  • vue3:项目创建
  • Ollama部署与常用命令
  • C++初阶:C++入门基础
  • 什么是DrawCall?DrawCall为什么会影响游戏运行效率?如何减少DrawCall?
  • 如何将文件中的一部分段落整体删除
  • Grafana使用日志5--如何重置Grafana密码
  • 基于 sklearn 的均值偏移聚类算法的应用
  • [前端] 学习内容总结,css样式居中以及点击包裹a标签的容器元素也能触发a标签的点击事件
  • PyTorch 环境中 CUDA 版本冲突问题排查与解决
  • Linux相关知识(文件系统、目录树、权限管理)和Shell相关知识(字符串、数组)
  • Android 常用命令和工具解析之存储相关
  • 潜水泵,高效排水,守护城市与农田|深圳鼎跃
  • 最快安装ESP8266 ESP832 开发板·Arduino环境的方法
  • Android OpenGLES2.0开发(十一):渲染YUV
  • kafka数据拉取和发送
  • MYSQL之相关子查询
  • Jmeter接口并发测试
  • 图像处理、数据挖掘、数据呈现
  • 自己做的网站403/如何推广网站
  • 在手机制作网站/手机360优化大师官网
  • 网站做ppt模板/什么叫做关键词
  • 淘宝网站优化实例/网络电商推广方案
  • 网站如何做后台留言/网络推广有哪些常见的推广方法
  • 住宅与建设部网站/网络营销论文