前言
在 Web 开发中,浏览器为我们提供了三种主要的音频播放方式,各自适用于不同的场景:
<audio>标签:只接受字符串形式的src,可播放普通 URL、Object URL或Data URI(Base64)等音频资源。 阿Audio对象:API 与<audio>标签完全一致,更适合在 JS 中动态创建与复用。AudioContext对象:用于处理二进制音频数据(如AudioBuffer),支持可视化、合成、特效等高级操作。
注意:无论使用哪种方式,浏览器的音频播放通常都需要用户交互(如点击按钮)来触发。
相关阅读:【Web 音频学习(二)】获取设备播放和麦克风权限
音频播放
<audio> 标签
<body>
<audio id="audio" src="https://audio-1304256198.cos.ap-guangzhou.myqcloud.com/%E4%BA%B2%E5%88%87%E5%A5%B3%E5%A3%B0.mp3 "></audio>
<button id="play">播放</button>
<script>
const playButton = document.getElementById('play')
const audioElement = document.getElementById('audio')
playButton.addEventListener('click', () => {
audioElement.play().then(() => {
console.log('播放成功')
})
})
</script>
</body>
Audio 对象
<body>
<button id="play">播放</button>
<script>
const playButton = document.getElementById('play')
playButton.addEventListener('click', () => {
const audioUrl = 'https://audio-1304256198.cos.ap-guangzhou.myqcloud.com/%E4%BA%B2%E5%88%87%E5%A5%B3%E5%A3%B0.mp3'
const audioElement = new Audio(audioUrl)
audioElement.play()
})
</script>
</body>
当然,<audio> 标签与 Audio 对象也能播放更复杂的类型,只需先转成 URL 即可:
Blob、File:通过URL.createObjectURL转换成 URL 后播放。Base64:先转为ArrayBuffer,再通过URL.createObjectURL生成 URL 播放。
相关阅读:前端也要学的“文件转换规则”知识
AudioContext 对象
AudioContext 通过连接各类 AudioNode 组成 音频路由图 来播放音频。支持的数据源几乎覆盖 Web 端所有类型:URL、Blob、File、ArrayBuffer、WebRTC 媒体流、Base64等……。
更关键的是,它能在二进制层面直接处理音频:频谱分析、动态压缩、音量调节、采样率转换、3D 空间化等,都可实时完成。
audioUrl
<body>
<button id="playBtn">播放</button>
<script>
(async () => {
const playButton = document.getElementById('playBtn')
const audioUrl = 'https://audio-1304256198.cos.ap-guangzhou.myqcloud.com/%E4%BA%B2%E5%88%87%E5%A5%B3%E5%A3%B0.mp3'
playButton.addEventListener('click', async () => {
const response = await fetch(audioUrl)
const arrayBuffer = await response.arrayBuffer()
const audioContext = new AudioContext()
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)
const sourceNode = audioContext.createBufferSource()
sourceNode.buffer = audioBuffer
sourceNode.connect(audioContext.destination)
sourceNode.start()
})
})()
</script>
</body>
File
<body>
<button id="play">播放</button>
<script>
const playButton = document.getElementById('play')
async function generateFile() {
const audioUrl = 'https://audio-1304256198.cos.ap-guangzhou.myqcloud.com/%E4%BA%B2%E5%88%87%E5%A5%B3%E5%A3%B0.mp3'
const response = await fetch(audioUrl)
const arrayBuffer = await response.arrayBuffer()
return new File([arrayBuffer], { type: 'audio/mpeg' })
}
playButton.addEventListener('click', async () => {
const file = await generateFile()
const audioContext = new AudioContext()
const audioBuffer = await audioContext.decodeAudioData(await file.arrayBuffer())
const sourceNode = audioContext.createBufferSource()
sourceNode.buffer = audioBuffer
sourceNode.connect(audioContext.destination)
sourceNode.start()
})
</script>
</body>
Base64
<body>
<button id="playBtn">播放</button>
<script>
(async () => {
const playButton = document.getElementById('playBtn')
async function generateBase64String() {
const audioUrl = 'https://audio-1304256198.cos.ap-guangzhou.myqcloud.com/%E4%BA%B2%E5%88%87%E5%A5%B3%E5%A3%B0.mp3'
const response = await fetch(audioUrl)
const arrayBuffer = await response.arrayBuffer()
const uint8Array = new Uint8Array(arrayBuffer);
let binaryString = '';
for (let i = 0; i < uint8Array.length; i++) {
binaryString += String.fromCharCode(uint8Array[i]);
}
const base64String = `data:audio/mpeg;base64,${btoa(binaryString)}`;
return base64String
}
playButton.addEventListener('click', async () => {
let base64String = await generateBase64String()
if(base64String.includes('data:audio/mpeg;base64,')){
base64String = base64String.replace('data:audio/mpeg;base64,', '')
}
const binaryString = atob(base64String);
const uint8Array = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
uint8Array[i] = binaryString.charCodeAt(i);
}
const audioContext = new AudioContext()
const audioBuffer = await audioContext.decodeAudioData(uint8Array.buffer)
const sourceNode = audioContext.createBufferSource()
sourceNode.buffer = audioBuffer
sourceNode.connect(audioContext.destination)
sourceNode.start()
})
})()
</script>
</body>
在开发 TTS 流式播放功能时,后端可能会返回以下几种音频数据格式:Blob、audioUrl、Base64。
这些格式用于实现音频的逐段接收与即时播放。当前阶段无需深入细节,了解其用途即可,具体实现时可作为参考。