9.9 KiB
bricks 音频模块技术文档
本文档为 bricks 框架中的音频相关功能模块提供详细说明,包含以下核心类:
bricks.formatMs()—— 时间格式化工具函数bricks.AudioPlayer—— 音频播放器组件bricks.AudioRecorder—— 音频录制与上传组件bricks.TextedAudioPlayer—— 带文本同步的流式音频播放器- 工厂注册机制(通过
bricks.Factory)
1. 工具函数:bricks.formatMs(ms, all)
将毫秒数转换为可读的时间字符串,支持自定义显示粒度。
参数
| 参数 | 类型 | 描述 |
|---|---|---|
ms |
number |
时间(单位:毫秒) |
all |
boolean? |
是否强制显示所有时间单位(即使高位为0) |
返回值
返回格式化的字符串,形式如:"h:mm:ss″sss" 或 "mm:ss″sss"
- 小时部分仅在非零时显示
- 分钟和秒根据上下文决定是否显示前导零
- 毫秒固定三位数字补全
示例
bricks.formatMs(3661234); // 输出: "1:01:01″234"
bricks.formatMs(61234, true); // 输出: "01:01″0234"
2. 音频播放器:bricks.AudioPlayer
基于 HTML5 <audio> 元素封装的高级音频播放控制组件。
继承关系
class AudioPlayer extends bricks.JsWidget
构造选项 (options)
| 属性 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
url |
string |
否 | null |
初始音频源 URL |
autoplay |
boolean |
否 | false |
是否自动播放 |
实例属性
| 属性 | 类型 | 描述 |
|---|---|---|
audio |
HTMLAudioElement |
内部使用的 <audio> DOM 节点 |
source |
HTMLSourceElement |
动态创建的 <source> 节点 |
playlist |
Array<string> |
待播放的 URL 列表(队列) |
url_generator |
AsyncGenerator |
流式加载 URL 的异步生成器 |
srcList |
Array<{played: boolean, url: string}> |
动态加载的音频源列表 |
方法
get_status() → string
获取当前播放状态。
返回值:
| 状态 | 说明 |
|---|---|
"error" |
音频加载出错 |
"ended" |
播放结束 |
"paused" |
暂停中 |
"loading" |
数据不足,正在缓冲 |
"playing" |
正在播放 |
add_url(url: string)
向播放队列添加新音频。若当前状态为 'error' 或 'ended',立即播放该音频;否则加入队列。
set_source(url: string)
设置音频源并更新 DOM。
⚠️ 注意:会同时设置
this.audio.src和内部<source>元素。
set_stream_urls(response: Response)
从服务器流式接收多个音频 URL(每行一个),用于连续播放场景(如语音合成流)。
参数
response:fetch返回的Response对象,其 body 应为逐行输出的文本流。
实现逻辑
- 创建异步生成器
dyn_urls()解析流数据。 - 使用
schedule_once()异步启动load_queue_url()。 - 自动预加载并顺序播放音频片段。
async load_queue_url()
内部方法:持续从 url_generator 获取新的音频 URL,并维护 srcList。
当 srcList.length < 2 时触发首次播放。
async play_srclist(event?)
播放 srcList 中尚未播放的第一个音频项。
- 若传入事件对象且音频未结束,则不执行。
- 播放完成后通过
'ended'事件继续下一首。
play() / toggle_play()
play(): 异步调用原生audio.play()。toggle_play(): 切换播放/暂停状态。
set_url(url)
设置音频源并立即开始播放。
等价于:
this.set_source(url);
this.audio.play();
3. 音频录制器:bricks.AudioRecorder
实现麦克风录音、可视化、文件上传与下载功能。
外部依赖
必须引入第三方库 Recorder.js,支持 WAV 格式录音。
<script src="https://cdn.jsdelivr.net/npm/recorder-js"></script>
继承关系
class AudioRecorder extends bricks.HBox
构造选项 (opts)
| 属性 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
upload_url |
string |
否 | null |
录音结束后上传的目标地址 |
start_icon |
string |
否 | 内置 SVG | 开始按钮图标路径 |
stop_icon |
string |
否 | 内置 SVG | 停止按钮图标路径 |
icon_rate |
number |
否 | undefined |
图标缩放比例 |
事件系统
通过 this.dispatch() 触发以下自定义事件:
| 事件名 | 触发时机 | 携带参数 |
|---|---|---|
record_started |
开始录音 | 无 |
record_ended |
结束录音 | {data: Blob, url: string, duration: number} |
uploaded |
成功上传后 | 服务器返回结果 |
可通过 bind() 监听这些事件。
主要组件
rec_btn: 使用bricks.Svg显示切换式按钮(开始/停止)rec_time: 显示已录制时长(调用bricks.formatMs())wave: (预留)波形图显示区域(需额外包支持)
核心方法
recOpen() / recClose()
打开或关闭麦克风权限。
- 调用
Recorder.open()请求用户授权。 - 成功后设置
this.rec实例并派发record_started。 - 失败时打印调试信息。
start_recording() / stop_recording()
开始或停止录音。
start_recording: 若已授权则直接开始,否则先调用recOpen()。stop_recording: 调用rec.stop()获取Blob和时长,生成本地 URL 并派发record_ended。
on_process(buffers, powerLevel, ...)
录音过程中的实时回调(约每秒12次)。
当前用途:
- 更新录音时长显示(
bufferDuration) - 可扩展用于绘制音量条或波形图(注释中示例)
upload() → Promise<void>
将录音文件以 FormData 形式上传至 upload_url。
使用 bricks.jpost() 发送请求,附带运行中提示(bricks.Running)。
成功后派发 uploaded 事件。
download()
触发浏览器下载当前录音文件(WAV 格式),文件名为 recorder-{timestamp}.wav。
⚠️ 下载完成后自动释放
ObjectURL防止内存泄漏。
4. 文本同步音频播放器:bricks.TextedAudioPlayer
专为“语音+字幕”场景设计的垂直布局播放器,支持流式 JSON 数据驱动。
继承关系
class TextedAudioPlayer extends bricks.VBox
组件结构
- 上方:
AudioPlayer控件 - 下方:
VScrollPanel包含Text组件用于显示文本内容
核心特性
支持通过流式响应动态加载语音与对应文本,实现边生成边播放的效果(适用于 TTS + 字幕同步)。
方法
set_stream_urls(response: Response)
解析流式 JSON 响应,每一行为一个 {audio: base64, text: string} 对象。
使用辅助函数 streamResponseJson(response, callback) 逐条处理。
load_stream_data(json)
接收到单条流数据后的处理逻辑:
- 存入
streaming_buffer队列; - 若当前空闲(
wait_play === true),立即触发playnext()。
playnext()
从缓冲区取出下一条数据:
- 提取
audio字段并转为 URL(base64_to_url()); - 设置播放器源并更新文本显示;
- 播放完毕后等待
'ended'事件再次调用自身。
当数据耗尽时清空界面。
5. 工厂注册
所有组件均通过 bricks.Factory 注册,可在模板中使用标签方式实例化。
bricks.Factory.register('AudioPlayer', bricks.AudioPlayer);
bricks.Factory.register('AudioRecorder', bricks.AudioRecorder);
bricks.Factory.register('TextedAudioPlayer', bricks.TextedAudioPlayer);
示例用法(假设支持声明式语法)
<widget type="AudioPlayer" url="demo.mp3" autoplay="true"/>
<widget type="AudioRecorder" upload_url="/api/upload-audio"/>
<widget type="TextedAudioPlayer"/>
6. 辅助函数与约定
base64_to_url(base64str) → string
将 Base64 编码的音频数据转换为 ObjectURL,供 <audio> 使用。
✅ 实际代码中需确保此函数存在。
schedule_once(fn, delay)
延迟执行一次函数(通常为 setTimeout(fn, delay * 1000) 封装)。
bricks.debug(msg, ...args)
框架级调试日志输出。
bricks.is_mobile() → boolean
判断是否运行在移动设备上,影响下载行为处理。
7. 使用场景建议
| 场景 | 推荐组件 |
|---|---|
| 普通音频播放 | AudioPlayer |
| 用户录音上传 | AudioRecorder |
| AI语音对话(TTS+字幕) | TextedAudioPlayer + 流式 API |
| 连续播放多个短音频 | AudioPlayer.set_stream_urls() |
8. 注意事项
- 跨域限制:录音上传、音频源加载需注意 CORS。
- HTTPS 要求:现代浏览器要求
getUserMedia()在安全上下文中运行(HTTPS 或 localhost)。 - 移动端兼容性:iOS Safari 对自动播放和
ObjectURL支持有限,建议用户交互后触发播放。 - 内存管理:使用
URL.revokeObjectURL()及时释放资源。 - 错误处理:建议监听
error事件并在 UI 中反馈。
9. 示例代码
初始化一个播放器
const player = new bricks.AudioPlayer({
url: 'music.mp3',
autoplay: true
});
document.body.appendChild(player.dom_element);
创建录音器并绑定上传
const recorder = new bricks.AudioRecorder({
upload_url: '/api/v1/audio-upload',
icon_rate: 1.2
});
recorder.bind('uploaded', (res) => {
console.log('Upload success:', res);
});
document.body.appendChild(recorder.dom_element);
流式语音播放(AI 回复)
fetch('/api/stream-tts', { method: 'POST', body: prompt })
.then(response => {
const tap = new bricks.TextedAudioPlayer();
tap.set_stream_urls(response);
document.body.appendChild(tap.dom_element);
});
📚 文档版本:v1.0
© 2025 bricks Framework Team