baidu.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. const audioTeam = [];
  2. let audioStartSwitch = false;
  3. const getAudioUrl = 'https://tsn.baidu.com/text2audio';
  4. /**
  5. * 浏览器调用语音合成接口
  6. * 获取token接口: https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=uFYiXWMCiYvx68V4EVyCGeL8j4GAzXD5&client_secret=897Mm2qCj7bC1eHYVDxaWrO38FscTOHD
  7. */
  8. function getBDVoicToken() {
  9. return new Promise((rs, rj) => {
  10. console.log('准备访问接口获取语音token')
  11. uni.request({ // 强烈建议此接口由后端访问并且维护token有效期,否则前端每次访问都会刷新token
  12. //此url为专门插件测试预览用的key和secret key, 请替换为自己申请的key
  13. url: 'https://openapi.baidu.com/oauth/2.0/token',
  14. method: 'POST', //建议使用post访问
  15. // data: 'grant_type=client_credentials&client_id=nm6Os9qqOacgxXjKv8PIp45H&client_secret=BXHhGIpNU7Wi3GDYUt0AGY5cWbWklrov',
  16. data: 'grant_type=client_credentials&client_id=jtwoB9xzRnv3qltcfqL0pk1t&client_secret=A16UKHBKVeAh68kuGGSPqnemCVyPDmgb',
  17. header: {
  18. "content-type": "application/x-www-form-urlencoded"
  19. },
  20. success: (res) => {
  21. console.log('访问成功');
  22. rs(res);
  23. },
  24. fail: (err) => {
  25. console.log('访问失败');
  26. rj(err);
  27. }
  28. })
  29. })
  30. }
  31. export default function openVoice(objs) { // 传入需转为语音的文本内容
  32. let lineUp = false;
  33. let returnAudio = false;
  34. if (typeof(objs) !== 'string') {
  35. if (objs && objs.lineUp === true) {
  36. lineUp = true;
  37. }
  38. if (objs && objs.returnAudio === true) {
  39. returnAudio = true;
  40. }
  41. }
  42. if (returnAudio) {
  43. return new Promise((resolve, reject) => {
  44. openVoiceFc(objs, returnAudio).then(res => {
  45. resolve(res);
  46. }).catch(err => {
  47. reject(err)
  48. });
  49. })
  50. }
  51. if (!audioStartSwitch || lineUp) {
  52. audioStartSwitch = true;
  53. openVoiceFc(objs);
  54. } else {
  55. audioTeam.push(objs);
  56. }
  57. }
  58. function openVoiceFc(objs, returnAudio) {
  59. console.log('准备获取语音tok');
  60. if (returnAudio) {
  61. return new Promise((resolve, reject) => {
  62. getBDVoicToken().then(res => {
  63. console.log('获取语音tok接口成功');
  64. if (res.data && res.data.access_token) {
  65. console.log('token: ' + res.data.access_token);
  66. resolve(tts(objs, res.data.access_token, returnAudio));
  67. } else {
  68. console.log('获取语音tok接口为空');
  69. reject('获取语音tok接口为空');
  70. }
  71. }).catch(err => {
  72. console.log('获取语音tok接口失败');
  73. reject(err || '获取语音tok接口失败');
  74. })
  75. })
  76. } else {
  77. getBDVoicToken().then(res => {
  78. console.log('获取语音tok接口成功');
  79. if (res.data && res.data.access_token) {
  80. console.log('token: ' + res.data.access_token);
  81. tts(objs, res.data.access_token);
  82. } else {
  83. console.log('获取语音tok接口为空');
  84. }
  85. }).catch(err => {
  86. console.log('获取语音tok接口失败');
  87. })
  88. }
  89. }
  90. function tts(objs, tok, returnAudio) {
  91. if (typeof(objs) == 'string')
  92. objs = {
  93. voiceSet: {
  94. tex: objs
  95. }
  96. };
  97. const data = {
  98. tok,
  99. cuid: tok,
  100. ctp: 1,
  101. lan: 'zh',
  102. ...objs.voiceSet
  103. }
  104. if (returnAudio)
  105. return btts(data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
  106. btts(data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
  107. }
  108. function setAudioSet(options, audio) {
  109. if (options) {
  110. audio.volume = options.volume || 1;
  111. audio.startTime = options.startTime || 0;
  112. audio.loop = options.loop || false;
  113. audio.obeyMuteSwitch = options.obeyMuteSwitch && typeof(options.obeyMuteSwitch) == 'boolean' ? options.obeyMuteSwitch :
  114. true; //支持微信小程序、百度小程序、头条小程序
  115. }
  116. }
  117. function btts(param, options, audioCallback, lineUp, returnAudio) {
  118. let audio = uni.createInnerAudioContext();
  119. setAudioSet(options, audio);
  120. // 序列化参数列表
  121. let fd = [];
  122. for (let k in param) {
  123. fd.push(k + '=' + encodeURIComponent(encodeURIComponent(param[k])));
  124. }
  125. audio.src = `${getAudioUrl}?${fd.join('&')}`;
  126. if (returnAudio) {
  127. audio.onEnded(() => {
  128. console.log('音频播放结束');
  129. console.log('销毁音频实例');
  130. audio.destroy(); //销毁音频实例
  131. audio = null;
  132. })
  133. audio.onError((e) => {
  134. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
  135. console.log('音频播放错误: ' + JSON.stringify(e));
  136. console.log('销毁音频实例');
  137. audio.destroy(); //销毁音频实例
  138. audio = null;
  139. })
  140. return audio;
  141. }
  142. audio.onPlay(() => {
  143. console.log('音频播放开始');
  144. if (audioCallback && audioCallback.onPlay && typeof(audioCallback.onPlay) == 'function') audioCallback.onPlay();
  145. })
  146. audio.onPause(() => {
  147. if (audioCallback && audioCallback.onPause && typeof(audioCallback.onPause) == 'function') audioCallback.onPause();
  148. })
  149. audio.onWaiting(() => {
  150. if (audioCallback && audioCallback.onWaiting && typeof(audioCallback.onWaiting) == 'function') audioCallback.onWaiting();
  151. })
  152. audio.onStop(() => {
  153. if (audioCallback && audioCallback.onStop && typeof(audioCallback.onStop) == 'function') audioCallback.onStop();
  154. })
  155. audio.onTimeUpdate(() => {
  156. if (audioCallback && audioCallback.onTimeUpdate && typeof(audioCallback.onTimeUpdate) == 'function') audioCallback.onTimeUpdate();
  157. })
  158. audio.onSeeking(() => {
  159. if (audioCallback && audioCallback.onSeeking && typeof(audioCallback.onSeeking) == 'function') audioCallback.onSeeking();
  160. })
  161. audio.onSeeked(() => {
  162. if (audioCallback && audioCallback.onSeeked && typeof(audioCallback.onSeeked) == 'function') audioCallback.onSeeked();
  163. })
  164. audio.onEnded(() => {
  165. console.log('音频播放结束');
  166. console.log('销毁音频实例');
  167. audio.destroy(); //销毁音频实例
  168. audio = null;
  169. if (audioCallback && audioCallback.onEnded && typeof(audioCallback.onEnded) == 'function') audioCallback.onEnded();
  170. if (lineUp !== false) {
  171. if (audioTeam.length > 0) {
  172. console.log('队列中');
  173. openVoiceFc(audioTeam[0]);
  174. audioTeam.splice(0, 1);
  175. } else {
  176. console.log('队列为零');
  177. audioStartSwitch = false;
  178. }
  179. }
  180. })
  181. audio.onError((e) => {
  182. if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
  183. console.log('音频播放错误: ' + JSON.stringify(e));
  184. console.log('销毁音频实例');
  185. audio.destroy(); //销毁音频实例
  186. audio = null;
  187. })
  188. audio.play();
  189. }