全部产品
云市场

使用函数计算方式的录音文件识别

更新时间:2019-10-11 14:20:26

1 简介

对于将音频文件存储在阿里云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音频文件识别结果:

  1. {
  2. "Result": {
  3. "Sentences": [{
  4. "EndTime": 2365,
  5. "SilenceDuration": 0,
  6. "BeginTime": 340,
  7. "Text": "北京的天气。",
  8. "ChannelId": 0,
  9. "SpeechRate": 177,
  10. "EmotionValue": 5.0
  11. }]
  12. },
  13. "TaskId": "fb0474184c6d11e9a213e11db149f2ff",
  14. "StatusCode": 21050000,
  15. "StatusText": "SUCCESS",
  16. "RequestTime": 1553237085804,
  17. "SolveTime": 1553237086146,
  18. "BizDuration": 2956
  19. }

以ossutil为例:

  1. 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 实现方式

我们需要在函数计算上实现的内容有:

  1. 创建函数计算的服务;
  2. 创建生成任务的函数,使用OSS触发器,设置第三步的回调URL,生成录音文件识别任务。
  3. 创建接收回调的函数,使用HTTP触发器,生成回调URL,用于将录音文件识别结果写回OSS。

4.1 创建服务

在函数计算的控制台创建一个服务,可以在创建时进行高级配置,也可以创建后再行设置。新建服务

高级配置:在高级配置—>权限配置中,如果没有已有角色,需要创建一个新角色,选择AliyunOSSFullAccess,点击授权。高级配置

登录RAM访问控制 > RAM角色管理,找新创建的角色,点击添加权限,添加AliyunOSSFullAccessAliyunSTSAssumeRoleAccessAliyunNLSFullAccess权限(如果已经授权,则不要添加)。角色授权

4.2 生成任务

生成任务用于提交录音文件识别请求,OSS上传音频文件时,将触发OSS触发器,调用函数,提交录音文件识别请求。

4.2.1 编写函数

在创建的服务下,创建一个函数,用于生成任务:

  1. 新建一个函数:call_filetrans
  2. 函数入口:call_filetrans.handler
  3. 运行环境:Python3
  4. 函数执行内存:128MB(选择最小值128MB已经够用,这个和函数计算的计费相关)
  5. 超时时间:600s

函数内容如下,需要用户替换的参数:

  1. OSS账号相关的AccessKey ID、AccessKey Secret、OSS EndPoint(选择外网访问)
  2. 录音文件识别账号相关的AccessKey ID、AccessKey Secret、Appkey、回调URL(在创建HTTP触发器时获取)
  1. # -*- coding: utf-8 -*-
  2. import json
  3. import time
  4. from aliyunsdkcore.acs_exception.exceptions import ClientException
  5. from aliyunsdkcore.acs_exception.exceptions import ServerException
  6. from aliyunsdkcore.client import AcsClient
  7. from aliyunsdkcore.auth.credentials import StsTokenCredential
  8. from aliyunsdkcore.request import CommonRequest
  9. import oss2
  10. import logging
  11. ossEndPoint = "您的OSS EndPoint" # oss账号EndPoint,请选择外网访问
  12. fileTransAppkey = "您的项目appkey" # 录音文件识别账号 appkey
  13. fileTransCallbackUrl = "您的回调URL" # 在创建HTTP触发器时获取
  14. def handler(event, context):
  15. logger = logging.getLogger()
  16. logger.info(event)
  17. eventObj = json.loads(event)["events"]
  18. eventName=eventObj[0]["eventName"]
  19. bucketName=eventObj[0]["oss"]["bucket"]["name"]
  20. ossFileName=eventObj[0]["oss"]["object"]["key"]
  21. logger.info("eventName: %s" % eventName)
  22. logger.info("bucketName: %s" % bucketName)
  23. logger.info("ossFileName: %s" % ossFileName)
  24. appKey = fileTransAppkey
  25. # 下面这些值是固定的,不需要改动
  26. REGION_ID = "cn-shanghai"
  27. PRODUCT = "nls-filetrans"
  28. DOMAIN = "filetrans.cn-shanghai.aliyuncs.com"
  29. API_VERSION = "2018-08-17"
  30. POST_REQUEST_ACTION = "SubmitTask"
  31. GET_REQUEST_ACTION = "GetTaskResult"
  32. KEY_APP_KEY = "appkey"
  33. KEY_FILE_LINK = "file_link"
  34. KEY_VERSION = "version"
  35. KEY_TASK = "Task"
  36. KEY_TASK_ID = "TaskId"
  37. KEY_STATUS_TEXT = "StatusText"
  38. creds = context.credentials
  39. # 创建AcsClient实例
  40. sts_token_credential = StsTokenCredential(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
  41. client = AcsClient(region_id=REGION_ID, credential=sts_token_credential)
  42. # 创建提交录音文件识别请求,并设置请求参数
  43. postRequest = CommonRequest()
  44. postRequest.set_domain(DOMAIN)
  45. postRequest.set_version(API_VERSION)
  46. postRequest.set_product(PRODUCT)
  47. postRequest.set_action_name(POST_REQUEST_ACTION)
  48. postRequest.set_method('POST')
  49. filename = ossFileName.split('/')[-1]
  50. # create file url
  51. auth = oss2.StsAuth(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
  52. bucket = oss2.Bucket(auth, ossEndPoint, bucketName)
  53. fileLink = bucket.sign_url('GET', ossFileName, 3600)
  54. logger.info("file link = " + fileLink)
  55. # 下面的回调地址,在第二步中生成。
  56. callback_url = fileTransCallbackUrl + "/" + filename
  57. logger.info("callback url = " + callback_url)
  58. 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}
  59. task = json.dumps(task)
  60. #logger.info (task)
  61. postRequest.add_body_params(KEY_TASK, task)
  62. taskId = ""
  63. try :
  64. # 提交录音文件识别请求,处理服务端返回的响应
  65. postResponse = client.do_action_with_exception(postRequest)
  66. postResponse = json.loads(postResponse)
  67. logger.info(postResponse)
  68. # 获取录音文件识别请求任务的ID,以供识别结果查询使用
  69. statusText = postResponse[KEY_STATUS_TEXT]
  70. if statusText == "SUCCESS" :
  71. logger.info("录音文件识别请求成功响应!")
  72. taskId = postResponse[KEY_TASK_ID]
  73. logger.info("taskId = " + taskId)
  74. else :
  75. logger.info ("录音文件识别请求失败!")
  76. except ServerException as e:
  77. logger.error(e)
  78. except ClientException as e:
  79. logger.error(e)
  80. logger.info('hello world')
  81. logger.info(taskId)
  82. return taskId

4.2.2 配置OSS触发器

说明:由于上传音频文件到OSS的Bucket中,有两种上传方式:Put和Post,所以为了能触发所有的上传事件,需要创建两个OSS触发器:

  • 触发器类型:对象存储触发器;
  • 触发器名称:可自定义;
  • 触发事件:分别选择 oss:ObjectCreated:PutObject 和 oss:ObjectCreated:PostObject 创建两个触发器;
  • 触发规则:前缀filetrans/raw/ (根据自己实际情况填写);
  • 后缀:.wav (根据自己实际情况填写);
  • 角色:如果已有合适角色,可直接选择;如果没有角色,则选择新建角色。

创建结果:

oss:ObjectCreated:PutObject事件:

putobject

oss:ObjectCreated:PostObject事件:

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

函数内容如下,需要用户替换的参数:

  1. OSS的EndPoint(外网访问)
  2. OSS Bucket名称
  3. OSS Bucket中的目录,用于存放识别结果文件
  1. # -*- coding: utf-8 -*-
  2. import logging
  3. import oss2
  4. import json
  5. endpoint = "您的OSS EndPoint" # oss配置
  6. bucketName = "您的OSS Bucket名称" # oss配置
  7. resultOssPath = "您的录音文件识别结果存放目录" # oss路径,用于存储识别结果文件
  8. B_OK = b"ok"
  9. def handler(environ, start_response):
  10. logger = logging.getLogger()
  11. context = environ['fc.context']
  12. request_uri = environ['fc.request_uri']
  13. for k, v in environ.items():
  14. if k.startswith("HTTP_"):
  15. # process custom request headers
  16. pass
  17. logger.info("request_uri = " + request_uri)
  18. filename = request_uri.split('/')[-1]
  19. logger.info('filename = ' + filename)
  20. # get request_body
  21. try:
  22. request_body_size = int(environ.get('CONTENT_LENGTH', 0))
  23. except (ValueError):
  24. request_body_size = 0
  25. request_body = environ['wsgi.input'].read(request_body_size)
  26. # parse result
  27. postResponse = json.loads(request_body)
  28. taskId = postResponse['TaskId']
  29. statusText = postResponse['StatusText']
  30. # put to oss
  31. creds = context.credentials
  32. auth = oss2.StsAuth(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
  33. logger.info("creds.accessKeyId = " + creds.accessKeyId)
  34. logger.info("creds.accessKeySecret = " + creds.accessKeySecret)
  35. logger.info("creds.securityToken = " + creds.securityToken)
  36. bucket = oss2.Bucket(auth, endpoint, bucketName)
  37. if statusText == "SUCCESS" :
  38. filename = resultOssPath + "/" + filename + "_" + taskId + '.json'
  39. else :
  40. filename = resultOssPath + "/" + filename + "_" + taskId + '_failed.json'
  41. logger.info('filename = ' + filename)
  42. bucket.put_object(filename, request_body)
  43. # do something here
  44. status = '200 OK'
  45. response_headers = [('Content-type', 'text/plain')]
  46. start_response(status, response_headers)
  47. return [B_OK]

4.3.2 配置HTTP触发器

新建HTTP触发器:

  • 服务类型:HTTP 触发器
  • 触发器名称:http_post_caller(可自定义)
  • 认证方式:anonymous
  • 请求方式:POST

创建成功后,会自动生成路径,作为回调URL,请将其设置到生成任务函数的回调URL中。

http触发器

至此,所有配置已经全部完成,您可以在OSS中上传音频文件,进行测试和使用了。