useAudio.js 3.2 KB

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