QS-baiduyy.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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');
  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. if (typeof(objs) == 'string')
  90. objs = {
  91. voiceSet: {
  92. tex: objs
  93. }
  94. };
  95. const data = {
  96. tok,
  97. cuid: tok,
  98. ctp: 1,
  99. lan: 'zh',
  100. ...objs.voiceSet
  101. }
  102. if (returnAudio) {
  103. return btts(data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
  104. }
  105. btts(data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
  106. }
  107. function setAudioSet(options, audio) {
  108. console.log('设置语音播放', options);
  109. if (options) {
  110. audio.volume = options.volume || 1;
  111. audio.startTime = options.startTime || 0;
  112. audio.loop = options.loop || false;
  113. // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO
  114. audio.obeyMuteSwitch = options.obeyMuteSwitch && typeof(options.obeyMuteSwitch) == 'boolean' ? options
  115. .obeyMuteSwitch :
  116. true; //支持微信小程序、百度小程序、头条小程序
  117. // #endif
  118. }
  119. }
  120. function btts(param, options, audioCallback, lineUp, returnAudio) {
  121. let audio = uni.createInnerAudioContext();
  122. setAudioSet(options, audio);
  123. // 序列化参数列表
  124. let fd = [];
  125. for (let k in param) {
  126. fd.push(k + '=' + encodeURIComponent(encodeURIComponent(param[k])));
  127. }
  128. audio.src = `${getAudioUrl}?${fd.join('&')}`;
  129. console.log(audio.src, 'wangzhi')
  130. // audio.src = 'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3'
  131. console.log('音频链接', fd.join('&'))
  132. // console.log('https://tsn.baidu.com/text2audio')
  133. if (returnAudio) {
  134. audio.onEnded(() => {
  135. console.log('音频播放结束');
  136. console.log('销毁音频实例');
  137. audio.destroy(); //销毁音频实例
  138. audio = null;
  139. })
  140. audio.onError((e) => {
  141. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function')
  142. audioCallback.onError(e);
  143. console.log('音频播放错误: ' + JSON.stringify(e));
  144. console.log('销毁音频实例');
  145. audio.destroy(); //销毁音频实例
  146. audio = null;
  147. })
  148. audio.onPause(function() {
  149. console.log('end');
  150. audio.destroy()
  151. })
  152. return audio;
  153. }
  154. console.log(audio);
  155. audio.onPlay(() => {
  156. console.log('音频播放开始');
  157. if (audioCallback && audioCallback.onPlay && typeof(audioCallback.onPlay) == 'function') {
  158. audioCallback.onPlay();
  159. }
  160. })
  161. audio.onPause(() => {
  162. if (audioCallback && audioCallback.onPause && typeof(audioCallback.onPause) == 'function') {
  163. audioCallback.onPause();
  164. }
  165. })
  166. audio.onWaiting(() => {
  167. if (audioCallback && audioCallback.onWaiting && typeof(audioCallback.onWaiting) == 'function') {
  168. audioCallback.onWaiting();
  169. }
  170. })
  171. audio.onStop(() => {
  172. if (audioCallback && audioCallback.onStop && typeof(audioCallback.onStop) == 'function') {
  173. audioCallback.onStop();
  174. }
  175. })
  176. audio.onTimeUpdate(() => {
  177. if (audioCallback && audioCallback.onTimeUpdate && typeof(audioCallback.onTimeUpdate) == 'function') {
  178. audioCallback.onTimeUpdate();
  179. }
  180. })
  181. audio.onSeeking(() => {
  182. if (audioCallback && audioCallback.onSeeking && typeof(audioCallback.onSeeking) == 'function') {
  183. audioCallback.onSeeking();
  184. }
  185. })
  186. audio.onSeeked(() => {
  187. if (audioCallback && audioCallback.onSeeked && typeof(audioCallback.onSeeked) == 'function') {
  188. audioCallback.onSeeked();
  189. }
  190. })
  191. audio.onEnded(() => {
  192. console.log('音频播放结束');
  193. console.log('销毁音频实例');
  194. audio.destroy(); //销毁音频实例
  195. audio = null;
  196. // 清除播报列表对象数据
  197. if (audioCallback && audioCallback.onEnded && typeof(audioCallback.onEnded) == 'function') {
  198. audioCallback.onEnded();
  199. }
  200. if (lineUp !== false) {
  201. // 删除已经播放对象
  202. audioTeam.splice(0, 1);
  203. if (audioTeam.length > 0) {
  204. console.log('队列中');
  205. openVoiceFc(audioTeam[0]);
  206. } else {
  207. console.log('队列为零');
  208. audioStartSwitch = false;
  209. }
  210. }
  211. })
  212. audio.onError((e) => {
  213. console.log(audioCallback, '错误')
  214. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback
  215. .onError(e);
  216. console.log('音频播放错误: ' + JSON.stringify(e));
  217. console.log('销毁音频实例');
  218. audio.destroy(); //销毁音频实例
  219. audio = null;
  220. })
  221. audio.play();
  222. }