对于将音频文件存储在阿里云OSS上的用户,除了文档中介绍的使用SDK集成录音文件识别的开发外,还可以通过函数计算的方式,将录音文件识别通过触发器函数自动执行,将识别结果保存回OSS或者其他存储器上,用户只需关注最终的识别结果,减少SDK集成开发的工作。对于非开发人员,可以通过该方式快速获取识别结果进行分析。函数计算的详细介绍,请阅读 官方文档。
2 效果
说明: 文档中使用的OSS Bucket为nls-file-trans,音频文件存放目录为filetrans/raw,识别结果存放目录为filetrans/result,识别结果保存在json文件中,以文件名_taskId.json
表示识别成功的结果,文件名_taskId_failed.json
表示识别失败的结果。用户在实际使用中,请根据实际情况,修改为自己的Bucket和文件存放目录。
- 通过OSS控制台上传音频文件
通过控制台的“上传文件”按钮,上传音频文件到指定的Bucket路径filetrans/raw:
对应函数计算的触发器(将在后面章节介绍):
识别结果存放路径filetrans/result:
上传的nls-sample-16k.wav音频文件识别结果:
{
"Result": {
"Sentences": [{
"EndTime": 2365,
"SilenceDuration": 0,
"BeginTime": 340,
"Text": "北京的天气。",
"ChannelId": 0,
"SpeechRate": 177,
"EmotionValue": 5.0
}]
},
"TaskId": "fb0474184c6d11e9a213e11db149f2ff",
"StatusCode": 21050000,
"StatusText": "SUCCESS",
"RequestTime": 1553237085804,
"SolveTime": 1553237086146,
"BizDuration": 2956
}
- 通过 常用工具上传音频文件
以ossutil为例:
ossutil cp nls-sample-16k.wav oss://nls-file-trans/filetrans/raw/nls-sample-16k.wav
与控制台上传音频文件的识别流程相同。
3 准备工作
需要准备的内容有:
- 开通OSS服务:有对应的AccessKey ID,AccessKey Secret,OSS EndPoint;
- 开通智能语音交互服务:有对应的AccessKey ID,AccessKey Secret,AppKey;
- 开通函数计算服务;
- 授权:需要给函数计算的账号授权OSS的读写权限。
4 实现方式
我们需要在函数计算上实现的内容有:
- 创建函数计算的服务;
- 创建生成任务的函数,使用OSS触发器,设置第三步的回调URL,生成录音文件识别任务。
- 创建接收回调的函数,使用HTTP触发器,生成回调URL,用于将录音文件识别结果写回OSS。
4.1 创建服务
在函数计算的控制台创建一个服务,可以在创建时进行高级配置,也可以创建后再行设置。
高级配置:在高级配置—>权限配置中,如果没有已有角色,需要创建一个新角色,选择AliyunOSSFullAccess,点击授权。
登录RAM访问控制 > RAM角色管理,找新创建的角色,点击添加权限,添加AliyunOSSFullAccess
、AliyunSTSAssumeRoleAccess
、AliyunNLSFullAccess
权限(如果已经授权,则不要添加)。
4.2 生成任务
生成任务用于提交录音文件识别请求,OSS上传音频文件时,将触发OSS触发器,调用函数,提交录音文件识别请求。
4.2.1 编写函数
在创建的服务下,创建一个函数,用于生成任务:
- 新建一个函数:call_filetrans
- 函数入口:call_filetrans.handler
- 运行环境:Python3
- 函数执行内存:128MB(选择最小值128MB已经够用,这个和函数计算的计费相关)
- 超时时间:600s
函数内容如下,需要用户替换的参数:
- OSS账号相关的AccessKey ID、AccessKey Secret、OSS EndPoint(选择外网访问)
- 录音文件识别账号相关的AccessKey ID、AccessKey Secret、Appkey、回调URL(在创建HTTP触发器时获取)
# -*- coding: utf-8 -*-
import json
import time
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.auth.credentials import StsTokenCredential
from aliyunsdkcore.request import CommonRequest
import oss2
import logging
ossEndPoint = "您的OSS EndPoint" # oss账号EndPoint,请选择外网访问
fileTransAppkey = "您的项目appkey" # 录音文件识别账号 appkey
fileTransCallbackUrl = "您的回调URL" # 在创建HTTP触发器时获取
def handler(event, context):
logger = logging.getLogger()
logger.info(event)
eventObj = json.loads(event)["events"]
eventName=eventObj[0]["eventName"]
bucketName=eventObj[0]["oss"]["bucket"]["name"]
ossFileName=eventObj[0]["oss"]["object"]["key"]
logger.info("eventName: %s" % eventName)
logger.info("bucketName: %s" % bucketName)
logger.info("ossFileName: %s" % ossFileName)
appKey = fileTransAppkey
# 下面这些值是固定的,不需要改动
REGION_ID = "ap-southeast-1"
PRODUCT = "nls-filetrans"
DOMAIN = "filetrans.ap-southeast-1.aliyuncs.com"
API_VERSION = "2019-08-23"
POST_REQUEST_ACTION = "SubmitTask"
GET_REQUEST_ACTION = "GetTaskResult"
KEY_APP_KEY = "appkey"
KEY_FILE_LINK = "file_link"
KEY_VERSION = "version"
KEY_TASK = "Task"
KEY_TASK_ID = "TaskId"
KEY_STATUS_TEXT = "StatusText"
creds = context.credentials
# 创建AcsClient实例
sts_token_credential = StsTokenCredential(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
client = AcsClient(region_id=REGION_ID, credential=sts_token_credential)
# 创建提交录音文件识别请求,并设置请求参数
postRequest = CommonRequest()
postRequest.set_domain(DOMAIN)
postRequest.set_version(API_VERSION)
postRequest.set_product(PRODUCT)
postRequest.set_action_name(POST_REQUEST_ACTION)
postRequest.set_method('POST')
filename = ossFileName.split('/')[-1]
# create file url
auth = oss2.StsAuth(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
bucket = oss2.Bucket(auth, ossEndPoint, bucketName)
fileLink = bucket.sign_url('GET', ossFileName, 3600)
logger.info("file link = " + fileLink)
# 下面的回调地址,在第二步中生成。
callback_url = fileTransCallbackUrl + "/" + filename
logger.info("callback url = " + callback_url)
task = {"SecurityToken": creds.securityToken, KEY_APP_KEY : appKey, KEY_FILE_LINK : fileLink, KET_VERSION : "4.0", "enable_words" : False, "enable_callback" : True, "callback_url" : callback_url}
task = json.dumps(task)
#logger.info (task)
postRequest.add_body_params(KEY_TASK, task)
taskId = ""
try :
# 提交录音文件识别请求,处理服务端返回的响应
postResponse = client.do_action_with_exception(postRequest)
postResponse = json.loads(postResponse)
logger.info(postResponse)
# 获取录音文件识别请求任务的ID,以供识别结果查询使用
statusText = postResponse[KEY_STATUS_TEXT]
if statusText == "SUCCESS" :
logger.info("录音文件识别请求成功响应!")
taskId = postResponse[KEY_TASK_ID]
logger.info("taskId = " + taskId)
else :
logger.info ("录音文件识别请求失败!")
except ServerException as e:
logger.error(e)
except ClientException as e:
logger.error(e)
logger.info('hello world')
logger.info(taskId)
return taskId
4.2.2 配置OSS触发器
说明:由于上传音频文件到OSS的Bucket中,有两种上传方式:Put和Post,所以为了能触发所有的上传事件,需要创建两个OSS触发器:
- 触发器类型:对象存储触发器;
- 触发器名称:可自定义;
- 触发事件:分别选择 oss:ObjectCreated:PutObject 和 oss:ObjectCreated:PostObject 创建两个触发器;
- 触发规则:前缀filetrans/raw/ (根据自己实际情况填写);
- 后缀:.wav (根据自己实际情况填写);
- 角色:如果已有合适角色,可直接选择;如果没有角色,则选择新建角色。
创建结果:
oss:ObjectCreated:PutObject事件:
oss:ObjectCreated:PostObject事件:
创建成功后,可以在OSS控制台对应Bucket的函数计算中找到这两个触发器。
4.3 接收回调
录音文件识别服务识别完成后,将识别结果通过HTTP触发器,写回OSS的Bucket中。在创建HTTP触发器的时候可以获得回调URL,请设置到生成任务函数的回调URL中。
4.3.1 编写函数
在创建的服务下,创建一个函数,用于将识别结果写回OSS:
- 新建一个函数:put_http_post_to_oss
- 函数入口:index.handler
- 运行环境:Python3
- 函数执行内存:128MB(选择最小值128MB已经够用,这个和函数计算的计费相关)
- 超时时间:600s
函数内容如下,需要用户替换的参数:
- OSS的EndPoint(外网访问)
- OSS Bucket名称
- OSS Bucket中的目录,用于存放识别结果文件
# -*- coding: utf-8 -*-
import logging
import oss2
import json
endpoint = "您的OSS EndPoint" # oss配置
bucketName = "您的OSS Bucket名称" # oss配置
resultOssPath = "您的录音文件识别结果存放目录" # oss路径,用于存储识别结果文件
B_OK = b"ok"
def handler(environ, start_response):
logger = logging.getLogger()
context = environ['fc.context']
request_uri = environ['fc.request_uri']
for k, v in environ.items():
if k.startswith("HTTP_"):
# process custom request headers
pass
logger.info("request_uri = " + request_uri)
filename = request_uri.split('/')[-1]
logger.info('filename = ' + filename)
# get request_body
try:
request_body_size = int(environ.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
request_body = environ['wsgi.input'].read(request_body_size)
# parse result
postResponse = json.loads(request_body)
taskId = postResponse['TaskId']
statusText = postResponse['StatusText']
# put to oss
creds = context.credentials
auth = oss2.StsAuth(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
logger.info("creds.accessKeyId = " + creds.accessKeyId)
logger.info("creds.accessKeySecret = " + creds.accessKeySecret)
logger.info("creds.securityToken = " + creds.securityToken)
bucket = oss2.Bucket(auth, endpoint, bucketName)
if statusText == "SUCCESS" :
filename = resultOssPath + "/" + filename + "_" + taskId + '.json'
else :
filename = resultOssPath + "/" + filename + "_" + taskId + '_failed.json'
logger.info('filename = ' + filename)
bucket.put_object(filename, request_body)
# do something here
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [B_OK]
4.3.2 配置HTTP触发器
新建HTTP触发器:
- 服务类型:HTTP 触发器
- 触发器名称:http_post_caller(可自定义)
- 认证方式:anonymous
- 请求方式:POST
创建成功后,会自动生成路径,作为回调URL,请将其设置到生成任务函数的回调URL中。
至此,所有配置已经全部完成,您可以在OSS中上传音频文件,进行测试和使用了。