目录

关于音视频文案提取

如何使用 Python 白嫖腾讯云的语音转文字

长时间的电话 / 会议录音 / 演讲视频之类的各种音视频媒体文件的信息,如果有长期存储的需求的话,你可能会因为体积积太大,不方便进行信息检索而头疼。但如果转成文字,润色后整理成文字稿,无论是从存储体积或是信息检索方面,都会比直接存储音视频媒体更方便些。

尝遍了市面上各种音频转文字的野鸡产品后,我最终还是选择用大厂提供的 API ,to B 的产品在价格和可定制性上肯定比 to C 的产品更有优势。

关于如何将视频转音频,手段很多,比如使用 FFmpeg 可以将视频转为音频:

ffmpeg -i input.mp4 -vn -acodec copy audio.mp3

一、音频转文字究竟有多贵?

参考当前的大型互联网厂商提供的音频转文字服务定价,讯飞最贵、百度云论单价虽然最便宜,但起购门槛金额较高,比较适合商用走量、,腾讯云的价格最合适,而且最关键的是腾讯云每月都有附赠一定量的额度,可以无限白嫖。

1.1、讯飞

语音转写:文档地址

产品价格:文档地址

  • 套餐一( 20 小时) 168 元 / 单价 8.4
  • 套餐二( 200 小时) 980 元 / 单价 4.9
  • 套餐三( 1000 小时) 3900 元 / 单价 3.9
  • 套餐四( 3000 小时) 10500 元 / 单价 3.5

1.2、百度云

音频文件转写:文档地址

按小时包预付费:文档地址

按调用时长后付费:文档地址

按小时包预付费

  • 套餐一( 1000 小时) 1200 元 / 单价 1.2
  • 套餐二( 10000 小时) 9000 元 / 单价 0.9
  • 套餐三( 100000 小时) 70000 元 / 单价 0.7
  • 套餐四( 500000 小时) 300000 元 / 单价 0.6

按调用时长后付费

  • 每小时 2 元,系统按用户实际使用,每小时出账单实时扣费,账户内需保留足量余额。

1.3、腾讯云

语音识别 ASR:https://cloud.tencent.com/product/asr

免费配额:https://console.cloud.tencent.com/asr/resourcebundle

资源包购买地址:https://buy.cloud.tencent.com/asr

录音文件识别(五小时内出结果)

  • 套餐一( 60 小时) 90 元 / 单价 1.5
  • 套餐二( 1000 小时) 1200 元 / 单价 1.2
  • 套餐三( 10000 小时) 10000 元 / 单价 1
  • 套餐四( 100000 小时) 80000 元 / 单价 0.8
  • 套餐五( 300000 小时) 210000 元 / 单价 0.7

支持中文普通话、英语、粤语、日语、泰语。对时长5小时以内的录音文件进行识别,异步返回识别全部结果。
支持语音 URL 和本地语音文件两种请求方式。
语音 URL 的音频时长不能长于5小时,文件大小不超过512MB。
本地语音文件不能大于5MB。
提交录音文件识别请求后,在5小时内完成识别(半小时内发送超过1000小时录音或者2万条识别任务的除外),识别结果在服务端可保存7天 支持回调或轮询的方式获取结果

录音文件识别极速版(准实时)

  • 套餐一( 30 小时) 72 元 / 单价 2.3
  • 套餐二( 1000 小时) 1500 元 / 单价 1.5
  • 套餐三( 10000 小时) 12000 元 / 单价 1.2
  • 套餐四( 100000 小时) 110000 元 / 单价 1.1
  • 套餐五( 300000 小时) 300000 元 / 单价 1

仅支持中文普通话,使用者通过 HTTPS POST 方式上传一段音频并在极短时间内同步返回识别结果,可满足音视频字幕、准实时质检等场景下对语音文件识别时效性的要求。
支持100MB以内音频文件的识别

1.4、阿里云

录音文件识别:文档地址

录音文件识别资源包:购买链接

录音文件识别(极速版)资源包:购买链接

录音文件识别(六小时内出结果)

  • 套餐一( 40 小时) 100 元 / 单价 2.5
  • 套餐二( 1000 小时) 1200 元 / 单价 1.2
  • 套餐三( 20000 小时) 20000 元 / 单价 1
  • 套餐四( 100000 小时) 90000 元 / 单价 0.9
  • 套餐五( 250000 小时) 200000 元 / 单价 0.8

录音文件识别极速版(30分钟以内时长的音频转写完成时间不超过10秒)

  • 套餐一( 40 小时) 90 元 / 单价 2.5
  • 套餐二( 1000 小时) 1560 元 / 单价 1.56
  • 套餐三( 20000 小时) 26000 元 / 单价 1.3
  • 套餐四( 100000 小时) 117000 元 / 单价 1.17
  • 套餐五( 250000 小时) 260000 元 / 单价 1.04

二、对接腾讯云

在使用腾讯云 API 之前,你需要先获取三个必要的参数。

2.1、录音文件识别极速版(V2)

极速版演示,目前腾讯云给的免费配额是每月 5 小时。

极速版仅支持中文普通话,通过 HTTPS POST 方式上传一段音频并在极短时间内同步返回识别结果,可满足音视频字幕、准实时质检等场景下对语音文件识别时效性的要求。支持100MB以内音频文件的识别。

1)将真实的值填入下方源代码的 APPID、SECRET_ID、SECRET_KEY 这三个参数中;

2)将源代码中的 audio 参数修改为本地音频文件的相对或绝对路径;

3)run it。

# 录音文件识别极速版 v2版本
# API 文档:https://cloud.tencent.com/document/api/1093/52097
# 签名生成:https://cloud.tencent.com/document/api/1093/52097#sign

import json
import requests
import time

import hashlib
import hmac
import base64


# 调用者身份
class Credential:
    def __init__(self, app_id, secret_id, secret_key):
        self.app_id = app_id
        self.secret_id = secret_id
        self.secret_key = secret_key


# 服务端信息
class Server:
    def __init__(self, protocol, host, port, uri):
        self.protocol = protocol
        self.host = host
        self.port = port
        self.uri = uri


# 打印日志
def show(title="", content=object, level="INFO"):
    print("[" + level + "] " + title)
    print(content)
    print()


# 获取时间戳
def getTimestamp():
    t = time.time()
    # return t # 原始时间数据
    return int(t)  # 秒级时间戳
    # return int(round(t * 1000))  # 毫秒级时间戳
    # return int(round(t * 1000000))  # 微秒级时间戳


# 字典序排序
def format_sign_string(param):
    param = sorted(param.items(), key=lambda d: d[0])

    signstr = f"POST{server.host + server.uri + credential.app_id}"
    for t in param:
        if 'appid' in t:
            signstr += str(t[1])
            break
    signstr += "?"
    for x in param:
        tmp = x
        if 'appid' in x:
            continue
        for t in tmp:
            signstr += str(t)
            signstr += "="
        signstr = signstr[:-1]
        signstr += "&"
    signstr = signstr[:-1]

    return signstr


# 签名
def sign(signstr, secret_key):
    hmacstr = hmac.new(secret_key.encode('utf-8'),
                       signstr.encode('utf-8'), hashlib.sha1).digest()
    s = base64.b64encode(hmacstr)
    s = s.decode('utf-8')
    return s

# 调用者信息对象初始化
# 在腾讯云控制台账号信息页面查看账号 APPID:https://console.cloud.tencent.com/developer
# 访问管理页面获取 SecretID 和 SecretKey:https://console.cloud.tencent.com/cam/capi
APPID = ""
SECRET_ID = ""
SECRET_KEY = ""
credential = Credential(APPID, SECRET_ID, SECRET_KEY)

# 服务端信息对象初始化
PROTOCOL = "https://"
HOST = "asr.cloud.tencent.com"
PORT = ""
URI = "/asr/flash/v1/"
server = Server(PROTOCOL, HOST, PORT, URI)

# 构造参数
params = {
    # 用户在腾讯云注册账号 AppId 对应的 SecretId
    "secretid": f"{credential.secret_id}",

    # 引擎模型类型。8k_zh:8k 中文普通话通用;16k_zh:16k 中文普通话通用;16k_zh_video:16k 音视频领域。
    "engine_type": "16k_zh",

    # 音频格式。支持 wav、pcm、ogg-opus、speex、silk、mp3、m4a、aac。
    "voice_format": "mp3",

    # 当前 UNIX 时间戳,如果与当前时间相差超过3分钟,会报签名失败错误。
    "timestamp": getTimestamp(),
}

# 是否开启说话人分离(目前支持中文普通话引擎),默认为0,0:不开启,1:开启。
# params["speaker_diarization"] = 0;

# 是否过滤脏词(目前支持中文普通话引擎),默认为0。0:不过滤脏词;1:过滤脏词;2:将脏词替换为 *。
# params["filter_dirty"] = 0;

# 是否过滤语气词(目前支持中文普通话引擎),默认为0。0:不过滤语气词;1:部分过滤;2:严格过滤。
# params["filter_modal"] = 0;

# 是否过滤标点符号(目前支持中文普通话引擎),默认为0。0:不过滤,1:过滤句末标点,2:过滤所有标点。
# params["filter_punc"] = 0;

# 是否进行阿拉伯数字智能转换,默认为1。0:全部转为中文数字;1:根据场景智能转换为阿拉伯数字。
params["convert_num_mode"] = 1;

# 是否显示词级别时间戳,默认为0。0:不显示;1:显示,不包含标点时间戳,2:显示,包含标点时间戳。
# params["word_info"] = 0;

# 是否只识别首个声道,默认为1。0:识别所有声道;1:识别首个声道。
# params["first_channel_only"] = 1;

show("生成 params", params)

# 获取 signature
signstr = format_sign_string(params)
signature = sign(signstr, SECRET_KEY)
show("生成 signstr", signstr)
show("生成 signature", signature)

# 计算 URL
URL = server.protocol + signstr[4::]
show("计算 URL", URL)

# 构造 header
headers = {
    "Host": "asr.cloud.tencent.com",
    "Authorization": f"{signature}",
    # "Content-Type": "application/octet-stream",
    # "Content-Length": "请求长度,此处对应语音数据字节数,单位:字节"
}
show("生成 headers", headers)

# 音频路径
audio = "./外卖佣金到底有多高.mp3"
with open(audio, 'rb') as f:
    # 读取音频数据
    data = f.read()

    # 调用腾讯云语音识别 API
    e = requests.post(URL, headers=headers, data=data)
    responese = json.loads(e.text)
    code = responese["code"]
    if code != 0:
        show("识别失败", responese)
    else:
        show("识别成功", responese)

    # 一个channl_result对应一个声道的识别结果
    # 大多数音频是单声道,对应一个channl_result
    for channl_result in responese["flash_result"]:
        channel_id = channl_result['channel_id']
        text = channl_result['text']

        show(f"channel_id: {channel_id}", text)

输出

[INFO] 生成 params
{'secretid': 'xxxxxxxxxxxxxxxxxxx', 'engine_type': '16k_zh', 'voice_format': 'mp3', 'timestamp': xxxxxxxxx, 'convert_num_mode': 1}

[INFO] 生成 signstr
POSTasr.cloud.tencent.com/asr/flash/v1/xxxxxxxxxxxxx?convert_num_mode=1&engine_type=16k_zh&secretid=xxxxxxxxxxxxxxxxxx&timestamp=xxxxxxxxxx&voice_format=mp3

[INFO] 生成 signature
xxxxxxxxxxxxxxxxxxx=

[INFO] 计算 URL
https://asr.cloud.tencent.com/asr/flash/v1/xxxxxxxxx?convert_num_mode=1&engine_type=16k_zh&secretid=xxxxxxxxxxxxxxxxxxxxxxxxxx&timestamp=xxxxxxx&voice_format=mp3

[INFO] 生成 headers
{'Host': 'asr.cloud.tencent.com', 'Authorization': 'xxxxxxxxxxxxxxxxxxxxx='}

[INFO] 识别成功
{'request_id': 'xxxxxxxxxxxxxxxxxx', 'code': 0, 'message': '', 'audio_duration': xxxxxxxx, 'flash_result': [{'text': '测试音频转文字内容', 'start_time': xxxxxxxxx, 'end_time': xxxxxx, 'speaker_id': 0}]}]}

[INFO] channel_id: 0
测试音频转文字内容

如果有特殊需求,根据可选的 params 参数去调整就好了。

2.2、录音文件识别(V3)

录音文件识别演示,目前腾讯云给的免费配额是每月 10 小时。

录音文件识别请求 API 文档:https://cloud.tencent.com/document/api/1093/37823

录音文件识别结果查询 API 文档:https://cloud.tencent.com/document/api/1093/37822

腾讯云 API 3.0 提供了配套的开发工具集 SDK:https://cloud.tencent.com/document/api/1093/37823#SDK

2.2.1、安装 Python SDK

在使用录音文件识别时,需要通过 pip 方式安装腾讯云提供的 Python 版本 SDK:

pip install --upgrade tencentcloud-sdk-python

# 中国大陆地区的用户可以使用国内镜像源提高下载速度
pip install -i https://mirrors.tencent.com/pypi/simple/ --upgrade tencentcloud-sdk-python。

2.2.2、上传本地录音文件识别

腾讯云提供的 API Explorer 可以很方便的生成代码和参数:https://console.cloud.tencent.com/api/explorer?Product=asr&Version=2019-06-14&Action=CreateRecTask&SignVersion=

下面我提供一个自己的 demo ,运行前记得替换三个参数为真实值。其中 audio 是本地录音文件相对路径或绝对路径。

import json
import base64
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.asr.v20190614 import asr_client, models

SecretId = "xxxxxxxxxxxxxxxxxxxxxxxxx"
SecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxx"
audio = "./audio.mp3"

# 将录音转为字符串
Data = ""
with open(audio, 'rb') as f:
    # 读取音频数据
    Data = f.read()

Data = base64.b64encode(Data)
Data = Data.decode()

try:
    cred = credential.Credential(SecretId, SecretKey)
    httpProfile = HttpProfile()
    httpProfile.endpoint = "asr.tencentcloudapi.com"

    clientProfile = ClientProfile()
    clientProfile.httpProfile = httpProfile
    client = asr_client.AsrClient(cred, "", clientProfile)

    req = models.CreateRecTaskRequest()
    params = {
        '''
        引擎模型类型。 这里的 k 指的是采样率
            电话场景: 
                • 8k_en:电话8k英语; 
                • 8k_zh:电话8k中文普通话通用; 
            
            非电话场景: 
                • 16k_zh:16k 中文普通话通用; 
                • 16k_zh_video:16k 音视频领域; 
                • 16k_en:16k 英语; 
                • 16k_ca:16k 粤语; 
                • 16k_ja:16k 日语; 
                • 16k_zh_edu 中文教育; 
                • 16k_en_edu 英文教育; 
                • 16k_zh_medical 医疗;
                • 16k_th 泰语;
        '''
        "EngineModelType": "16k_zh",

        '''
            识别声道数。注意:录音识别会自动将音频转码为填写的识别声道数
                1:单声道;
                2:双声道(仅支持 8k_zh 引擎模)。
        '''
        "ChannelNum": 1,

        '''
            识别结果返回形式。
                0: 识别结果文本(含分段时间戳); 
                1:词级别粒度的详细识别结果(不含标点,含语速值);
                2:词级别粒度的详细识别结果(包含标点、语速值)
        '''
        "ResTextFormat": 0,

        '''
            语音数据来源。
                0:语音 URL;
                1:语音数据(post body)。
        '''
        "SourceType": 1,

        '''
            语音数据,当SourceType 值为1时必须填写,为0可不写。
                要base64编码(采用python语言时注意读取文件应该为string而不是byte,以byte格式读取后要decode()。
                编码后的数据不可带有回车换行符)。音频数据要小于5MB。
        '''
        "Data": Data
    }
    req.from_json_string(json.dumps(params))

    resp = client.CreateRecTask(req)
    print(resp.to_json_string())

except TencentCloudSDKException as err:
    print(err)

输出

{
    "Data":{
        "TaskId":1234567890
    },
    "RequestId":"f1234567-89a4-1234-12d3-d56bdd9aac1a"
}

请求成功后,返回的 JSON 中 Data -> TaskId 就是我们此次上传任务的 ID ,需要拿这个 ID 去轮训另一个接口,查询是否成功。

2.2.3、查询录音文件识别结果

腾讯云提供的 API Explorer 可以很方便的生成代码和参数:https://console.cloud.tencent.com/api/explorer?Product=asr&Version=2019-06-14&Action=DescribeTaskStatus&SignVersion=

用 TaskID 查询识别结果。

import json
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.asr.v20190614 import asr_client, models

SecretId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
SecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
TaskId = 1234567890

try:
    cred = credential.Credential(SecretId, SecretKey)
    httpProfile = HttpProfile()
    httpProfile.endpoint = "asr.tencentcloudapi.com"

    clientProfile = ClientProfile()
    clientProfile.httpProfile = httpProfile
    client = asr_client.AsrClient(cred, "", clientProfile)

    req = models.DescribeTaskStatusRequest()
    params = {
        "TaskId": TaskId
    }
    req.from_json_string(json.dumps(params))

    resp = client.DescribeTaskStatus(req)
    print(resp.to_json_string())

except TencentCloudSDKException as err:
    print(err)

输出:

{
    "Data":{
        "TaskId":1234567890,
        "Status":2,
        "StatusStr":"success",
        "Result":"[0:0.000,1:0.320]  识别结果。\n[1:0.320,2:0.360]  识别结果。\n[2:0.360,3:0.380]  识别结果。\n[3:0.380,4:0.400]  识别结果。\n[4:0.400,5:0.420]  识别结果。\n",
        "ErrorMsg":"",
        "ResultDetail":null
    },
    "RequestId":"12345678-1234-1234-1234-b11234567890"
}

2.3、一句话识别(V3)

文档地址:https://cloud.tencent.com/document/product/1093/35646

API Explorer:https://console.cloud.tencent.com/api/explorer?Product=asr&Version=2019-06-14&Action=SentenceRecognition&SignVersion=

2.3.1、安装 Python SDK

在使用录音文件识别时,需要通过 pip 方式安装腾讯云提供的 Python 版本 SDK:

pip install --upgrade tencentcloud-sdk-python

# 中国大陆地区的用户可以使用国内镜像源提高下载速度
pip install -i https://mirrors.tencent.com/pypi/simple/ --upgrade tencentcloud-sdk-python。

2.3.2、源码

借助 API Explorer 生成的源码,我修改了一些东西:

import json
import base64
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.asr.v20190614 import asr_client, models

SecretId = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
SecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
audio = "./一句话录音.mp3"

# 将录音转为字符串
Data = ""
with open(audio, 'rb') as f:
    # 读取音频数据
    Data = f.read()

Data = base64.b64encode(Data)
Data = Data.decode()

try:
    cred = credential.Credential(SecretId, SecretKey)
    httpProfile = HttpProfile()
    httpProfile.endpoint = "asr.tencentcloudapi.com"

    clientProfile = ClientProfile()
    clientProfile.httpProfile = httpProfile
    client = asr_client.AsrClient(cred, "", clientProfile)

    req = models.SentenceRecognitionRequest()
    params = {
        "ProjectId": 0,
        "SubServiceType": 2,
        "EngSerViceType": "16k_zh",
        "SourceType": 1,
        "Data": Data,
        "VoiceFormat": "mp3",
        "UsrAudioKey": "uniqueKey-1",
    }
    req.from_json_string(json.dumps(params))

    resp = client.SentenceRecognition(req)
    print(resp.to_json_string())

except TencentCloudSDKException as err:
    print(err)

输出:

{
    "Result":"一句话录音识别内容",
    "AudioDuration":59996,
    "WordSize":0,
    "WordList":null,
    "RequestId":"12345678-4307-46ae-1234-beb3eb051234"
}

REF

长时间的会议录音如何快速转化成文字:https://www.zhihu.com/question/21552953

如何用ffmpeg从mkv视频文件中提取音频?:https://www.zhihu.com/question/420452079