useAudio.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. }
  81. }
  82. export function useAudioCache() {
  83. const cacheMapKey = 'audio_cache_map'; // Storage 中缓存映射的键名
  84. // 下载并缓存音频
  85. async function cacheAudio(url) {
  86. try {
  87. let cacheMap = uni.getStorageSync(cacheMapKey) || {};
  88. if (cacheMap[url]) {
  89. // console.log('已缓存音频地址', cacheMap[url])
  90. return cacheMap[url]; // 返回有效缓存路径
  91. }
  92. // 3. 下载音频文件
  93. const {
  94. tempFilePath
  95. } = await new Promise((resolve, reject) => {
  96. uni.downloadFile({
  97. url,
  98. success: resolve,
  99. fail: reject
  100. });
  101. });
  102. if (!tempFilePath.includes('.mp3')) {
  103. // console.log(`文件下载失败${url}`)
  104. return null;
  105. }
  106. // 4. 持久化存储到本地
  107. const savedFilePath = tempFilePath; // 跨平台安全路径[2](@ref)
  108. await uni.saveFile({
  109. tempFilePath,
  110. toSavedFilePath: savedFilePath
  111. });
  112. cacheMap[url] = savedFilePath;
  113. uni.setStorageSync(cacheMapKey, cacheMap);
  114. // console.log('当前音频地址', savedFilePath)
  115. return savedFilePath;
  116. } catch (err) {
  117. // console.error('音频缓存失败:', err);
  118. return null;
  119. }
  120. }
  121. function clearAudioCache() {
  122. // uni.setStorageSync(cacheMapKey, {})
  123. const cacheMap = uni.getStorageSync(cacheMapKey) || {};
  124. Object.entries(cacheMap).forEach(([key, path]) => {
  125. uni.removeSavedFile({
  126. filePath: path
  127. }); // 删除文件
  128. delete cacheMap[key];
  129. })
  130. // console.log('已清理完成', cacheMap)
  131. uni.setStorageSync(cacheMapKey, cacheMap)
  132. }
  133. return {
  134. cacheAudio,
  135. clearAudioCache
  136. }
  137. }