asrRealtimeSdk.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (C) 2020 Tencent Cloud.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. const axios = require('axios');
  17. const crypto = require('crypto');
  18. const { secretId, secretKey, appId } = require('../config');
  19. class RealTime {
  20. /**
  21. * 实例化client对象
  22. * @param {obejct} query 配置参数
  23. */
  24. constructor(query) {
  25. this.query = query || null;
  26. }
  27. /**
  28. * 参数签名
  29. * @param {string} signStr 需要签名的参数
  30. * @return {string} 签名后返回的数组
  31. */
  32. sign(signStr) {
  33. const hash = crypto.createHmac('sha1', secretKey || '');
  34. const sign = hash.update(Buffer.from(signStr, 'utf8')).digest('base64');
  35. return sign;
  36. }
  37. /**
  38. * 将请求的参数转为stirng类型
  39. * @param {object} params
  40. * @return {string}
  41. */
  42. formatSignString(params) {
  43. let strParam = '';
  44. let signStr = 'POSTasr.cloud.tencent.com/asr/v1/';
  45. if (appId) {
  46. signStr += appId;
  47. }
  48. const keys = Object.keys(params);
  49. keys.sort();
  50. for (const k in keys) {
  51. if (Object.prototype.hasOwnProperty.call(keys, k)) {
  52. strParam += `&${keys[k]}=${params[keys[k]]}`;
  53. }
  54. }
  55. const strSign = `${signStr}?${strParam.slice(1)}`;
  56. return strSign;
  57. }
  58. /**
  59. * 请求参数组装
  60. */
  61. createQuery() {
  62. const params = {};
  63. const time = new Date().getTime();
  64. params.projectid = 0;
  65. params.secretid = secretId;
  66. params.sub_service_type = 1;
  67. params.engine_model_type = this.query.engine_model_type;
  68. params.res_type = this.query.res_type;
  69. params.voice_format = this.query.voice_format;
  70. params.source = 0;
  71. params.timestamp = `${Math.round(time / 1000)}`;
  72. params.expired = Math.round(time / 1000) + 24 * 60 * 60;
  73. params.nonce = Math.round(time / 100000);
  74. params.voice_id = this.query.voice_id;
  75. params.end = this.query.end;
  76. params.seq = this.query.seq;
  77. // 非必填参数
  78. this.query.hasOwnProperty('hotword_id') && (params.hotword_id = this.query.hotword_id);
  79. this.query.hasOwnProperty('result_text_format') && (params.result_text_format = this.query.result_text_format);
  80. this.query.hasOwnProperty('needvad') && (params.needvad = this.query.needvad);
  81. this.query.hasOwnProperty('filter_dirty') && (params.filter_dirty = this.query.filter_dirty);
  82. this.query.hasOwnProperty('filter_modal') && (params.filter_modal = this.query.filter_modal);
  83. this.query.hasOwnProperty('filter_punc') && (params.filter_punc = this.query.filter_punc);
  84. this.query.hasOwnProperty('convert_num_mode') && (params.convert_num_mode = this.query.convert_num_mode);
  85. return params;
  86. }
  87. /**
  88. * 发起请求
  89. * @param {string} url 请求的url
  90. * @param {object} chunk 音频的buffer
  91. * @param {object} headers 请求头
  92. * @return {Promise<object>} 音频识别结果
  93. */
  94. async doRequest(url, chunk, headers) {
  95. const options = {
  96. url,
  97. method: 'POST',
  98. headers,
  99. data: chunk
  100. };
  101. const response = await axios(options);
  102. const { status, statusText, data } = response;
  103. if (status !== 200) {
  104. throw new Error(`实时语音接口调用失败[${status} - ${statusText}]`);
  105. }
  106. if (data.code !== 0) {
  107. throw new Error(data.message);
  108. }
  109. return data;
  110. }
  111. /**
  112. * 实时语音请求参数组装
  113. * @param {object} chunk
  114. * @return {Promise<object>} 音频识别结果
  115. */
  116. sendRequest(chunk) {
  117. if (chunk.size === 0) {
  118. return '';
  119. }
  120. const query = this.createQuery();
  121. const signStr = this.formatSignString(query);
  122. const autho = this.sign(signStr);
  123. const datalen = chunk.length;
  124. const headers = {};
  125. headers.Authorization = autho;
  126. headers['Content-Length'] = datalen;
  127. headers['Content-Type'] = 'application/octet-stream';
  128. headers.Host = 'asr.cloud.tencent.com';
  129. const reqUrl = `http://${signStr.substring(4, signStr.length)}`;
  130. const res = this.doRequest(reqUrl, chunk, headers);
  131. return res;
  132. }
  133. }
  134. module.exports = RealTime;