bricks/aidocs/recorder.md
2025-10-05 06:39:58 +08:00

10 KiB
Raw Blame History

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.clickswitch_record()
    • cancel.clickcancel_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()

启动实际录制流程。

步骤:
  1. 设置 normal_stop = false
  2. 实例化 MediaRecorder 并绑定事件:
    • ondataavailable: 收集数据块到 recordedChunks
    • onstop: 处理最终文件生成与事件分发
  3. 记录 start_time
  4. 启动定时器更新时间显示
  5. 调用 mediaRecorder.start()
  6. 触发 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()

清理资源并关闭弹窗。

清理项:
  • 取消 taskpic_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。

流程:
  1. webmBlob.arrayBuffer() → 获取二进制数据
  2. 使用 AudioContext.decodeAudioData() 解码为 AudioBuffer
  3. 调用 encodeWAV() 生成 WAV 文件头 + 数据
  4. 返回新的 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();

注意事项

  1. 权限请求getUserMedia 需要在安全上下文HTTPS中运行且用户需授权。
  2. 兼容性MediaRecorder 在部分旧浏览器中不支持或需前缀。
  3. 内存管理:长时间录制可能导致大量 recordedChunks 占用内存,建议限制最大时长。
  4. 格式支持:不同浏览器支持的 mimeType 不同,应做检测回退。
  5. 跨域问题captureStream()<video> 要求同源或 CORS 允许。

总结

bricks.MediaRecorder 提供了一个模块化、可扩展的媒体录制架构,适用于多种场景:

用途 输出格式
WidgetRecorder 录屏(特定元素) MP4 / WAV
SysAudioRecorder 录音 WAV经转换
SysVideoRecorder 录像 MP4
SysCamera 拍照 JPEG

结合 bricks 框架的组件系统与事件机制,可轻松集成至可视化编辑器或交互式应用中。