python 腾讯/百度/讯飞 ASR 语音转文字

因为项目中有需要把微信里的语音转成文本处理, 本次只说语音转文本。
需要注意的是平台对语音的格式有要求, 所以我们需要对语音进行转换格式。

语音转换

使用的工具是ffmpeg, ffmpeg的安装和配置请自行百度。

import os
import tempfile
import subprocess
import base64
import logging
logger = logging.getLogger(__name__)
def mp3_2_wav(_path = None, _byte = None):
    ''' MP3转WAV
    _path和_byte必须存在一个, 优先级_path > _byte
    :param _path: 
    :param _byte:  
    :return: wav的字节流
    '''
    try:
        if _path is None and _byte is None: return
        temp = None
        if _path is None: # 字节流存入临时文件
            temp = tempfile.NamedTemporaryFile(mode="w+b", delete=False)
            temp.write(_byte)
            temp.seek(0)
            _path = temp.name
        if _path is None: return
        # 根据要求进行格式转换,-t 60 最大保存60秒, 采样率 16K, 默认单声道
        logger.info('mp3 ==> wav ========================')
        target_file = tempfile.NamedTemporaryFile(mode="w+b", delete=False, suffix='.wav')
        _perfix = r'ffmpeg'
        command = [_perfix, '-y', '-t', '60', '-i', _path, '-ar', '16K', target_file.name]
        return_code = subprocess.call(command)
        logger.info('mp3 ==> wav ==={}====================='.format(return_code))
        if return_code == 0:
            target_file.seek(0)
            _byte = target_file.read()
            target_file.close()
            os.remove(target_file.name)
            if temp is not None:
                temp.close()
                os.remove(temp.name)
            return _byte
    except Exception as e:
        logger.error('mp3_2_wav error [{}]'.format(e))

百度AI开放平台 API

百度的比较方便,有百度封装好的SDK使用和安装都很方便, 上面API里有详细介绍。

def BAIDU_ASR(_path):
    ''' 百度语音转文字
    
    :param _path: 
    :return: 
    '''
    from aip import AipSpeech
    """ 你的 APPID AK SK """
    APP_ID = '你的 App ID'
    API_KEY = '你的 Api Key'
    SECRET_KEY = '你的 Secret Key'
    client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
    result = client.asr(mp3_2_wav(_path), 'pcm', 16000, {
        'dev_pid': '1537',
    })
    return result.get('result')[0]

讯飞开放平台API

需要把请求的IP在讯飞控制台加入白名单, 否则报错:
{"code":"10105","data":"","desc":"illegal access|illegal client_ip: xxx.xxx.xxx.xxx","sid":"....."}
把报错信息里的xxx.xxx.xxx.xxx加入白名单即可

import json
import time
import requests
def XUNFEI_ASR(_path):
    ''' 讯飞语音转文字
    
    :param _path: 
    :return: 
    '''
    _byte = mp3_2_wav(_path)
    base64_audio = base64.b64encode(_byte)
    import urllib.parse
    body = urllib.parse.urlencode({'audio': base64_audio})
    url = 'http://api.xfyun.cn/v1/service/v1/iat'
    APP_ID = '你的 App ID'
    API_KEY = '你的 Api Key'
    param = {"engine_type": "sms16k", "aue": "raw"}
    import hashlib
    x_param = base64.b64encode(json.dumps(param).replace(' ', '').encode('utf-8'))
    x_time = int(int(round(time.time() * 1000)) / 1000)
    _str = API_KEY + str(x_time) + x_param.decode('utf-8')
    x_checksum = hashlib.md5(_str.encode('utf-8')).hexdigest()
    x_header = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
                'X-Appid': APP_ID,
                'X-CurTime': str(x_time),
                'X-Param': x_param,
                'X-CheckSum': x_checksum}
    res = requests.post(url, body, headers = x_header)
    res = res.content.decode('utf-8')
    return res

腾讯AI开放平台API

腾讯平台主要是签名算法需要注意

签名算法

def get_sign_code(params, app_key):
    ''' 生成签名CODE
    
    1. 计算步骤
    用于计算签名的参数在不同接口之间会有差异,但算法过程固定如下4个步骤。
    将<key, value>请求参数对按key进行字典升序排序,得到有序的参数对列表N
    将列表N中的参数对按URL键值对的格式拼接成字符串,得到字符串T(如:key1=value1&key2=value2),URL键值拼接过程value部分需要URL编码,URL编码算法用大写字母,例如%E8,而不是小写%e8
    将应用密钥以app_key为键名,组成URL键值拼接到字符串T末尾,得到字符串S(如:key1=value1&key2=value2&app_key=密钥)
    对字符串S进行MD5运算,将得到的MD5值所有字符转换成大写,得到接口请求签名
    2. 注意事项
    不同接口要求的参数对不一样,计算签名使用的参数对也不一样
    参数名区分大小写,参数值为空不参与签名
    URL键值拼接过程value部分需要URL编码
    签名有效期5分钟,需要请求接口时刻实时计算签名信息
    :param params: 参数字典
    :param app_key: 
    :return: 
    '''
    if params is None or type(params) != dict or len(params) == 0: return
    try:
        params = sorted(params.items(), key=lambda x:x[0])
        _str = ''
        for item in params:
            key = item[0]
            value = item[1]
            if value == '': continue
            _str += urllib.parse.urlencode({key: value}) + '&'
        _str += 'app_key=' + app_key
        _str = hashlib.md5(_str.encode('utf-8')).hexdigest()
        return _str.upper()
    except Exception as e:
        logger.error('tencen get_sign_code error [{}]'.format(e))

ASR

def TencenASR(_path):
    ''' 腾讯语音转文字
    
    :param _path: 
    :return: 
    '''
    APP_ID = '你的 App ID'
    API_KEY = '你的 Api Key'
    _byte = mp3_2_wav(_path)
    base64_audio = base64.b64encode(_byte)
    url = 'https://api.ai.qq.com/fcgi-bin/aai/aai_asr'
    params = {'app_id': APP_ID, 'time_stamp':int(time.time()), 'nonce_str': 'fa577ce340859f9fe', 'format': 2, 'speech': base64_audio, 'rate': 16000}
    sign = get_sign_code(params, API_KEY)
    params['sign'] = sign
    rt = requests.post(url, data=params)
    jsonData = json.loads(rt.text)
    if jsonData.get('ret') == 0:
        rt = jsonData.get('data').get('text')
        logger.info('Tencen ==> wav ===> {}'.format(rt))
        return rt

至此关键代码开发完成。 比较效果使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335