QS-baiduyy.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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接口成功');
  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.obeyMuteSwitch :
  115. true; //支持微信小程序、百度小程序、头条小程序
  116. // #endif
  117. }
  118. }
  119. function btts(param, options, audioCallback, lineUp, returnAudio) {
  120. let audio = uni.createInnerAudioContext();
  121. setAudioSet(options, audio);
  122. // 序列化参数列表
  123. let fd = [];
  124. for (let k in param) {
  125. fd.push(k + '=' + encodeURIComponent(encodeURIComponent(param[k])));
  126. }
  127. audio.src = `${getAudioUrl}?${fd.join('&')}`;
  128. if (returnAudio) {
  129. audio.onEnded(() => {
  130. console.log('音频播放结束');
  131. console.log('销毁音频实例');
  132. audio.destroy(); //销毁音频实例
  133. audio = null;
  134. })
  135. audio.onError((e) => {
  136. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
  137. console.log('音频播放错误: ' + JSON.stringify(e));
  138. console.log('销毁音频实例');
  139. audio.destroy(); //销毁音频实例
  140. audio = null;
  141. })
  142. return audio;
  143. }
  144. console.log(audio);
  145. audio.onPlay(() => {
  146. console.log('音频播放开始');
  147. if (audioCallback && audioCallback.onPlay && typeof(audioCallback.onPlay) == 'function') {
  148. audioCallback.onPlay();
  149. }
  150. })
  151. audio.onPause(() => {
  152. if (audioCallback && audioCallback.onPause && typeof(audioCallback.onPause) == 'function') {
  153. audioCallback.onPause();
  154. }
  155. })
  156. audio.onWaiting(() => {
  157. if (audioCallback && audioCallback.onWaiting && typeof(audioCallback.onWaiting) == 'function') {
  158. audioCallback.onWaiting();
  159. }
  160. })
  161. audio.onStop(() => {
  162. if (audioCallback && audioCallback.onStop && typeof(audioCallback.onStop) == 'function') {
  163. audioCallback.onStop();
  164. }
  165. })
  166. audio.onTimeUpdate(() => {
  167. if (audioCallback && audioCallback.onTimeUpdate && typeof(audioCallback.onTimeUpdate) == 'function') {
  168. audioCallback.onTimeUpdate();
  169. }
  170. })
  171. audio.onSeeking(() => {
  172. if (audioCallback && audioCallback.onSeeking && typeof(audioCallback.onSeeking) == 'function') {
  173. audioCallback.onSeeking();
  174. }
  175. })
  176. audio.onSeeked(() => {
  177. if (audioCallback && audioCallback.onSeeked && typeof(audioCallback.onSeeked) == 'function') {
  178. audioCallback.onSeeked();
  179. }
  180. })
  181. audio.onEnded(() => {
  182. console.log('音频播放结束');
  183. console.log('销毁音频实例');
  184. audio.destroy(); //销毁音频实例
  185. audio = null;
  186. // 清除播报列表对象数据
  187. if (audioCallback && audioCallback.onEnded && typeof(audioCallback.onEnded) == 'function') {
  188. audioCallback.onEnded();
  189. }
  190. if (lineUp !== false) {
  191. // 删除已经播放对象
  192. audioTeam.splice(0, 1);
  193. if (audioTeam.length > 0) {
  194. console.log('队列中');
  195. openVoiceFc(audioTeam[0]);
  196. } else {
  197. console.log('队列为零');
  198. audioStartSwitch = false;
  199. }
  200. }
  201. })
  202. audio.onError((e) => {
  203. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
  204. console.log('音频播放错误: ' + JSON.stringify(e));
  205. console.log('销毁音频实例');
  206. audio.destroy(); //销毁音频实例
  207. audio = null;
  208. })
  209. audio.play();
  210. }