useAudio.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import {
  2. reactive,
  3. ref
  4. } from 'vue';
  5. import {
  6. onHide,
  7. onUnload
  8. } from "@dcloudio/uni-app"
  9. import {
  10. nextTick
  11. } from 'vue';
  12. let audioContext = null;
  13. let code = null; // 身份标识
  14. audioContext = uni.createInnerAudioContext(); // 单例模式[3](@ref)
  15. audioContext.onEnded(() => {
  16. // console.log('触发播放结束')
  17. // 播放结束
  18. uni.$emit('danci-audio-ended', code)
  19. audioContext?.stop();
  20. })
  21. audioContext.onPlay(() => {
  22. // 播放
  23. // console.log('播放事件:', code)
  24. uni.$emit('danci-audio-play', code);
  25. });
  26. audioContext.onError((err) => {
  27. // 播放
  28. uni.$emit('danci-audio-ended', code)
  29. audioContext?.stop();
  30. // uni.$emit('danci-audio-play', code);
  31. uni.showToast({
  32. title: '音频播放异常,已重置'
  33. })
  34. });
  35. function createAudioNew() {
  36. audioContext = uni.createInnerAudioContext(); // 单例模式[3](@ref)
  37. audioContext.onEnded(() => {
  38. // console.log('触发播放结束')
  39. // 播放结束
  40. uni.$emit('danci-audio-ended', code)
  41. audioContext?.stop();
  42. })
  43. audioContext.onPlay(() => {
  44. // 播放
  45. // console.log('播放事件:', code)
  46. uni.$emit('danci-audio-play', code);
  47. });
  48. audioContext.onError((err) => {
  49. // 播放
  50. uni.$emit('danci-audio-ended', code)
  51. audioContext?.stop();
  52. // uni.$emit('danci-audio-play', code);
  53. uni.showToast({
  54. title: '音频播放异常,已重置'
  55. })
  56. });
  57. }
  58. export class audioPlayer {
  59. // 播放音频
  60. play(path, code1) {
  61. // console.log('播放文件地址', path)
  62. code = code1;
  63. if (audioContext.src === path && !audioContext.paused) return;
  64. audioContext.stop();
  65. audioContext.destroy();
  66. audioContext = null;
  67. nextTick(() => {
  68. createAudioNew();
  69. audioContext.src = path;
  70. audioContext.play();
  71. })
  72. }
  73. // 暂停播放
  74. pause() {
  75. audioContext?.pause();
  76. }
  77. // 停止播放(释放资源)
  78. stop() {
  79. audioContext?.stop();
  80. audioContext = null;
  81. }
  82. }
  83. export function useAudioCache() {
  84. const cacheMapKey = 'audio_cache_map'; // Storage 中缓存映射的键名
  85. // 下载并缓存音频
  86. async function cacheAudio(url) {
  87. try {
  88. let cacheMap = uni.getStorageSync(cacheMapKey) || {};
  89. if (cacheMap[url]) {
  90. // console.log('已缓存音频地址', cacheMap[url])
  91. return cacheMap[url]; // 返回有效缓存路径
  92. }
  93. // 3. 下载音频文件
  94. const {
  95. tempFilePath
  96. } = await new Promise((resolve, reject) => {
  97. uni.downloadFile({
  98. url,
  99. success: resolve,
  100. fail: reject
  101. });
  102. });
  103. if (!tempFilePath.includes('.mp3')) {
  104. // console.log(`文件下载失败${url}`)
  105. return null;
  106. }
  107. // 4. 持久化存储到本地
  108. const savedFilePath = tempFilePath; // 跨平台安全路径[2](@ref)
  109. await uni.saveFile({
  110. tempFilePath,
  111. toSavedFilePath: savedFilePath
  112. });
  113. cacheMap[url] = savedFilePath;
  114. uni.setStorageSync(cacheMapKey, cacheMap);
  115. // console.log('当前音频地址', savedFilePath)
  116. return savedFilePath;
  117. } catch (err) {
  118. // console.error('音频缓存失败:', err);
  119. return null;
  120. }
  121. }
  122. function clearAudioCache() {
  123. // uni.setStorageSync(cacheMapKey, {})
  124. const cacheMap = uni.getStorageSync(cacheMapKey) || {};
  125. Object.entries(cacheMap).forEach(([key, path]) => {
  126. uni.removeSavedFile({
  127. filePath: path
  128. }); // 删除文件
  129. delete cacheMap[key];
  130. })
  131. // console.log('已清理完成', cacheMap)
  132. uni.setStorageSync(cacheMapKey, cacheMap)
  133. }
  134. return {
  135. cacheAudio,
  136. clearAudioCache
  137. }
  138. }