bricks/docs/cn/continueaudio.md
2025-10-12 17:59:59 +08:00

314 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `ContinueAudioPlayer` 技术文档
> 一个基于 Web Audio API 的连续音频播放器组件,支持流式播放、音量控制、暂停/恢复、静音切换和事件回调。
---
## 概述
`bricks.ContinueAudioPlayer` 是一个继承自 `bricks.VBox` 的音频播放类,专为在浏览器中实现无缝连续音频播放而设计。它使用 Web Audio API 解码并播放 Base64 编码或 ArrayBuffer 格式的音频数据,并支持动态控制播放状态与音量。
该组件适用于需要精确时间控制的语音合成TTS、实时音频流处理等场景。
---
## 类定义
```js
class ContinueAudioPlayer extends bricks.VBox
```
注册名称:`'ContinueAudioPlayer'`
注册方式:
```js
bricks.Factory.register('ContinueAudioPlayer', bricks.ContinueAudioPlayer);
```
---
## 构造函数
### `constructor(options)`
初始化播放器实例。
#### 参数
| 参数名 | 类型 | 描述 |
|----------|--------|------|
| `options.ws_url` | `string` | WebSocket 地址(当前未实际使用,保留字段) |
| `options.onStart` | `Function` | 音频开始播放时触发的回调函数 |
| `options.onEnd` | `Function` | 当前音频片段结束播放时触发 |
| `options.onPause` | `Function` | 暂停播放时触发 |
| `options.onResume` | `Function` | 恢复播放时触发 |
| `options.onVolumeChange` | `Function` | 音量变化时触发,参数为新音量值 |
#### 示例
```js
const player = new bricks.ContinueAudioPlayer({
ws_url: 'wss://example.com/audio',
onStart: () => console.log('Audio started'),
onEnd: () => console.log('Audio ended'),
onPause: () => console.log('Paused'),
onResume: () => console.log('Resumed'),
onVolumeChange: (vol) => console.log(`Volume: ${vol}`)
});
```
---
## 属性
| 属性 | 类型 | 描述 |
|------|------|------|
| `audioContext` | `AudioContext` | Web Audio 上下文对象 |
| `gainNode` | `GainNode` | 控制音量的增益节点 |
| `nextStartTime` | `Number` | 下一段音频应开始播放的时间(以秒为单位) |
| `started` | `Boolean` | 是否已成功初始化音频上下文 |
| `muted` | `Boolean` | 当前是否处于静音状态 |
| `volume` | `Number` | 当前音量范围0.0 - 1.0 |
| `ws_url` | `String` | 存储传入的 WebSocket URL目前仅作存储用途 |
| `options` | `Object` | 用户传入的配置选项 |
---
## 方法
### `initAudioContext()`
创建并初始化 `AudioContext``GainNode`,准备音频播放环境。
- 若上下文已被关闭,则可通过调用此方法重新激活。
- 自动设置初始增益值为 `this.volume`
- 更新 `nextStartTime` 为当前时间,确保后续音频从正确时间点开始。
> ⚠️ 注意:由于浏览器策略限制,**必须在用户交互(如点击)后才能创建或恢复 AudioContext**。
---
### `base64ToArrayBuffer(base64) → ArrayBuffer`
将 Base64 字符串转换为 `ArrayBuffer`,用于 Web Audio API 解码。
#### 参数
| 参数名 | 类型 | 描述 |
|-------|------|------|
| `base64` | `string` | Base64 编码的二进制音频数据 |
#### 返回值
- `{ArrayBuffer}`:可用于 `decodeAudioData` 的原始二进制缓冲区。
#### 示例
```js
const buffer = player.base64ToArrayBuffer("UklGRiQAAABXQVZFZm...");
```
---
### `handleAudioTrack(arrayBuffer)`
解码并播放一段音频数据。
#### 参数
| 参数名 | 类型 | 描述 |
|-------|------|------|
| `arrayBuffer` | `ArrayBuffer` | 包含编码音频数据的二进制缓冲区(如 WAV、MP3 等) |
#### 行为说明
1. 使用 `audioContext.decodeAudioData()` 异步解码音频。
2. 创建 `AudioBufferSourceNode` 并连接到增益节点。
3. 在合适的时间点开始播放(避免重叠):
- 开始时间为 `Math.max(currentTime, this.nextStartTime)`
4. 更新 `nextStartTime` 为本次播放结束时间,保证下段音频接续播放。
5. 触发 `onStart` 回调。
6. 播放结束后触发 `onEnd` 回调。
#### 错误处理
若解码失败,会在控制台输出错误日志:
```text
Error decoding audio data: [Error]
```
---
### `pauseAudio()`
暂停所有正在播放的音频。
- 调用 `audioContext.suspend()` 挂起上下文。
- 成功后触发 `onPause` 回调。
> 📝 仅当 `audioContext.state === 'running'` 时有效。
---
### `resumeAudio()`
恢复被暂停的音频播放。
- 调用 `audioContext.resume()` 恢复上下文运行。
- 成功后触发 `onResume` 回调。
> 📝 仅当 `audioContext.state === 'suspended'` 时有效。
---
### `restart()`
停止当前播放,关闭音频上下文,并重新初始化,实现“重新开始”。
#### 行为流程
1. 如果上下文存在且未关闭,先调用 `close()`
2. 关闭完成后调用 `initAudioContext()` 重建上下文。
3. 重置播放时间线。
> ✅ 可用于重置播放状态或应对长时间运行后的资源释放问题。
---
### `setVolume(value)`
设置播放音量。
#### 参数
| 参数名 | 类型 | 范围 | 描述 |
|-------|------|------|------|
| `value` | `number` | `0.0 ~ 1.0` | 目标音量值 |
#### 功能
- 自动限制输入值在 `[0, 1]` 范围内。
- 更新 `this.volume`
- 如果已初始化 `gainNode`,则更新其 `gain.value`(若已静音则保持为 0
- 触发 `onVolumeChange` 事件。
#### 示例
```js
player.setVolume(0.75); // 设置音量为 75%
```
---
### `toggleMute()`
切换静音状态。
- 若当前非静音,则进入静音状态(`gain.value = 0`)。
- 若当前静音,则恢复至原音量(`gain.value = this.volume`)。
- 切换后更新 `this.muted` 并触发 `onVolumeChange`
---
### `emit(eventName, ...args)`
触发指定事件回调(如果定义了对应函数)。
#### 参数
| 参数名 | 类型 | 描述 |
|-------|------|------|
| `eventName` | `string` | 回调函数名(对应 `options[eventName]` |
| `...args` | any | 传递给回调的参数 |
#### 示例
```js
this.emit('onStart'); // 调用 options.onStart()
```
---
## 使用示例
```js
// 创建播放器实例
const audioPlayer = new bricks.ContinueAudioPlayer({
onStart: () => console.log("▶️ 开始播放"),
onEnd: () => console.log("⏹️ 播放结束"),
onVolumeChange: (v) => console.log(`🔊 音量: ${v}`)
});
// 假设你有一段 Base64 音频数据
const base64Audio = "UklGRiQAAABXQVZFZm1...";
const buffer = audioPlayer.base64ToArrayBuffer(base64Audio);
// 播放音频
audioPlayer.handleAudioTrack(buffer);
// 控制操作
audioPlayer.setVolume(0.5); // 调整音量
audioPlayer.toggleMute(); // 切换静音
audioPlayer.pauseAudio(); // 暂停
audioPlayer.resumeAudio(); // 恢复
audioPlayer.restart(); // 重启播放器
```
---
## 浏览器兼容性
| 浏览器 | 支持情况 |
|--------|----------|
| Chrome | ✅ 支持 |
| Firefox | ✅ 支持 |
| Safari | ⚠️ 需要 `webkitAudioContext` 兼容写法(已内置处理) |
| Edge | ✅ 支持 |
| iOS Safari | ✅(注意自动播放策略) |
> 🔐 **注意**:出于安全策略,大多数现代浏览器要求 **用户手势(如点击)** 后才能启动音频上下文。
---
## 注意事项
1. **自动播放限制**
大多数浏览器禁止页面加载时自动播放音频。建议在用户点击事件中初始化或调用 `handleAudioTrack`
2. **内存管理**
长时间连续播放大量音频可能导致内存占用上升,请合理管理音频数据生命周期。
3. **跨域音频数据**
所有音频数据需满足同源策略或 CORS 要求,否则无法解码。
4. **精度同步**
利用 `AudioContext.currentTime` 实现高精度播放调度,适合多段连续播放场景。
---
## 图解工作流程
```
[Base64]
↓ base64ToArrayBuffer()
[ArrayBuffer]
↓ handleAudioTrack()
decodeAudioData() → AudioBuffer
↓ createBufferSource()
[Source Node] → gainNode → destination
startTime = max(now, nextStartTime)
nextStartTime += duration
```
---
## 许可与归属
© 2025 Bricks Framework. All rights reserved.
开源协议:请参考项目 LICENSE 文件。
---
📌 **提示**:结合 WebSocket 或 Fetch 流式传输,可实现 TTS 实时语音播报系统。