bricks/docs/ai.old/continueaudio.md
2025-11-18 14:59:26 +08:00

145 lines
5.4 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
该控件是一个**容器控件**,继承自 `bricks.VBox`,用于在浏览器中连续播放通过 WebSocket 或 Base64 编码传输的音频数据。它基于 Web Audio API 实现高精度、低延迟的音频播放控制,支持暂停、恢复、重新开始、音量调节和静音功能。适用于语音播报、实时通信、在线教育等需要无缝播放多个音频片段的场景。
---
## 主要方法
- **`initAudioContext()`**
初始化 Web Audio API 的上下文AudioContext和增益节点GainNode为后续音频播放做准备。
- **`base64ToArrayBuffer(base64)`**
将 Base64 编码的音频字符串转换为 ArrayBuffer`decodeAudioData` 使用。
- **`handleAudioTrack(arrayBuffer)`**
解码并播放传入的音频数据ArrayBuffer自动管理播放时间线确保多个音频连续播放不重叠。
- **`pauseAudio()`**
暂停当前播放的音频(实际是挂起 AudioContext
- **`resumeAudio()`**
恢复被暂停的音频播放。
- **`restart()`**
关闭当前 AudioContext 并重新初始化,从头开始播放。
- **`setVolume(value)`**
设置音量0.0 ~ 1.0),自动更新增益节点,并触发 `onVolumeChange` 事件。
- **`toggleMute()`**
切换静音状态,同时更新增益值并发出音量变化事件。
- **`emit(eventName, ...args)`**
触发配置中的回调函数,如 `onStart``onEnd` 等。
---
## 主要事件
这些事件可通过 `options` 配置传入回调函数,在特定时刻执行逻辑:
- **`onStart`**:当一个音频轨道开始播放时触发。
- **`onEnd`**:当一个音频轨道播放结束后触发。
- **`onPause`**:调用 `pauseAudio` 成功后触发。
- **`onResume`**:调用 `resumeAudio` 成功后触发。
- **`onVolumeChange`**:音量或静音状态改变时触发,参数为当前有效音量(静音时为 0
---
## 源码例子
```json
{
"id": "audioPlayerContainer",
"widgettype": "ContinueAudioPlayer",
"options": {
"ws_url": "wss://example.com/audio-stream", // 可选WebSocket 地址(若使用流式接收)
"onStart": "function() { console.log('音频开始播放'); }",
"onEnd": "function() { console.log('音频播放结束'); }",
"onPause": "function() { bricks.getWidget('playBtn').setValue('▶️ 播放'); }",
"onResume": "function() { bricks.getWidget('playBtn').setValue('⏸️ 暂停'); }",
"onVolumeChange": "function(vol) { bricks.getWidget('volumeSlider').setValue(vol); }"
},
"subwidgets": [
{
"id": "controlBar",
"widgettype": "HBox",
"subwidgets": [
{
"id": "playBtn",
"widgettype": "Button",
"options": {
"value": "▶️ 播放",
"onClick": "function() { var player = bricks.getWidget('audioPlayerContainer'); if (player.audioContext.state === 'running') { player.pauseAudio(); } else { player.resumeAudio(); } }"
}
},
{
"id": "restartBtn",
"widgettype": "Button",
"options": {
"value": "🔁 重新开始",
"onClick": "function() { bricks.getWidget('audioPlayerContainer').restart(); }"
}
},
{
"id": "muteBtn",
"widgettype": "Button",
"options": {
"value": "🔊 静音",
"onClick": "function() { var player = bricks.getWidget('audioPlayerContainer'); player.toggleMute(); this.setValue(player.muted ? '🔇 取消静音' : '🔊 静音'); }"
}
},
{
"id": "volumeSlider",
"widgettype": "Slider",
"options": {
"min": 0,
"max": 1,
"step": 0.01,
"value": 1,
"onChange": "function(val) { bricks.getWidget('audioPlayerContainer').setVolume(val); }"
}
}
]
}
],
"binds": [
{
"actiontype": "method",
"wid": "externalStartTrigger",
"event": "click",
"target": "audioPlayerContainer",
"method": "resumeAudio",
"conform": {
"title": "确认播放",
"message": "确定要开始播放音频吗?",
"confirmButtonText": "确定",
"cancelButtonText": "取消"
}
},
{
"actiontype": "script",
"wid": "dataReceiver",
"event": "audioDataReady",
"target": "audioPlayerContainer",
"datascript": "return base64EncodedAudioChunk;", // 假设外部脚本提供了此变量
"script": "const buf = widget.base64ToArrayBuffer(rtdata); widget.handleAudioTrack(buf);"
}
]
}
```
> ✅ **注释说明:**
>
> - `ContinueAudioPlayer` 本身作为容器,包含一组控制按钮(播放/暂停、重启、静音、音量滑块)。
> - `binds` 中定义了两个行为:
> 1. 点击外部元素 `externalStartTrigger` 时,调用播放器的 `resumeAudio` 方法,带确认弹窗。
> 2. 当 `dataReceiver` 组件触发 `audioDataReady` 事件时,执行脚本将 Base64 数据转为 ArrayBuffer 并交给播放器处理。
> - 所有 UI 控件通过 ID 获取实例并与 `ContinueAudioPlayer` 实例交互。
> - 回调函数使用字符串形式的 `function(){}` 写法,符合 Bricks.js 对 options 中函数的序列化要求。
---
💡 **提示:**
要实现真正的“持续”播放,需保证不断向 `handleAudioTrack` 方法传入新的音频数据块ArrayBuffer。可结合 WebSocket 接收流式音频并解码推送至此控件。