本文为您介绍如何使用函数计算方式进行录音文件识别。
概述
对于将音频文件存储在阿里云OSS上的用户,除使用SDK集成录音文件识别的开发方式外,还可以通过函数计算的方式,录音文件识别通过触发器函数自动执行,将识别结果保存回OSS或者其他存储器上,您只需关注最终的识别结果,减少SDK集成开发工作量。对于非开发人员,可以通过该方式快速获取识别结果进行分析。函数计算的详细介绍,请参见什么是函数计算。
前提条件
已开通如下服务,且需要给开通函数计算服务的账号授权OSS服务的读写权限:
效果
本文使用的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": "fb0474184c6d11e9a213e11db149****", "StatusCode": 21050000, "StatusText": "SUCCESS", "RequestTime": 1553237085804, "SolveTime": 1553237086146, "BizDuration": 2956 }
通过OSS常用工具上传音频文件
以ossutil为例,与控制台上传音频文件的识别流程相同。
ossutil cp nls-sample-16k.wav https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav
实现方式
需要在函数计算上实现的内容如下:
创建函数计算的服务。
创建生成任务的函数,使用OSS触发器,设置第3步的回调URL,生成录音文件识别任务。
创建接收回调的函数,使用HTTP触发器,生成回调URL,用于将录音文件识别结果写回OSS。
步骤一:创建服务
在函数计算的控制台创建一个服务。
可以在创建时进行高级配置,也可以创建后再进行设置。
创建服务角色。
在高级配置 > 权限配置中,如果没有已有角色,需要创建一个新角色,系统模板授权选择AliyunOSSFullAccess,单击点击授权。
添加权限。
登录RAM访问控制,在左侧导航栏选择RAM角色管理,添加
AliyunOSSFullAccess
、AliyunSTSAssumeRoleAccess
、AliyunNLSFullAccess
权限(如果已经授权,则不需要添加)。
步骤二:生成任务
生成任务用于提交录音文件识别请求,OSS上传音频文件时将触发OSS触发器,调用函数,提交录音文件识别请求。
编写函数。
在创建的服务下,创建一个函数,用于生成任务:
函数名称:call_filetrans
函数入口:call_filetrans.handler
运行环境:Python 3
函数执行内存:128 MB(选择最小值128 MB即可,该值与函数计算的计费相关)
超时时间: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 = "your OSS EndPoint" # oss账号EndPoint,请选择外网访问。 fileTransAppkey = "your appkey" # 录音文件识别账号Appkey,获取Appkey请前往控制台:https://nls-portal.console.aliyun.com/applist 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 = "cn-shanghai" PRODUCT = "nls-filetrans" DOMAIN = "filetrans.cn-shanghai.aliyuncs.com" API_VERSION = "2018-08-17" 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, KEY_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
创建并配置OSS触发器。
重要由于上传音频文件到OSS的Bucket中,有两种方式:Put和Post。所以为了触发所有的上传事件,需要创建两个OSS触发器。
参数
说明
触发器类型
对象存储触发器。
触发器名称
自定义名称。
触发事件
分别选择
oss:ObjectCreated:PutObject
和oss:ObjectCreated:PostObject
创建两个触发器。触发规则:前缀
filetrans/raw/
触发规则:后缀
.wav
角色
如果已有合适角色,可直接选择;如果没有角色,则选择新建角色。
创建成功后,可以在OSS控制台对应Bucket的函数计算中找到这两个触发器。
oss:ObjectCreated:PutObject事件:
oss:ObjectCreated:PostObject事件:
步骤三:接收回调
录音文件识别服务识别完成后,将识别结果通过HTTP触发器,写回OSS的Bucket中。在创建HTTP触发器的时候可以获得回调URL,请设置到生成任务函数的回调URL中。
编写函数。
在创建的服务下,创建一个函数,用于将识别结果写回OSS:
函数名称:put_http_post_to_oss
函数入口:index.handler
运行环境:Python 3
函数执行内存:128 MB(选择最小值128 MB,该值与函数计算的计费相关)
超时时间: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]
创建并配置HTTP触发器。
根据下表说明创建成功后,会自动生成路径作为回调URL。请将其设置到生成任务函数的回调URL中。
参数
说明
服务类型
HTTP触发器
触发器名称
http_post_caller
认证方式
anonymous
请求方式
POST