videojs v10 源代码系列解读:18 · 媒体轨道与 rendition 列表实现

【python】epub的电子书繁体字与简体字转换 中文繁体与简体转换 阅读详情

卷三收尾篇。这篇讲 media/src/core/media-tracks/ 目录——v10 怎么在浏览器原生不支持的地方,polyfill 出音频轨道、视频轨道、音频 rendition、视频 rendition(清晰度)列表。这套实现有几个让我印象深刻的细节:用 WeakRef 反向引用宿主、用 queueMicrotask 做事件防抖、用 generator 实现 [Symbol.iterator]。

为什么需要 polyfill

浏览器对媒体轨道的支持参差不齐:

  • Safari 有原生 audioTracks/videoTracks(带 rendition)。
  • Chrome/Firefox 长期没有(或部分)。
  • hls.js/dash.js 自己管理轨道,不走原生 API。

v10 需要一套统一的轨道抽象(13 篇讲的 AudioTrackLike/VideoTrackLike/*RenditionListLike),在原生不支持时用 polyfill 填充。media-tracks/ 就是这套 polyfill 的具体实现类。

Track 类:AudioTrack 和 VideoTrack

AudioTrack(audio-track.ts)

// audio-track.ts:14-45 简化
export class AudioTrack {
  id; kind; label = ''; language = ''; sourceBuffer;
  #enabled = false;

  addRendition(src, codec?, bitrate?) {
    const rendition = new AudioRendition();
    // 赋值 src/codec/bitrate
    addRendition(this, rendition);   // 挂到 list
    return rendition;
  }

  get enabled() { return this.#enabled; }
  set enabled(value) {
    if (this.#enabled !== value) {
      this.#enabled = value;
      enabledChanged(this);    // 触发 list 事件
    }
  }
}

关键字段:id(可写)、kind(只读,alternative/descriptions/main/'main-desc'/translation/commentary,L5-12)、enabled(可写,选轨入口)。

enabled 的 setter 在值真改变时才调 enabledChanged(this)——触发 list 的 change 事件。这个「值变了才通知」的模式在 v10 里到处都是(element 的 Object.is 判变、store 的 patch 判变)。

VideoTrack(video-track.ts)

结构类似 AudioTrack,但有两个关键差异:

  1. 用 #selected 而非 #enabled(video-track.ts:20)。
  2. setter(L42-49)只在变 true 时才触发 selectedChanged(L46 的 if (value !== true) return)——隐式实现了 video track 的「同时只能选一个」互斥语义。

addRendition 签名更宽(L22):(src, width?, height?, codec?, bitrate?, frameRate?)——视频 rendition 有尺寸和帧率。

kind 集合不同

我注意到 AudioTrackKind 和 VideoTrackKind 的值集不一样:

  • Audio: alternative, descriptions, main, 'main-desc', translation, commentary
  • Video: alternative, captions, main, sign, subtitles, commentary

这忠实反映了 HTML 规范——音视频轨道的 kind 语义本就不同。

Rendition 类:清晰度/编码变体

AudioRendition(audio-rendition.ts)

export class AudioRendition {
  src; id; bitrate; codec;   // 都 | undefined
  #selected;
  // selected setter 值变时调 selectedChanged(this)
}

字段简单——音频 rendition 主要是 bitrate 和 codec。

VideoRendition(video-rendition.ts)

比 audio 多 width/height/frameRate(L10-13),以及双私有状态#selected 和 #active(L15-16)。

这俩的区别很重要:

  • selected——用户/上层指定「想播这个」。
  • active——引擎实际正在播这个(由 ABR 算法决定)。

对应 types.ts 的 VideoRenditionLike.active?。ADR 算法可能因为带宽选了比 selected 更低的 rendition,active 反映实际选择。UI 的「当前清晰度」应该读 active 而非 selected。

List 类:基于 EventTarget 的类数组容器

AudioRenditionList(audio-rendition-list.ts,143 行)

这是最有料的。它 extends EventTarget,但内部逻辑大量是模块级自由函数(不在 class 里)。

addRendition(track, rendition)(L7-30):

// 简化
const list = getPrivate(track).media?.deref()?.audioRenditions;  // L7 — WeakRef 反查 list
// 设 rendition 的 media/track 私有指针
renditionSet.add(rendition);
// 必要时在原型上 Object.defineProperty 添加数字索引 getter(L17-23)
queueMicrotask(() => {
  if (track.enabled) list.dispatchEvent(new TrackEvent('addrendition', rendition));
});

几个精妙点:

  1. getPrivate(track).media?.deref()——通过 WeakRef 从 track 反查到 media 元素的 list。track 不强引用 media,避免循环引用。
  2. Object.defineProperty 添加数字索引(L17-23)——动态给 list 加 [0]/[1]… 的 getter,让它像数组。因为 rendition 是动态加的,不能预先定义。
  3. queueMicrotask 派发事件(仅当 track.enabled)——批量操作时合并事件。

selectedChanged(rendition)(L45-60)——事件防抖:

// 简化
if (!getPrivate(list).changeRequested) {
  getPrivate(list).changeRequested = true;
  queueMicrotask(() => {
    getPrivate(list).changeRequested = false;
    list.dispatchEvent(new Event('change'));
  });
}

一 tick 内多次 selected 变化只派发一次 change。这和 store 的微任务批处理(11 篇)是同一思想——高频变化合并成一次通知。

getCurrentRenditions(list)(L62-68):从 media 取 audioTracks,filter enabled,flatMap 出每个 enabled track 的 renditionSet——即 rendition list 是「所有启用轨道的 rendition 并集」。

class 本身(L70-142)提供:数字索引签名、[Symbol.iterator](返回 getCurrentRenditions(this).values())、get length、getRenditionById、get/set selectedIndex(set 时遍历设 rendition.selected = i === index)、onaddrendition/onremoverendition/onchange 的 get/set。

on* 回调的 setter(L98-141)每次先 removeEventListener 旧 callback 再 addEventListener 新的——防止重复注册。

VideoRenditionList(video-rendition-list.ts,159 行)

结构几乎和 Audio 版相同,三个差异:

  1. 用 track.selected 判定(非 enabled)。
  2. 多一个 activeChanged(rendition) 函数(L62-76),防抖派发 activechange 事件——对应 ABR 算法的实际选择变化。
  3. getCurrentRenditions filter track.selected。

activechange 是视频 rendition list 独有的事件——音频 rendition 没有「active」概念(音频 ABR 不暴露给 UI)。

WeakRef + 私有存储:避免循环引用

这套实现有个贯穿性的设计:用 WeakRef 让 track/rendition 反向引用 media,不形成强引用环。

utils.ts 的 getPrivate 用 WeakMap 给对象挂 media/track/renditionSet 等私有字段。media 字段是 WeakRef<HTMLMediaElement>——track 不阻止 media 被 GC。media 被回收时,deref() 返回 undefined,操作安全降级。

这解决了「track 属于 media,但 track 要触发 media 上的 list 事件」的循环引用难题。经典前端工程问题,v10 用 WeakRef 干净解决。

queueMicrotask 事件防抖

另一个贯穿性设计:用 queueMicrotask 合并高频事件。

  • addRendition 批量添加时,事件延迟到微任务统一派发。
  • selectedChanged 一 tick 内多次变化只派发一次 change。
  • activeChanged 同理。

这和 store 的跨容器批处理(11 篇)、element 的更新去重(09 篇)是同一套思想——高频变化合并通知。v10 在三个不同的包里用了三种不同的批处理机制,但核心理念一致:减少不必要的通知/渲染。

global.ts:polyfill 注册

index.ts 第一行 import './global'——有副作用。global.ts(803 字节)往全局注册 polyfill,让没有原生 audioTracks/videoTracks 的浏览器也能用。mixin.ts(8677 字节,目录里最大的)大概率是 mixinMediaTracks(Media),把轨道能力注入到 media 对象。

小结:卷三全貌

至此卷三·媒体契约层讲完。回顾 6 篇:

  • 13 能力契约——正交分解,每个 Capability 只管一件事。
  • 14 谓词守卫——运行时安全探测,复合谓词排除空哨兵。
  • 15 主机-组件模型——host 不持有状态,getMediaOwner 路由组件覆盖。
  • 16 custom-media-element——两层属性转发,包装成 Web Component。
  • 17 引擎适配器——Host-subclass(全程接管)vs Component/override(条件接管)。
  • 18 媒体轨道 polyfill——WeakRef 反引用 + queueMicrotask 防抖。

这套设计的核心成就:用一套类型系统,描述了从最全的原生 <video> 到最异质的 Vimeo iframe、再到动态切换的 Google Cast。Feature(卷四)靠谓词安全降级,引擎靠两种模式接入,轨道靠 polyfill 统一。这就是 v10 相比 v8 「tech 注册表」的根本进步。

从 Junior 到 Lead:ABAP 开发者进阶路线图与真实项目练级法 本文拆解了ABAP工程师从初级到高级的成长路径,强调能力提升依赖于可复用经验的积累。对于初级开发者,建议夯实ABAP Dictionary、内表处理和数据库思维三大基础,培养数据流与规则层的结构化思维,并逐步掌握面向对象编程。中级阶段应注重代码可维护性,通过单元测试和Clean ABAP规范提升工程质量。文章指出,ABAP开发者需要学会筛选学习重点,建立知识地图,并重视团队协作中的代码可读性。关键在于将碎片知识整合为可迁移的模型,而非盲目追求新技术。 阅读详情

相关推荐

【Unity报错】Unity导入海康SDK 报错 DllNotFoundException: PlayCtrl assembly

2.尝试按网上其他的办法(包括使用depengs查看dll依赖等)1.先检查Plugins文件夹中是否存在PlayCtrl文件。3.如果网上查阅的办法都不能解决,请继续往下看。更换低版本的SDK库文件。

weixin_42968584的博客 1126

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 206

轴承故障诊断——领域知识

幅域分析、频域分析及轴承方面的领域知识

qq_58516607的博客 3532

从一段视频到可漫游的 4D 有声场景:思路拆解与最小复现手记

只需一段手机视频,你就能生成可"走进去"的 4D 有声场景:转头时狗叫声方向随之变化,走近时声音更清晰。本文拆解 Video-to-4DAVScene 的核心思路,手把手带你用几十行 Python 搭出最小管线,把视频中的运动物体变成带空间位置的声源,并附上三个真实踩坑的排障经验,代码可直接跑。🎧

helloagent的博客 234

手把手教你用scRNA-seq和scTCR-seq分析CD8⁺ T细胞在免疫治疗中的动态变化

本文详细介绍了如何整合单细胞RNA测序(scRNA-seq)与单细胞TCR测序(scTCR-seq)技术,深入解析CD8⁺ T细胞在癌症免疫治疗中的动态变化。通过从数据预处理、细胞亚群鉴定到TCR克隆追踪的完整分析流程,揭示了T细胞的功能状态转变与克隆演化规律,为理解免疫应答机制和开发精准治疗策略提供了关键方法学指导。

p8q9r0的博客 566

如何在OBS中添加实时时间戳:Lua脚本配置教程(附效果展示)

本文详细介绍了如何在OBS中通过Lua脚本配置实时时间戳功能,包括环境准备、脚本获取、安装配置及高级定制。适用于直播和视频录制场景,提供精准回溯和风格自定义,支持多平台适配和性能优化,是专业制作的必备技巧。

day7的博客 1044

本地化部署会议视频软件如何替换旧平台?账号迁移、历史数据与用户培训怎么安排?

账号先映射:身份与权限验证通过,再开放使用。资料分级处理:能查、能读、权限正确,比“全部搬完”更重要。切换可恢复:入口、增量数据和业务通知都要纳入回退方案。培训按岗位落地:让用户完成真实任务,而不是只听功能介绍。这套方法适合政企、集团及医疗等具有长期资料留存、多终端接入和业务集成需求的组织。小规模替换可以简化批次与流程,但不应省略权限验证、备份恢复和关键会议演练。

hz56789的博客 281

实战交易策略 篇二十二:情绪流龙头交易策略

在股票市场中,机构主导趋势,游资驱动热点,散户易被情绪裹挟,形成“金字塔”式生态链,并存在情绪传递、强者恒强、物极必反的规律特点。股市是资金驱动的情绪博弈场,价格波动由群体心理、资金博弈和预期差共同驱动,核心是资本逐利性与人性贪婪恐惧的交织,兼具资源配置、财富再分配与风险定价功能。涨停加速与逃逸缺口(主升强化)凹字板/平台突破(趋势延续)天量弱转强(分歧买点)不参与首波(二波策略)情绪周期(道术合一)主线思维(聚焦核心)开盘抢筹(竞价博弈)一字助攻(情绪强化)分批进出(滚动操作)

生活在别处 1487

打字就能剪视频的AI工具

AI 会替代剪辑师吗?这个问题和“AI 会替代程序员吗”一样,问错了方向。会用 AI 工具的人,正在替代不会用的人。一个剪辑师用传统方式花三天做的宣传片,另一个人用 UniCut 一天做完,质量差不多,市场会选谁,答案很明显。工具的进化从来不是把专业的人淘汰掉,而是把专业的门槛拆掉。浏览器已经打开了,剩下的就是你愿不愿意试一下。体验地址:https://unicut.h5ds.com/开源仓库:https://github.com/mtsee/unicut。

d676015863的博客 157

Python 爬虫实战:知网论文数据爬取(题录 / 摘要 / 引用提取 + Excel 结构化)

在学术研究中,获取准确且全面的文献数据是至关重要的。知网(CNKI)作为国内最大的学术文献数据库,拥有海量的论文资源。通过 Python 爬虫技术,我们可以高效地从知网爬取论文数据,包括题录、摘要和引用信息,并将这些数据结构化存储到 Excel 文件中,方便后续的学术分析和研究。

yansideyucsdn的博客 1749

矢量网络分析仪校准:原理、方法与系统适配性

矢量网络分析仪(VNA)校准是射频测量的关键环节,通过误差建模(12项误差项)和标准件测量,可将系统不确定度从±5dB降至±0.1dB以下。主流校准方法包括SOLT(适用于同轴系统)和TRL(适用于波导系统),二者在标准件、误差重点及频率上限等方面存在显著差异。随着6G与量子通信的发展,动态实时校准将成为新趋势。工程师需根据传输结构、频率范围及精度需求选择合适方法,确保测量精度。

u014344410的博客 262

音频自动匹配歌词:本地音乐库元数据维护实践

实施顺序建议为:建立主库、统一命名、批量匹配、人工校验、权限分享、定期备份。工具选择上,SMB/WebDAV、Navidrome、Jellyfin 以及轻量文件管理服务各有适用场景,应结合访问方式、权限需求和维护成本评估。把文件组织好、把批量操作控制住、把备份习惯建立起来,歌词补全才能真正提升本地音乐库的可用性,而不是带来新的整理负担。音乐文件不常修改,但歌词、封面、播放列表和目录结构属于人工整理成果,丢失后恢复成本较高。更合理的顺序是:集中存放、统一命名、批量匹配、人工校验、权限管理、定期备份。

zxcvb153的博客 116

中国国家级地面气象站基本气象要素日值数据集(V3.0)

气温数据TEM, 包括站点编号(sid), 纬度(lat), 经度(long), 高程(elev), 年(year), 月(month),日(day), 平均气温(tmean), 最高气温(tmax), 最低气温(tmin)气压数据PRS, 包括站点编号(sid), 纬度(lat), 经度(long), 高程(elev), 年(year), 月(month),日(day), 平均气压(pmean), 最高气压(pmax), 最低气压(pmin)中国国家级地面气象站基本气象要素日值数据集(V3.0)

J_Giser的博客 3895

视频美颜sdk的API设计会影响开发效率吗?

视频美颜SDK不仅需要具备优秀的图像处理能力,API接口设计同样会影响软件开发效率。本文从接口调用、参数配置、版本兼容、开发文档以及业务扩展等多个角度,分析API设计对视频美颜SDK集成和后期维护的实际影响,为直播APP、视频社交平台等项目的SDK选型与技术开发提供参考。

wanyuekeji的博客 211

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

视频号数据怎么采?接入方式、字段范围与场景适配

视频号数据采集的技术难点不在“调哪个接口”,而在。官方API服务的是“经营与交易”闭环,返回的是直播记录、订单、售后等结构化实体,但播放完成率、互动明细、评论区内容这些内容分析赖以生存的字段,并不在官方接口的返回Schema里。这意味着任何技术方案的选择,本质上是。

城章科技 297

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

AI 礼盒开箱视频怎么做?让商品亮相更有仪式感

AI商品视频通过精细设计开箱动作与场景节奏,将礼盒从静态包装转化为沉浸式送礼体验。从暖光布景、情感化构图到手部停顿、商品细节特写,每一帧都传递“精致”与“珍视”。以珠宝礼盒为例,俯拍视角下,红色对开门展开如舞台揭幕,银色项链在深蓝夜空衬底中缓缓呈现,掌心承托、缓慢转动,强化视觉记忆。结尾平铺构图,礼盒与商品共存,情绪由期待落至静谧珍藏。全程无文字,靠画面叙事,实现仪式感与品牌调性的深度融合。

yunhhhhh的博客 115

本地化部署会议视频软件如何开展试点?试用范围、评估指标与推广步骤

试用范围覆盖真实差异,评估指标具有明确口径,推广过程具备放行和回退机制。对于政企、金融、医疗及信创项目,尤其要避免三个误区:把本地部署等同于合规,把演示并发等同于生产容量,把功能清单等同于可运维能力。如果正在准备试点,建议先整理一张“网络—终端—业务—故障”矩阵,再决定试用人数。

hz56789的博客 320

RN鸿蒙空间音频实战

示例仓库:https://atomgit.com/m0_37170006/react-native-ohos-spatial-audio 社区导引:框架源码与版本发布见 https://atomgit.com/CPF-RN/ohos_react_native/tree/0.84-main CPF-RN 鸿蒙社区:https://atomgit.com/CPF-rn。

buhuisuanfa的博客 2万+

通过 AIGC 生成视频何时才能告别“抽卡”!

如果视频的主体内容已经符合要求,只存在错误字幕或局部画面瑕疵时,重新生成不仅增加成本,还可能改变原本满意的部分。针对这类问题,WAND-EraseVibe+ 提供了视频擦除与画面重建能力。根据腾讯云披露的技术方案,该工具采用基于隐空间 Transformer 的生成式修复架构,先将视频画面编码为隐空间特征,在特征层推断并重建需要修复的区域,再解码为视频画面。白模前置、垂直场景调优和局部修复分别作用于不同环节,目的都是减少为了获得可用内容而付出的重复生成成本。

Enweitech Software Works 147

网页视频资源识别与本地化管理:从 HTTP 流媒体技术到完整的视频工作流

现代网页视频技术已经从简单的文件传输发展到分段传输、自适应码率和浏览器端媒体处理。这使视频播放体验不断改善,也让资源识别和本地管理变得更加复杂。对于技术人员而言,理解 HTTP、HLS、MPEG-DASH 和 MSE 的基本工作机制,有助于更准确地分析网页视频的传输过程。对于视频创作者和研究人员而言,建立从内容发现、资源识别到本地整理的完整工作流,可能比单纯寻找一个下载工具更有长期价值。

m0_68263549的博客 408

联犀 Go SIMD 实战:视频转码从 16.5ms 到 5.46ms

联犀Go视频转码实战:在352×288测试流中单帧单核CPU耗时从16.5ms到5.46ms,区分SIMD、代码及编码策略的综合收益。保留测试条件、压测结果与适用边界。

QQ603785348的博客 333

15. 调用ComfyUI生成视频!

在“导演大师”中,我们不仅支持导出分镜导演包并一键导入运行,还为用户提供了极高的自定义自由度。许多创作者希望结合自己精心调试的 MiniMax H3 工作流来生成视频,这当然是完全支持的。通常有两种操作方式:一种是手动复制,将分镜的资产与提示词手动粘贴至本地工作流中;另一种则是更为高效的自动化方案——直接在“导演大师”中调用 ComfyUI 工作流,实现一键生成。本文将重点介绍后者的配置与使用全流程,帮助你打通从分镜脚本到视频直出的自动化链路。

2601_95544990的博客 238

AI智能美妆如何适应不同面部特征?视频美颜SDK技术解析

AI智能美妆正在推动视频美颜技术向个性化方向发展。面对不同用户的脸型、眼型、唇形及肤色差异,视频美颜SDK如何通过人脸检测、关键点识别、动态追踪和实时渲染实现精准适配?本文从核心技术原理、不同面部特征的妆容适配方式,以及实际应用场景等方面展开解析,帮助开发者了解AI智能美妆的技术实现与发展趋势。

q1031691172的博客 357

面向强噪声工业场景的 KL‑2510 音频 DSP 模组设计与多场景落地分析

KL-2510是一款22×16mm邮票孔SMT封装音频模组,集成ADC/DAC、AI-ENC降噪(45–90dB)与AEC回声消除(100dB),支持USB免驱及模拟/PDM麦克风输入,具备4档硬件拾音增益,适配医疗、矿山、安防等复杂噪声场景。通过五类真实案例验证其在病房对讲、井下报警、门铃对讲等应用中的稳定性与易用性。重点提示:需接入AEC_IN参考信号、输出加分压电路、外设勿接3V3电源,避免烧毁。适用于空间紧凑、无算法团队的嵌入式项目,显著降低音频开发门槛。

R190_6589的博客 391

Gemini Omni 1.2 Flash发布:视频10秒变15秒、720p降价30%

发布日期:2026-11-06Gemini Omni 1.2 Flash是Google于2026年11月发布的视频生成模型,支持原生15秒视频、多轮对话编辑和更强的参考素材遵循。Google公告发布于北京时间11月6日凌晨,官网标注日期为11月5日。相比Omni 1.1,新版把最长片段从10秒延长至15秒,720p视频单价降至每秒0.07美元,降幅30%。这次更新还涉及生成之后的修改:换背景、调光线、替换产品,可以围绕同一条视频继续提出要求。

aidoudoulong的博客 410

实时互动、直播、点播:音视频SDK选型的技术逻辑

在远程办公、在线教育、文娱电商、政务民生等数字化业务中,音视频能力已经成为多数互联网应用的基础设施。行业内目前形成了实时互动、直播、点播三种主流业务形态,三者在技术架构、传输逻辑与技术指标上差异明显。对研发团队和技术决策者来说,先分清业务属于哪种形态,再据此匹配音视频SDK与传输方案,可以直接影响研发周期、开发成本和终端体验。本文拆解三类业务形态的技术特征、核心指标与选型逻辑,并补充相关的传输原理,供选型时参考。## 一、实时互动:低延迟双向交互的技术体系实时互动的本质,是在双方或多方之间建立低延迟、高稳定

YWamy的博客 146

直播上课+课后回放,音视频流媒体直播/点播系统EasyDSS直播/点播帮健身房搭建线上健身

助力场馆打造轻量化、可复用的线上健身教学资源。

EasyDSS官方技术博客 183
上一篇: ZLMediaKit 前端播放器怎么选?xgplayer / DPlayer / ckplayer / ZWPlayer 横向对比
下一篇: videojs v10 源代码系列解读:19 · Feature 即 Slice:播放器的能力组装机制
逻辑玩家
博客等级 码龄19年 75粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值