QS-baiduyy.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import request from '@/utils/request'
  2. const audioTeam = [];
  3. let audioStartSwitch = false;
  4. const getAudioUrl = 'https://tsn.baidu.com/text2audio';
  5. /**
  6. * 浏览器调用语音合成接口
  7. * 请参考 https://ai.baidu.com/docs#/TTS-API/41ac79a6
  8. * 强烈建议后端访问接口获取token返回给前端
  9. * client_id = API Key & client_secret = secret Key
  10. * 获取token接口: https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=uFYiXWMCiYvx68V4EVyCGeL8j4GAzXD5&client_secret=897Mm2qCj7bC1eHYVDxaWrO38FscTOHD
  11. */
  12. function getBDVoicToken() {
  13. return new Promise((rs, rj) => {
  14. console.log('准备访问接口获取语音token')
  15. request({
  16. url: '/api/baidutoken',
  17. method: 'get',
  18. }).then((res) => {
  19. console.log('访问成功');
  20. rs(res);
  21. }).catch((err) => {
  22. console.log('访问失败');
  23. rj(err);
  24. });
  25. })
  26. }
  27. export default function openVoice(objs) { // 传入需转为语音的文本内容
  28. let lineUp = false;
  29. let returnAudio = false;
  30. if (typeof(objs) !== 'string') {
  31. if (objs && objs.lineUp === true) {
  32. lineUp = true;
  33. }
  34. if (objs && objs.returnAudio === true) {
  35. returnAudio = true;
  36. }
  37. }
  38. if (returnAudio) {
  39. return new Promise((resolve, reject) => {
  40. openVoiceFc(objs, returnAudio).then(res => {
  41. resolve(res);
  42. }).catch(err => {
  43. reject(err)
  44. });
  45. })
  46. }
  47. if (lineUp = true) {
  48. audioTeam.push(objs);
  49. }
  50. console.log(audioTeam);
  51. if (!audioStartSwitch) {
  52. audioStartSwitch = true;
  53. openVoiceFc(objs);
  54. }
  55. }
  56. function openVoiceFc(objs, returnAudio) {
  57. console.log('准备获取语音tok', objs);
  58. if (returnAudio) {
  59. return new Promise((resolve, reject) => {
  60. getBDVoicToken().then(res => {
  61. console.log('获取语音tok接口成功');
  62. if (res.data && res.data.access_token) {
  63. console.log('token: ' + res.data.access_token);
  64. resolve(tts(objs, res.data.access_token, returnAudio));
  65. } else {
  66. console.log('获取语音tok接口为空');
  67. reject('获取语音tok接口为空');
  68. }
  69. }).catch(err => {
  70. console.log('获取语音tok接口失败');
  71. reject(err || '获取语音tok接口失败');
  72. })
  73. })
  74. } else {
  75. getBDVoicToken().then(res => {
  76. console.log('获取语音tok接口成功', res.data);
  77. if (res.data && res.data.access_token) {
  78. console.log('token: ' + res.data.access_token);
  79. tts(objs, res.data.access_token);
  80. } else {
  81. console.log('获取语音tok接口为空');
  82. }
  83. }).catch(err => {
  84. console.log('获取语音tok接口失败');
  85. })
  86. }
  87. }
  88. function tts(objs, tok, returnAudio) {
  89. console.log(objs, 'info');
  90. if (typeof(objs) == 'string')
  91. objs = {
  92. voiceSet: {
  93. tex: objs
  94. }
  95. };
  96. const data = {
  97. tok,
  98. cuid: tok,
  99. ctp: 1,
  100. lan: 'zh',
  101. ...objs.voiceSet
  102. }
  103. if (returnAudio) {
  104. return btts(data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
  105. }
  106. btts(data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
  107. }
  108. function setAudioSet(options, audio) {
  109. console.log('设置语音播放', options);
  110. if (options) {
  111. audio.volume = options.volume || 1;
  112. audio.startTime = options.startTime || 0;
  113. audio.loop = options.loop || false;
  114. // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO
  115. audio.obeyMuteSwitch = options.obeyMuteSwitch && typeof(options.obeyMuteSwitch) == 'boolean' ? options
  116. .obeyMuteSwitch :
  117. true; //支持微信小程序、百度小程序、头条小程序
  118. // #endif
  119. }
  120. }
  121. function btts(param, options, audioCallback, lineUp, returnAudio) {
  122. let audio = uni.createInnerAudioContext();
  123. setAudioSet(options, audio);
  124. // 序列化参数列表
  125. let fd = [];
  126. for (let k in param) {
  127. fd.push(k + '=' + encodeURIComponent(encodeURIComponent(param[k])));
  128. }
  129. console.log(fd.join('&'), '123456');
  130. audio.src = `${getAudioUrl}?${fd.join('&')}`;
  131. console.log(audio.src, 'wangzhi')
  132. // audio.src = 'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3'
  133. console.log('音频链接', fd.join('&'))
  134. // console.log('https://tsn.baidu.com/text2audio')
  135. if (returnAudio) {
  136. audio.onEnded(() => {
  137. console.log('音频播放结束');
  138. console.log('销毁音频实例');
  139. audio.destroy(); //销毁音频实例
  140. audio = null;
  141. })
  142. audio.onError((e) => {
  143. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function')
  144. audioCallback.onError(e);
  145. console.log('音频播放错误: ' + JSON.stringify(e));
  146. console.log('销毁音频实例');
  147. audio.destroy(); //销毁音频实例
  148. audio = null;
  149. })
  150. audio.onPause(function() {
  151. console.log('end');
  152. audio.destroy()
  153. })
  154. return audio;
  155. }
  156. audio.onPlay(() => {
  157. console.log('音频播放开始');
  158. if (audioCallback && audioCallback.onPlay && typeof(audioCallback.onPlay) == 'function') {
  159. audioCallback.onPlay();
  160. }
  161. })
  162. audio.onPause(() => {
  163. if (audioCallback && audioCallback.onPause && typeof(audioCallback.onPause) == 'function') {
  164. audioCallback.onPause();
  165. }
  166. })
  167. audio.onWaiting(() => {
  168. if (audioCallback && audioCallback.onWaiting && typeof(audioCallback.onWaiting) == 'function') {
  169. audioCallback.onWaiting();
  170. }
  171. })
  172. audio.onStop(() => {
  173. if (audioCallback && audioCallback.onStop && typeof(audioCallback.onStop) == 'function') {
  174. audioCallback.onStop();
  175. }
  176. })
  177. audio.onTimeUpdate(() => {
  178. if (audioCallback && audioCallback.onTimeUpdate && typeof(audioCallback.onTimeUpdate) == 'function') {
  179. audioCallback.onTimeUpdate();
  180. }
  181. })
  182. audio.onSeeking(() => {
  183. if (audioCallback && audioCallback.onSeeking && typeof(audioCallback.onSeeking) == 'function') {
  184. audioCallback.onSeeking();
  185. }
  186. })
  187. audio.onSeeked(() => {
  188. if (audioCallback && audioCallback.onSeeked && typeof(audioCallback.onSeeked) == 'function') {
  189. audioCallback.onSeeked();
  190. }
  191. })
  192. audio.onEnded(() => {
  193. console.log('音频播放结束');
  194. console.log('销毁音频实例');
  195. audio.destroy(); //销毁音频实例
  196. audio = null;
  197. // 清除播报列表对象数据
  198. if (audioCallback && audioCallback.onEnded && typeof(audioCallback.onEnded) == 'function') {
  199. audioCallback.onEnded();
  200. }
  201. if (lineUp !== false) {
  202. // 删除已经播放对象
  203. audioTeam.splice(0, 1);
  204. if (audioTeam.length > 0) {
  205. console.log('队列中');
  206. openVoiceFc(audioTeam[0]);
  207. } else {
  208. console.log('队列为零');
  209. audioStartSwitch = false;
  210. }
  211. }
  212. })
  213. audio.onError(e => {
  214. console.log(audioCallback, '错误')
  215. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback
  216. .onError(e);
  217. console.log('音频播放错误: ' + JSON.stringify(e));
  218. console.log('销毁音频实例');
  219. audio.destroy(); //销毁音频实例
  220. audio = null;
  221. })
  222. audio.play();
  223. }