10 KiB
bricks.MediaRecorder 技术文档
概述
bricks.MediaRecorder 是一个基于浏览器 MediaRecorder API 的通用媒体录制组件,继承自 bricks.Popup。它提供了统一的界面和控制逻辑,支持音频、视频以及特定 DOM 元素(如 <video>)的录制功能。
通过继承机制,该类派生出多个具体实现:
WidgetRecorder:录制指定页面中的媒体元素(如<video>或<audio>)SysAudioRecorder:录制系统麦克风输入(音频流),并自动转换 WebM 为 WAV 格式SysVideoRecorder:录制摄像头及麦克风输入(音视频流),实时预览画面SysCamera:仅拍照模式,用于从摄像头抓取单帧图像
所有子类均通过 bricks.Factory 注册,便于在应用中动态创建。
基础类:bricks.MediaRecorder
继承关系
class bricks.MediaRecorder extends bricks.Popup
构造函数
constructor(opts)
参数
| 参数名 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
opts.fps |
Number | 否 | 30 |
帧率(每秒更新次数),用于时间显示刷新频率 |
初始化内容
- 设置任务周期:
this.task_period = 1 / fps - 创建 UI 组件:
preview: 预览区域(VBox)controls: 控制栏(HBox)toggle_record: 开始/停止按钮(SVG 图标)timepass: 显示已录制时间(格式:HH:MM:SS)filler: 弹性填充空间cancel: 取消按钮(删除图标)
- 绑定事件:
toggle_record.click→switch_record()cancel.click→cancel_record()
- 初始化状态:
record_status = 'standby'- 初始禁用录制按钮
- 调度
open_recorder()在 0.1 秒后执行(异步准备设备)
属性
| 属性 | 类型 | 描述 |
|---|---|---|
fps |
Number | 每秒帧数,决定 UI 更新频率 |
task_period |
Number | 定时任务间隔(秒) |
task |
TaskHandle | 当前运行的时间更新定时器 |
pic_task |
TaskHandle | (仅视频)图像捕获定时器 |
stream |
MediaStream | 获取到的媒体流 |
mediaRecorder |
MediaRecorder | 浏览器原生录制实例 |
recordedChunks |
Array | 存储录制过程中产生的数据块 |
mimetype |
String | 媒体 MIME 类型(如 'audio/wav', 'video/mp4') |
normal_stop |
Boolean | 是否正常结束录制(防止重复触发) |
record_status |
String | 状态:'standby' 或 'recording' |
start_time |
Number | 录制开始的时间戳(毫秒) |
time_diff |
String | 当前录制时长字符串(HH:MM:SS) |
方法
tick_task()
定时更新录制时间显示。
tick_task()
- 使用
schedule_once循环调用自身,间隔为this.task_period - 调用
bricks.timeDiff(this.start_time)计算经过时间 - 更新
this.timepass文本
⚠️ 注意:必须手动取消任务以避免内存泄漏。
async switch_record()
切换录制状态(开始或停止录制)。
switch_record()
行为根据当前 record_status 决定:
| 状态 | 动作 |
|---|---|
'standby' |
调用 start_recorder(),图标变为“停止” |
'recording' |
调用 stop_recorder(),图标恢复为“开始” |
cancel_record()
取消当前录制操作,关闭资源并关闭弹窗。
cancel_record()
等价于调用 close_recorder()。
async open_recorder()
虚方法:由子类重写以打开具体的媒体源。
open_recorder()
默认实现为空,仅输出调试日志。
子类应在此方法中:
- 请求用户权限(如麦克风/摄像头)
- 获取
MediaStream - 设置
this.stream - 解除录制按钮禁用状态
async start_recorder()
启动实际录制流程。
步骤:
- 设置
normal_stop = false - 实例化
MediaRecorder并绑定事件:ondataavailable: 收集数据块到recordedChunksonstop: 处理最终文件生成与事件分发
- 记录
start_time - 启动定时器更新时间显示
- 调用
mediaRecorder.start() - 触发
record_started事件
事件分发
record_started: 录制开始时触发
async blob_convert(blob)
可扩展方法:允许子类对录制结果 Blob 进行格式转换。
blob_convert(blob) → Promise<Blob>
默认直接返回原始 Blob。
示例:
SysAudioRecorder中将 WebM 转换为 WAV。
stop_recorder()
停止录制,并标记为正常终止。
行为:
- 设置
normal_stop = true - 更新时间显示
- 调用
mediaRecorder.stop() - 调用
close_recorder()
close_recorder()
清理资源并关闭弹窗。
清理项:
- 取消
task和pic_task(如有) - 停止
mediaRecorder(若存在) - 停止
stream所有轨道 - 调用
dismiss()关闭弹窗
若正在录制,会强制中断。
子类详解
bricks.WidgetRecorder
录制页面中某个媒体元素(如
<video>或<audio>)
继承链
class WidgetRecorder extends MediaRecorder
open_recorder()
- 根据
opts.widgetid查找目标组件 - 检查其 DOM 标签类型:
<video>→mimetype = 'video/mp4'<audio>→mimetype = 'audio/wav'
- 调用
captureStream()获取流 - 启用录制按钮
⚠️ 错误处理:非媒体元素抛出异常
bricks.SysAudioRecorder
录制麦克风输入,支持 WebM → WAV 自动转换
继承链
class SysAudioRecorder extends MediaRecorder
open_recorder()
- 请求麦克风权限(
getUserMedia({ audio: true })) - 设置
mimetype = 'audio/webm' - 获取音频流并启用按钮
blob_convert(webmBlob)
将 WebM 编码的音频解码为 PCM,再编码为标准 WAV 格式 Blob。
流程:
webmBlob.arrayBuffer()→ 获取二进制数据- 使用
AudioContext.decodeAudioData()解码为AudioBuffer - 调用
encodeWAV()生成 WAV 文件头 + 数据 - 返回新的
Blob(type='audio/wav')
encodeWAV(audioBuffer)
手动构建 WAV 文件二进制结构,包含 RIFF 头信息。
| 参数 | 值 |
|---|---|
| 采样率 | 来自 audioBuffer.sampleRate |
| 声道数 | audioBuffer.numberOfChannels |
| 位深 | 16-bit PCM |
| 格式 | 小端序(little-endian) |
使用 DataView 写入头部字段。
interleave(left, right)
交错左右声道数据,生成立体声 PCM 数组。
writeString(view, offset, string)
辅助函数:向 DataView 写入 ASCII 字符串。
bricks.SysVideoRecorder
录制摄像头+麦克风,带实时预览
继承链
class SysVideoRecorder extends MediaRecorder
open_recorder()
- 请求音视频权限:
{ audio: true, video: true } - 设置
mimetype = 'video/mp4' - 创建
ImageCapture(track)对象用于逐帧捕获 - 添加
bricks.Image到预览区 - 启动
show_picture()循环任务
show_picture()
- 调用
imageCapture.takePhoto()获取当前帧 Blob - 转换为 Data URL 并设置给
imgw - 创建
File对象供后续使用 - 递归调度下一次拍摄
实现了类似“摄像机取景器”的效果
close_recorder()
重写以额外清理 pic_task。
bricks.SysCamera
专用拍照工具,从摄像头抓拍一张照片
继承链
class SysCamera extends SysVideoRecorder
switch_record()
重写行为为“拍照”而非录制:
动作:
- 阻止事件冒泡(
event.stopPropagation()) - 停止
pic_task - 设置
task_period = 0防止继续更新 - 分发
shot事件,携带:{ url: this.dataurl, // 图像 Data URL file: this.imgfile // 图像 File 对象 } - 调用
close_recorder()关闭
不进行任何视频录制,仅抓取一帧
工厂注册
以下类通过 bricks.Factory 注册,可在配置中通过名称实例化:
bricks.Factory.register('SysCamera', bricks.SysCamera);
bricks.Factory.register('WidgetRecorder', bricks.WidgetRecorder);
bricks.Factory.register('SysAudioRecorder', bricks.SysAudioRecorder);
bricks.Factory.register('SysVideoRecorder', bricks.SysVideoRecorder);
示例使用方式(假设框架支持):
{
"type": "SysAudioRecorder",
"opts": {
"fps": 25
}
}
事件列表
| 事件名 | 触发时机 | 传递数据 |
|---|---|---|
record_started |
录制开始时 | 无 |
record_end |
录制正常结束 | { url: string, file: File } |
shot |
(SysCamera)拍照完成 | { url: string, file: File } |
使用
this.dispatch(eventName, data)触发
工具函数依赖
| 函数 | 来源 | 用途 |
|---|---|---|
bricks_resource(path) |
全局函数 | 解析静态资源路径 |
schedule_once(fn, delay) |
全局函数 | 延迟执行函数(支持取消) |
bricks.timeDiff(timestamp) |
工具模块 | 将时间戳差值转为 HH:MM:SS 字符串 |
bricks.getWidgetById(id, app) |
框架 API | 根据 ID 获取组件实例 |
使用示例
启动音频录制
const recorder = new bricks.SysAudioRecorder({
fps: 30
});
recorder.bind('record_end', (data) => {
console.log('录音完成:', data.file);
const audio = document.createElement('audio');
audio.src = data.url;
audio.controls = true;
document.body.appendChild(audio);
});
recorder.present(); // 显示录制界面
抓拍摄像头照片
const camera = new bricks.SysCamera();
camera.bind('shot', ({ file }) => {
console.log('照片已拍摄:', file);
});
camera.present();
注意事项
- 权限请求:
getUserMedia需要在安全上下文(HTTPS)中运行,且用户需授权。 - 兼容性:
MediaRecorder在部分旧浏览器中不支持或需前缀。 - 内存管理:长时间录制可能导致大量
recordedChunks占用内存,建议限制最大时长。 - 格式支持:不同浏览器支持的
mimeType不同,应做检测回退。 - 跨域问题:
captureStream()对<video>要求同源或 CORS 允许。
总结
bricks.MediaRecorder 提供了一个模块化、可扩展的媒体录制架构,适用于多种场景:
| 类 | 用途 | 输出格式 |
|---|---|---|
WidgetRecorder |
录屏(特定元素) | MP4 / WAV |
SysAudioRecorder |
录音 | WAV(经转换) |
SysVideoRecorder |
录像 | MP4 |
SysCamera |
拍照 | JPEG |
结合 bricks 框架的组件系统与事件机制,可轻松集成至可视化编辑器或交互式应用中。