videojs v10 源代码系列解读:33 · Behavior:通用组合单元

地图打印与 GeoTIFF 导出:框选区域、矢量标绘、一键出图 空间智能实验室 Vol.19:地图打印与 GeoTIFF 导出:框选区域、矢量标绘、一键出图 「把这块区域导成一张带地理坐标的高清图」是个很朴素的需求,但朴素不等于简单。你要在浏览器里框一个框、画几个箭头标个文字、叠一层 阅读详情

03 篇预告过:「Behavior 是 SPF 区别于所有其他流媒体库的核心创新」。这篇正式拆它。Behavior 把信号、Actor、Reactor、Runner 全部统一成一种可组合单元——引擎就是一个 Behavior 列表。还会讲 defineBehavior 的穷尽性强制和 makeShareSignals 的消费者边界。下一篇讲 createComposition 的类型冲突检测。

回顾:Behavior 接口

create-composition.ts:83-93(03 篇引用过):

export interface Behavior<StateMap, ContextMap, Cfg> {
  stateKeys: readonly (keyof StateMap)[];      // L89 — 声明需要的状态键
  contextKeys: readonly (keyof ContextMap)[];   // L91 — 声明需要的上下文键
  setup: (deps: BehaviorDeps) => BehaviorCleanup;  // L92
}

一个 behavior 声明自己需要哪些键(stateKeys/contextKeys),提供一个 setup 函数,返回可选清理。BehaviorDeps(L60-64)给 setup 传 { state, context, config }——槽位映射 + 静态配置。

BehaviorCleanup(L9):void | (() => void | Promise<void>) | { destroy(): void | Promise<void> }——三种形态,函数或带 destroy 的对象,可异步。

两种 flavor:简单 vs 原语增强

设计文档(27 篇引过)的核心论断:问题的核心从来不是「用 Behavior 还是 Actor?」,而是「用 Behavior 包裹什么?」

  • 简单 behavior——只用信号。stateKeys 声明槽位,setup 里 computed/effect 建响应关系。
  • 原语增强 behavior——内部实例化 actor/reactor/runner。actor/reactor/runner 永远活在 behavior 内部,从不出现在组合层。

这个规则我读源码验证过:setup-mediasource.ts、load-segments.ts 这些 behavior 内部 new 了一堆 actor/reactor,但对外的形态仍然是标准的 { stateKeys, contextKeys, setup }。组合层只认 Behavior 一种东西——这就是「通用组合单元」的含义。

对比 hls.js:它有 StreamController、BufferController、LevelController……一堆 controller 类互相引用、互相调用方法。SPF 里这些全部变成 behavior,互相之间零直接引用——只通过信号槽位通信。

defineBehavior:穷尽性强制(L428-455)

手写 Behavior 字面量有个风险:类型声明了 state map,但 stateKeys 忘了列全某个键。运行时那个键的信号不会被创建,setup 里读它拿到 undefined,出了 bug 还很难查。

defineBehavior 在编译期堵住这个漏洞。核心是 ExhaustiveKeys(L375-379):

type ExhaustiveKeys<Keys extends readonly PropertyKey[], Slot extends object, Name extends string> =
  [keyof Slot] extends [Keys[number]]
    ? Empty
    : { [K in `Error: ${Name}Keys must list every key in the typed slice`]: Exclude<keyof Slot, Keys[number]> };

判定 keyof Slot ⊆ Keys[number](槽位类型的每个键都在 keys 数组里)。不满足时给参数 shape 加一个 phantom 字段——错误消息是模板字面量类型(Error: stateKeys must list every key in the typed slice),值是缺失键的列表。用户提供的值不可能满足这个字段,调用点直接编译报错,错误消息里列出漏了哪些键。

这是「把运行时 bug 提前到编译期」的又一手(和 store 的 UnionSliceState、capability 的谓词一个思路,但更极致——错误消息本身是类型)。

还有个贴心细节(L432-433):defineBehavior 的 const 修饰符让 stateKeys: ['preload'] 直接推断为 readonly ['preload'],调用点免写 as const。

运行时呢?恒等(L450-454 只有 as unknown as 桥接)——defineBehavior 是纯类型检查器,零运行时成本。

makeShareSignals:消费者边界(53 行)

Behavior 们互相通过信号槽位通信,那外部消费者(比如引擎的使用者)怎么拿到这些信号?share-signals.ts 的 makeShareSignals(L41-44):

export function makeShareSignals<S, C>(inputStateKeys = [], inputContextKeys = []) {
  return {
    stateKeys: inputStateKeys,      // 透传(默认 [])
    contextKeys: inputContextKeys,
    setup: ({ state, context, config }) => {
      config.onSignalsReady?.({ state, context });   // L47 — setup 时刻交出完整映射
    },
  };
}

它是个特殊 behavior:setup 不干活,只把 composition 的完整信号映射交给 onSignalsReady 回调。引擎使用者通过这个回调捕获信号引用,之后读写。

两个精妙点:

  1. 「capture refs, use later」是安全模式(L10-14 注释警告):回调触发时其他 behavior 还在 setup 阶段,读到的是初始种子值而非后续写入的值。所以正确用法是捕获引用(signal 的身份是稳定的),延迟使用——不要在回调里立刻 .get() 拿业务数据。
  2. inputStateKeys 用来「物化」消费者输入槽(L29-39 注释):如果某个键没有任何 behavior 生产(比如引擎使用者要传入的 userAudioTrackSelection),makeShareSignals 声明它,composition 就会为它创建信号。消费者输入也走同一套槽位机制。

还有一个类型层面的细节(L37-39):它刻意用 Behavior<> 字面量而非 defineBehavior——避免空/部分 keys 数组触发穷尽性检查。因为它的 setup 参数描述的是「回调收到的完整 S/C」,而非它物化的子集,穷尽性检查对它不适用。知道什么时候不用工具,和知道怎么用一样重要。

41 篇会看到 HLS 引擎用 makeShareSignals 作为对外的 I/O 边界。

Behavior 的读写权限模型

把 03 篇的伏笔正式收掉。behavior 的 setup 参数类型是槽位映射:

setup: (deps: {
  state: { presentation: ReadonlySignal<Presentation>, preload: Signal<Preload> },
  // ...
}) => Cleanup

每个槽位自己决定 Signal<T>(可写)或 ReadonlySignal<T>(只读)——28 篇讲过 ReadonlySignal 是 Omit<State<T>, 'set'>。TS 编译期拒绝在只读槽上调 .set()。

读写意图是每个 behavior 自己声明的类型契约。composition 不强制谁拥有哪个键——多个 behavior 可以声明同一个键(一个写、其他读),类型冲突检测(下篇)保证它们对键的类型一致。

引擎 = Behavior 列表(预览)

41 篇详讲,这里先看形态。createSimpleHlsEngine 大致是:

createComposition(
  [
    resolvePresentation,      // 简单 behavior:fetch + 解析清单 → presentation 槽位
    selectTracks,             // 选择轨道 → selection 槽位
    setupMediaSource,         // 原语增强:内部建 MediaSource → mediaSource 槽位
    setupBufferActors,        // 原语增强:SourceBufferActor(video/audio)
    loadSegments,             // 原语增强:SegmentLoaderActor + Reactor 翻译
    endOfStream,              // ...
    abr,                      // ABR(5.75 步)
    makeShareSignals(['userAudioTrackSelection'], [], { onSignalsReady }),  // 消费者边界
  ],
  { config, initialState, initialContext }
);

约 20 个 behavior 按固定顺序。初始化顺序是承重的——比如 syncPreload 必须在 resolvePresentation 之前注册,两个 SourceBuffer 要在一个同步过程创建(Firefox 的 mozHasAudio)。这个顺序约束是显式写在引擎代码里的知识,41 篇展开。

小结

  • Behavior 是唯一组合单元——actor/reactor/runner 活在 behavior 内部,组合层只认 Behavior。
  • behavior 之间零直接引用——只通过信号槽位通信(对比 hls.js 的 controller 互调)。
  • defineBehavior 穷尽性强制——漏列键编译期报错,错误消息列出缺失键;运行时恒等。
  • const 修饰符免 as const。
  • makeShareSignals 是消费者边界——onSignalsReady 交出信号映射;「capture refs, use later」;可物化消费者输入槽。
  • 读写权限是 setup 参数的类型契约——每槽位自选 Signal/ReadonlySignal。

下一篇拆 createComposition 的完整实现——运行时怎么构建信号映射、编译期怎么做类型冲突检测。

吐血总结《Mysql从入门到入魔》,图文并茂 文章目录1. 查询1.1 查询多列1.2 检索唯一值1.3 限制输出1.4 注释2. ORDER BY 排序2.1 单列排序3.2 多列排序3.3 指定排序方向4. WHERE 过滤数据4.1 WHERE 子句操作符4.2 范围值检查4.3 空值检查5. 高级数据过滤5.1 WHERE 组合过滤5.2 IN 操作符5.3 NOT 操作符6. 通配符过滤6.1 % 通配符6.2 _ 通配符7. 创建计算字段7.1 计算字段7.2 拼接字段7.3 执行算数计算8. 函数8.1 常用文本处理函数8.2 日期和时间 阅读详情

相关推荐

别再只调PID了!手把手教你从LC谐振到检波,搞定STM32智能车电磁循迹硬件电路

本文深入解析STM32智能车电磁循迹硬件电路设计,从LC谐振选频到数字信号处理,提供完整的信号链路设计要点与实战技巧。通过优化电磁杆布局和信号放大电路,显著提升赛道位置检测精度,误差可控制在±0.5cm以内,为智能车竞赛提供可靠硬件支持。

weixin_29220405的博客 263

Web 版翻译者资料库

本项目是桌面版《翻译者资料库》的 Web 移植版,基于 Spring Boot 3.3、Thymeleaf、Bootstrap 5.3 与 MySQL 8.0 构建。它面向翻译写作提供资料、词汇、句库、文本工具、对照制作、查找、备份恢复及旧库迁移等功能,完整继承桌面版核心业务规则,支持一键启动与离线访问。

howard2005的专栏 140

高速电路的信号完整性分析

摘要:介绍了高速PCB设计中的信号完整性概念以及破坏信号完整性的原因,从理论和计算的层面上分析了高速电路设计中反射和串扰的形成原因,并介绍了IBIS仿真。 关键词:信号完整性 反射 串扰 IBIS仿真 随着半导体技术和深压微米工艺的不断发展,IC的开关速度目前已经从几十MHz增加到几百MHz,甚至达到几GHz。在高速PCB设计中,工程师经常会碰到误触发、阻尼振荡、过冲、欠冲、串...

bh_wang的专栏 1431

Jackson 序列化 / 反序列化注解 完整版笔记

Jackson 序列化 / 反序列化注解 完整版笔记

handsome_sai的博客 272

RV1126上YOLOv8部署实战:从模型转换到板端推理的完整避坑指南

本文提供了在瑞芯微RV1126芯片上部署YOLOv8目标识别算法的完整实战指南。内容涵盖从模型转换、环境搭建到板端推理代码编写的全流程,重点解析了RKNN-Toolkit使用、量化配置、内存优化及后处理实现等关键环节的常见问题与解决方案,旨在帮助开发者高效避坑,实现边缘AI应用的稳定落地。

pz89012345的博客 568

IAR9.20.4安装与注册全攻略:附资源及典型问题解决方案

本文提供IAR9.20.4的详细安装与注册指南,涵盖环境准备、安装步骤、权限设置及注册机使用技巧。针对典型问题如评估版残留、权限不足和杀毒软件拦截等,给出了具体解决方案,帮助用户顺利完成IAR开发环境的搭建与激活。

a2b3c4d5e的博客 296

【项目推荐】基于 SpringBoot3 + Spring AI 的游泳馆管理系统:Agent + RAG + Function Calling 一次学全

它不是玩具 Demo,而是一个「业务 + AI」双主线交织的真实系统——预约业务在跑,AI 客服在旁边实时查库作答,两条线通过 Function Calling、RAG、站内消息串成一体。面试官问「你做过什么 AI 项目」时,你能从业务场景讲到架构取舍,从 RAG 切分参数讲到降级兜底——这和「我调了一下 ChatGPT 的 API」是完全不同的两个段位。项目已包含完整的建表 SQL、初始化数据、部署文档,克隆下来就能跑。获取方式:见文末说明 / 后台回复关键词获取。—— 完 ——

深耕开发,专注编程实战。分享源码解析、项目搭建、问题排查笔记,沉淀技术,持续更新。 347

PINN疲劳寿命预测优化

本项目基于物理信息神经网络(PINN)构建材料疲劳寿命预测模型,通过融合Paris裂纹扩展方程与实验数据,实现裂纹扩展行为的精准预测。核心方法包括:1)将Paris方程作为物理约束嵌入神经网络训练;2)生成含噪声的模拟数据并进行归一化处理;3)采用PINN-GA联合优化框架,以裂纹扩展速率最小化为目标优化材料参数。该方案通过物理规律与数据驱动的结合,显著提升预测模型的泛化能力,为工程材料寿命评估提供新思路。

huanghm88的专栏 146

MCP 协议会成为前端 AI 工程的标准接口吗?

MCP(Model Context Protocol)正在成为连接 AI 模型与外部工具、数据源的一层通用协议。本文从 MCP 的核心机制出发,分析它在浏览器与前端工程中的落地边界,讨论它能否成为前端 AI 工程的标准接口,并给出当下更务实的架构选择建议。

m0_62937412的博客 336

液滴碰撞壁面的过程背景论文——bouncing反弹,spreading扩展,splashing飞溅。铺展过程介绍。还存在很多未解之谜。

【1993-德国-Phenomena of liquid drop impact on solid and liquid surfaces】液滴碰撞壁面的过程背景——bouncing反弹,spreading扩展,splashing飞溅。还存在很多未解之谜。还存在很多未解之谜。不同液滴形状碰撞过程。

qq_15963745的博客 199

1.嵌入式控制器EC学习,编译环境搭建

工欲善其事,必先利其器。 在学习EC相关知识之前,首先需要完成EC代码编译环境的搭建,需要如下内容: Keil C51(用于EC中C代码的编译器环境) EC源代码,我们使用从网上可以下载到的 ITE_V12.4_Update 版的代码为例进行学习 代码编辑器,这个可以根据自己的习惯选择,VS Code或者Source Insight等 Keil C51下载地址: http://www.downcc.com/soft/307131.html 下载完成后请进行破解 EC源代码 ...

qq_30135687的博客 3917

LangGraph 本地 build 频频翻车,最终在服务器跑通流式对话

先说结论:我本地那个,一次都没成功过。三次,三次,全挂在拉镜像上。而顺得像刚上过油。这就很像我高中那辆自行车:骑着能走,一上锁就坏。那天晚上我盯着终端里那行红字看了很久,想的不是技术方案,想的是——为什么同一个工具,可以一边让我觉得自己很行,一边让我觉得自己不太行。

人工智能AI技术 97

2023年12月机器人技术等级考试试卷(三级理论) 试题解析

2023年12月机器人技术等级考试试卷(三级理论) 试题解析

http://www.cierobot.com 4095

海外平台频繁弹验证?从 DNS、WebRTC 到浏览器指纹的环境异常排查清单

在运营多地区海外平台账号时,即使代理节点通畅、TCP 握手成功,仍可能遇到频繁人机验证、地区限制、播放失败等异常。核心结论是:这类问题往往不在网络传输层,而在浏览器环境参数与网络出口之间的逻辑自洽性。本文从 DNS 泄漏、WebRTC 穿透、时区与语言匹配、Canvas/WebGL 指纹、TLS 特征五个维度,给出一份可复现的环境异常排查清单,并对比个人手动配置与工程化环境管理方案的适用边界。适用于跨境运营、多账号运维团队。

P1Browser【p1指纹浏览器】的博客 183

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

智能问诊的流程

本文介绍基于FastAPI构建的医疗多Agent系统MediAgent,通过症状分析、诊断推理与治疗建议等模块协同,实现从问诊到报告生成的完整工作流。系统采用前后端分离架构,结合MySQL、RabbitMQ与Docker实现工程化部署,支持异步化验结果接入。虽当前状态暂存于内存,但已具备可扩展性,未来可通过Redis持久化、消息队列联动及医疗安全机制完善,应用于慢病管理、辅助决策等场景,推动AI在医疗流程中的落地应用。

Joey 的工作空间~ 773

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

信号链电路怎么选运放?奥特四款信号链运放解析【选型参考】

在模拟电路设计中,运放作为信号链的“第一道门槛”,其微小误差往往决定了整个系统的成败。

naNa_1120的博客 191

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

流式输出 SSE:实现 AI 对话打字机效果后端开发

摘要解决传统 HTTP 请求在 LLM 长文本生成时导致的客户端长时间阻塞与 TTFT 极高的问题。适用于需为 AI 应用提供打字机效果、优化交互体验的后端开发工程师。读完可获得基于 FastAPI 与 SSE(Server-Sent Events)技术的流式响应实现代码、协议规范及生产环境避坑指南。关键词SSE、流式输出、FastAPI、打字机效果、TTFT、大模型推理背景与问题大模型(LLM)生成完整回复通常耗时数秒至数十秒,传统请求-响应模型导致用户界面长时间无响应,体验极差。

2402_85729970的博客 181

基于 YOLOv8 的森林火灾检测系统(Web 版)

本项目面向林区早期火情识别场景,使用YOLOv8完成火焰(Fire)与烟雾(Smoke)两类目标的检测模型训练,并以FastAPI构建 Web 检测平台,把模型能力封装为可直接登录使用的系统。平台除常规的图片、批量、视频、摄像头检测外,还提供同图多权重对比、数据集浏览与标注核对、模型热切换,以及把训练搬到网页上的能力:可在浏览器配置超参数发起真实训练,训练中在线调整学习率、查看进度与动态曲线,训练完成后下载产物或直接应用到检测。

Michael_Jay的博客 62

身份验证漏洞专题(三):持久登录、密码重置与密码修改中的凭据绑定缺陷

密码登录与双因素认证是身份验证的主干流程,但一个完整的认证体系还依赖三类辅助机制:持久登录("记住我")、密码重置、密码修改。这三类机制的共同特征是:它们同样携带或验证凭据,同样直接决定认证状态的归属,但实现时获得的防护强度往往远低于登录页面本身。攻击者绕不开登录接口时,常常可以从这些辅助入口进入。

2401_85321170的博客 630

二进制木马免杀-Python 分离免杀与 Web 挂马

二进制木马免杀-Python 分离免杀与 Web 挂马

2503_94637398的博客 268

Vue 前端开发 AI 对话页面:流式消息渲染、文件上传

关键点是不能手动设置 Content-Type 为 multipart/form-data,必须由浏览器自动生成带有 boundary 的请求头,否则后端无法解析。思路:将对象序列化为 JSON 字符串,作为 FormData 的一个普通字段(如 formData.append(‘payload’, JSON.stringify(data))),后端接收该字段后再反序列化。若上传大文件(>10MB),需实现独立的分片上传接口,在提交对话前先获取文件 id 或 url,再随文本发送引用。移除输入框的禁用态;

2402_85729970的博客 388

在Open-WebUI中提升向量化速度

让Open-WebUI AI聊天的向量化过程不超过10秒,而不是默认的20+分钟……

xyzzklk的博客 574

Writeup 4 0xGame 2021 · command (WEB)

前端限制不可信:永远不要相信前端的任何限制(如disabled按钮、JS 验证等)。攻击者可以直接构造 HTTP 数据包绕过前端校验,所有的安全限制必须在后端实现。命令执行/注入(RCE):Web 应用如果直接调用系统命令且未对输入进行严格过滤,攻击者可以利用;||等符号拼接恶意命令。绕过技巧:在 CTF 中,如果遇到命令执行被过滤,常见的绕过方式包括:${IFS}$IFS$9等。。cat /fla?或cat /fl*。Linux 基础。

hengdonghui的博客 131

使用HTML+CSS+JavaScript实现文件上传弹窗

使用HTML+CSS+JavaScript实现文件上传弹窗

bjzhang75的博客 207

ArkWeb 混合开发的内存清理与桥接陷阱

起初我以为是 H5 内部的定时器没有清理,结果接了 DevEco Studio 的 Profiler 一看,全是 ArkTS 侧的原生对象没有释放。改用 RESIZE 后,键盘弹出只会压缩窗口高度,底部的输入框会自适应滚动到可视区域,页面顶部的元素则岿然不动。综上所述,混合开发绝不是简单的拼接,管好桥接的生命周期,做好跨域兜底,才是稳定运行的前提。如果不去主动干预,它会把你的原生内存吃得连骨头都不剩。在 H5 的输入框打字时,软键盘一弹出来,整个 Web 页面就被顶得飞起,连顶部的原生导航栏都不见了。

2502_91284977的博客 235

热工测点布线改造难题?IDCB 远程 I/O 采集前端简化现场布线

IDCB智能数据采集前端基于Modbus-RTU协议,支持热电偶、热电阻、直流信号多类型混采,单设备多通道接入,减少模块选型压力。双总线冗余设计保障数据连续性,适配锅炉、窑炉等高可靠性工况。采用总线式布线替代点对点接线,大幅减少电缆用量,配合组态软件或LCD面板,实现远程监控与现场调试便捷化。适用于脱硫脱硝、就地监控及系统改造项目,具备抗干扰、隔离保护、掉电存参等特性,有效提升热工测点采集系统的稳定性与运维效率。

wxyzzdh200988的博客 192
上一篇: videojs v10 源代码系列解读:32 · Reactor 模型:信号驱动的状态机
下一篇: videojs v10 源代码系列解读:34 · `createComposition`:类型安全的冲突检测
逻辑玩家
博客等级 码龄19年 75粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值