123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // utils/audioManager.js
- export default {
- player: null,
-
- initPlayer() {
- if (!this.player) {
- this.player = uni.createInnerAudioContext()
- this.player.obeyMuteSwitch = false // iOS静音模式设置
- }
- return this.player
- },
- // 从单词数据中提取所有音频信息
- extractAudioInfo(wordData) {
- const audioInfo = {
- main: null,
- syllables: [],
- frequencies: []
- }
-
- // 主音频
- if (wordData.yinpin) {
- audioInfo.main = {
- id: `word_${wordData.id}_main`,
- url: wordData.yinpin,
- type: 'main',
- text: wordData.name
- }
- }
-
- // 音节音频
- if (wordData.yinjie && Array.isArray(wordData.yinjie)) {
- audioInfo.syllables = wordData.yinjie.map((item, index) => ({
- id: `word_${wordData.id}_syllable_${index}`,
- url: item.yinpin,
- type: 'syllable',
- text: item.cigen,
- index
- })).filter(item => item.url)
- }
-
- // 频度音频
- if (wordData.pindu && Array.isArray(wordData.pindu)) {
- audioInfo.frequencies = wordData.pindu.map((item, index) => ({
- id: `word_${wordData.id}_frequency_${index}`,
- url: item.yinpin,
- type: 'frequency',
- text: item.cigen,
- index
- })).filter(item => item.url)
- }
-
- return audioInfo
- },
- // 缓存单词的所有音频
- async cacheWordAudios(wordData) {
- try {
- // 1. 提取音频信息
- const { main, syllables, frequencies } = this.extractAudioInfo(wordData)
-
- // 2. 准备所有需要缓存的音频
- const allAudios = []
- if (main) allAudios.push(main)
- allAudios.push(...syllables)
- allAudios.push(...frequencies)
-
- // 3. 缓存所有音频
- await this.cacheAllAudios(allAudios)
-
- // 4. 保存音频信息到统一存储
- this.saveAudioInfoToStorage(wordData.id, {
- main,
- syllables,
- frequencies
- })
-
- return true
- } catch (error) {
- console.error('音频缓存失败:', error)
- return false
- }
- },
- // 保存音频信息到storage(结构化存储)
- saveAudioInfoToStorage(wordId, audioInfo) {
- const cacheKey = `word_audio_${wordId}`
- const cachedData = {
- timestamp: Date.now(),
- ...audioInfo
- }
- uni.setStorageSync(cacheKey, cachedData)
- },
- // 从storage获取音频信息
- getAudioInfoFromStorage(wordId) {
- const cacheKey = `word_audio_${wordId}`
- return uni.getStorageSync(cacheKey) || null
- },
- // 缓存所有音频
- async cacheAllAudios(audioList) {
- const cachePromises = audioList.map(audio => {
- return this.cacheSingleAudio(audio.id, audio.url).catch(e => {
- console.warn(`音频 ${audio.id} 预加载失败:`, e)
- return null
- })
- })
-
- await Promise.all(cachePromises)
- },
- // 缓存单个音频
- async cacheSingleAudio(id, url) {
- return new Promise((resolve, reject) => {
- uni.downloadFile({
- url,
- success: (res) => {
- if (res.statusCode === 200) {
- // 存储音频文件路径
- uni.setStorageSync(`audio_file_${id}`, res.tempFilePath)
- resolve()
- } else {
- reject(new Error(`下载失败,状态码: ${res.statusCode}`))
- }
- },
- fail: reject
- })
- })
- },
- // 播放音频
- playAudio(audioInfo) {
- if (!audioInfo || !audioInfo.url) return
-
- const player = this.initPlayer()
- player.stop()
-
- // 尝试从缓存获取
- const cachedPath = uni.getStorageSync(`audio_file_${audioInfo.id}`)
-
- if (cachedPath) {
- // 有缓存,直接播放
- player.src = cachedPath
- player.play()
- } else {
- // 无缓存,从网络播放并后台缓存
- console.warn(`音频 ${audioInfo.id} 未缓存,从网络加载`)
- player.src = audioInfo.url
- player.play()
-
- // 后台缓存
- this.cacheSingleAudio(audioInfo.id, audioInfo.url).catch(console.error)
- }
-
- player.onError((err) => {
- console.error('播放失败:', err)
- uni.showToast({ title: '播放失败', icon: 'none' })
- })
-
- return player
- },
- // 清理指定单词的缓存
- clearWordCache(wordId) {
- // 1. 清理音频信息
- uni.removeStorageSync(`word_audio_${wordId}`)
-
- // 2. 清理所有相关音频文件
- const prefix = `word_${wordId}_`
- const keys = uni.getStorageInfoSync().keys
-
- keys.filter(key => key.startsWith('audio_file_') && key.includes(prefix))
- .forEach(key => uni.removeStorageSync(key))
- },
- // 清理所有缓存
- clearAllCache() {
- // 1. 清理所有音频信息
- const keys = uni.getStorageInfoSync().keys
- keys.filter(key => key.startsWith('word_audio_'))
- .forEach(key => uni.removeStorageSync(key))
-
- // 2. 清理所有音频文件
- keys.filter(key => key.startsWith('audio_file_'))
- .forEach(key => uni.removeStorageSync(key))
- }
- }
|