音视频多轨权限过滤通过多态解耦绑定与冲刷:定义trackbindingstage抽象类及disabled/preview/active/muted等子类,按权限上下文动态创建阶段对象,统一调用enter()/flush()完成各轨绑定与清理,支持阶段迁移与批量协同。

在音视频多轨权限过滤中,用对象多态解耦多阶段绑定与冲刷,核心是把“不同阶段的绑定行为”和“不同权限下的处理策略”从硬编码分支里抽离出来,变成可替换、可组合、有明确生命周期的对象。
多态不是为了炫技,而是让“什么时候绑”和“怎么绑”不再纠缠在一起。
多阶段绑定应由状态驱动,而非条件判断
多轨系统常见阶段包括:准备(prepare)、预加载(preload)、启用(enable)、激活(activate)、暂停(pause)、释放(flush)。若每个阶段都写 if-else 判断当前权限再决定是否调用 track.enabled = true 或 stop(),代码会迅速腐化。
用多态替代的方式是:
- 定义抽象基类
TrackBindingStage,声明enter()和exit()方法 - 为每种权限上下文实现具体子类:
DisabledStage(无权限,静默跳过)、PreviewStage(仅预览,不启流)、ActiveStage(全功能启用)、MutedStage(采集但禁用输出) - 每个子类内部封装该阶段下对轨道的完整操作序列(如创建 TrackProcessor、设置 enabled、触发 ontrackready 回调、注册冲刷钩子)
这样,阶段切换不再是 if (hasPerm) { bind(); } else { skip(); },而是:
const stage = this.stageFactory.createFor(permissionContext); stage.enter(track); // 自动完成绑定、监听、配置
冲刷(flush)必须与绑定阶段语义对齐,不能全局暴力清空
“冲刷”不是简单地 track.stop() 或 srcObject = null。它应是当前绑定阶段的自然退出动作:
-
PreviewStage.flush()→ 释放预加载缓冲,不清空 MediaStream -
ActiveStage.flush()→ 调用track.enabled = false+ 触发 flush 事件 + 清理编码器上下文 -
DisabledStage.flush()→ 什么也不做(本就没绑定)
所有 flush 行为由 stage 对象自己定义,上层调度器只需调用 currentStage.flush(),无需知道底层是停流、静音还是忽略。
多轨协同靠统一接口,不依赖具体类型
当处理多轨(如 video + audio + subtitle)时,不要为每轨写一套 if-else 阶段逻辑。而是:
- 所有轨道包装成
TrackHandle对象,持有track,id,permissionScope等元数据 -
TrackHandle实现统一接口:.bind(stage)、.flush()、.isBound() - 绑定阶段对象接收
TrackHandle[]数组,批量调用其方法,内部自动按各轨权限选择对应 stage 实例
例如:
class ActiveStage {
enter(handles) {
handles.forEach(handle => {
handle.track.enabled = true;
handle.emit('bound');
// 注册该轨专属 flush 清理函数到全局冲刷队列
this.flushQueue.push(() => handle.track.enabled = false);
});
}
}
权限变更时,不是重走流程,而是阶段迁移
用户权限动态变化(如从试用升级为会员),不应销毁重建整个流,而应触发 stage 迁移:
this.currentStage.exit(); this.currentStage = this.stageFactory.createFor(newPermission); this.currentStage.enter(this.handles);
迁移过程可带过渡逻辑:PreviewStage → ActiveStage 可自动恢复 enabled;ActiveStage → MutedStage 只设 enabled = false,保留采集状态,便于秒级恢复。
不复杂但容易忽略:多态解耦的真正价值,不在减少几行代码,而在让“绑定”和“冲刷”成为可测试、可回滚、可审计的一等公民。每个 stage 是一个行为契约,而不是一堆散落的开关指令。











