音频系统分析.md
8.47 KB
音频系统分析
最后更新: 2026-02-09 相关文件:
-
src/components/audioBackground.vue- 背景音频(单模式) -
src/components/audioBackground1.vue- 背景音频(备用) -
src/components/audioList.vue- 音频列表(播放列表模式) -
src/api/map.js- 音频 API (mapAudioAPI)
系统架构
双模式设计
音频系统支持两种播放模式:
-
单模式 (Single Mode)
- 组件:
audioBackground.vue,audioBackground1.vue - 用途: 单个音频的背景播放
- 特点: 简单、轻量
- 组件:
-
播放列表模式 (Playlist Mode)
- 组件:
audioList.vue - 用途: 多个音频的顺序播放
- 特点: 支持播放列表控制
- 组件:
状态管理
Pinia Store (src/store/index.js):
// 单模式状态
audio_entity: null, // 当前音频实体
audio_status: false, // 播放状态
// 播放列表模式状态
audio_list_entity: [], // 播放列表
audio_list_status: false, // 播放状态
核心功能
1. 音频加载
API 端点: /srv/?a=map_audio
// src/api/map.js
export const mapAudioAPI = (params) => fn(fetch.get(Api.MAP_AUDIO, params));
请求参数:
-
id: 位置/景点 ID -
type: 音频类型(可选)
响应数据:
{
code: 1,
data: {
audioUrl: '/audio/guide.mp3',
title: '景点介绍',
duration: 120,
// 其他音频信息
},
msg: ''
}
2. 单模式播放
组件: audioBackground.vue
功能:
- ✅ 播放/暂停控制
- ✅ 进度条显示
- ✅ 音量控制
- ✅ 自动播放(可选)
- ✅ 循环播放(可选)
使用示例:
<template>
<audioBackground
:audio-url="currentAudio"
:autoplay="true"
@play="handlePlay"
@pause="handlePause"
@ended="handleEnded"
/>
</template>
<script setup>
import audioBackground from '@components/audioBackground.vue';
import { ref } from 'vue';
const currentAudio = ref('/audio/guide.mp3');
const handlePlay = () => {
console.log('开始播放');
};
const handlePause = () => {
console.log('暂停播放');
};
const handleEnded = () => {
console.log('播放结束');
};
</script>
3. 播放列表模式
组件: audioList.vue
功能:
- ✅ 播放列表管理
- ✅ 上一首/下一首
- ✅ 播放进度
- ✅ 当前播放高亮
- ✅ 自动播放下一首
- ✅ 列表循环
使用示例:
<template>
<audioList
v-model:playlist="audioPlaylist"
:current-index="currentIndex"
@play="handlePlay"
@pause="handlePause"
@next="handleNext"
@prev="handlePrev"
/>
</template>
<script setup>
import audioList from '@components/audioList.vue';
import { ref } from 'vue';
const audioPlaylist = ref([
{
id: 1,
title: '景点介绍 1',
url: '/audio/guide1.mp3',
duration: 120
},
{
id: 2,
title: '景点介绍 2',
url: '/audio/guide2.mp3',
duration: 90
}
]);
const currentIndex = ref(0);
const handlePlay = (index) => {
console.log('播放索引:', index);
};
const handleNext = () => {
if (currentIndex.value < audioPlaylist.value.length - 1) {
currentIndex.value++;
}
};
const handlePrev = () => {
if (currentIndex.value > 0) {
currentIndex.value--;
}
};
</script>
4. 音频状态同步
Pinia Store:
import { defineStore } from 'pinia';
export const useAudioStore = defineStore('audio', {
state: () => ({
// 单模式
audio_entity: null,
audio_status: false,
// 播放列表模式
audio_list_entity: [],
audio_list_status: false,
audio_list_index: 0,
}),
actions: {
// 设置单模式音频
setAudio(entity) {
this.audio_entity = entity;
},
// 播放/暂停单模式
toggleAudio() {
this.audio_status = !this.audio_status;
},
// 设置播放列表
setPlaylist(list) {
this.audio_list_entity = list;
},
// 播放/暂停播放列表
togglePlaylist() {
this.audio_list_status = !this.audio_list_status;
},
// 下一首
nextTrack() {
if (this.audio_list_index < this.audio_list_entity.length - 1) {
this.audio_list_index++;
}
},
// 上一首
prevTrack() {
if (this.audio_list_index > 0) {
this.audio_list_index--;
}
},
},
});
音频格式
支持的格式
- ✅ MP3(推荐)
- ✅ WAV
- ✅ OGG
- ✅ AAC
- ✅ M4A
推荐配置
编码格式: MP3 比特率: 128 kbps 采样率: 44.1 kHz 声道: 立体声
文件大小建议
| 音频时长 | 推荐大小 |
|---|---|
| < 1 分钟 | < 1 MB |
| 1-3 分钟 | 1-3 MB |
| 3-5 分钟 | 3-5 MB |
| > 5 分钟 | 建议分割 |
性能优化
1. 懒加载
// 仅在需要时加载音频
const loadAudio = async (url) => {
const audio = new Audio();
audio.src = url;
await audio.load(); // 预加载
return audio;
};
2. 缓存策略
// 缓存已加载的音频
const audioCache = new Map();
export const getCachedAudio = (url) => {
if (audioCache.has(url)) {
return audioCache.get(url);
}
const audio = new Audio(url);
audioCache.set(url, audio);
return audio;
};
3. 预加载
<audio :src="audioUrl" preload="auto" />
preload 选项:
-
none: 不预加载 -
metadata: 仅预加载元数据(时长、尺寸等) -
auto: 完全预加载
4. 资源释放
// 组件卸载时释放音频资源
onUnmounted(() => {
if (audio.value) {
audio.value.pause();
audio.value.src = '';
audio.value.load();
}
});
已知问题
1. iOS 自动播放限制
问题: iOS 不允许自动播放音频
解决方案:
// 用户交互后播放
const playAudio = () => {
document.addEventListener('touchstart', function onTouchStart() {
// 播放音频
audio.play();
// 移除监听器
document.removeEventListener('touchstart', onTouchStart);
}, { once: true });
};
2. 多个音频冲突
问题: 同时播放多个音频
解决方案:
// 播放新音频前停止其他音频
const playAudio = (newAudio) => {
if (currentAudio.value) {
currentAudio.value.pause();
}
currentAudio.value = newAudio;
currentAudio.value.play();
};
3. 音频加载失败
问题: 网络错误或文件不存在
解决方案:
audio.addEventListener('error', (e) => {
console.error('音频加载失败:', e);
// 显示错误提示
showToast('音频加载失败,请检查网络');
// 尝试重新加载
setTimeout(() => {
audio.load();
}, 1000);
});
最佳实践
1. 音频路径管理
// ✅ 推荐:使用别名
const audioUrl = ref('@images/audio/guide.mp3');
// ❌ 不推荐:使用相对路径
const audioUrl = ref('../../images/audio/guide.mp3');
2. 音频加载状态
<template>
<div v-if="loading" class="loading">加载中...</div>
<div v-else-if="error" class="error">加载失败</div>
<audio v-else :src="audioUrl" @loadeddata="onLoaded" />
</template>
<script setup>
import { ref } from 'vue';
const loading = ref(true);
const error = ref(false);
const onLoaded = () => {
loading.value = false;
};
</script>
3. 音频控制
// ✅ 推荐:使用 Vue 组件
<audioBackground v-model:playing="isPlaying" :audio-url="audioUrl" />
// ❌ 不推荐:直接操作 DOM
document.querySelector('audio').play();
调试技巧
1. 查看音频状态
// 在控制台查看音频状态
console.log('音频状态:', {
src: audio.src,
duration: audio.duration,
currentTime: audio.currentTime,
paused: audio.paused,
ended: audio.ended,
});
2. 监听音频事件
audio.addEventListener('loadstart', () => console.log('开始加载'));
audio.addEventListener('canplay', () => console.log('可以播放'));
audio.addEventListener('play', () => console.log('播放'));
audio.addEventListener('pause', () => console.log('暂停'));
audio.addEventListener('ended', () => console.log('结束'));
audio.addEventListener('error', (e) => console.error('错误:', e));
3. 模拟音频播放
// 在控制台手动播放音频
document.querySelector('audio').play();