Gutenberg core/video 视频块源码级指南:Attributes 体系、Hybrid 渲染与文本轨道
2026/9/17 6:29:32 网站建设 项目流程

Gutenberg core/video 视频块源码级指南:Attributes 体系、Hybrid 渲染与文本轨道

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

导读

core/video是 Gutenberg(WordPress 块编辑器)中负责视频内容的核心媒体块,允许用户从媒体库嵌入视频或上传新文件。本文以 packages/block-library/src/video/README.md 为主体骨架,结合该目录下block.jsonedit.jsxsave.jsxindex.php等源码实现,系统讲解视频块的全部 13 个属性、支持的编辑器能力(anchor/align/spacing/interactivity)、Hybrid 混合渲染机制、GIF 变体以及字幕/说明等文本轨道(tracks)的完整工作方式。读完本文,你将能基于core/video的既有设计,深入理解并二次开发自定义视频块。


一、块概览:core/video在 Gutenberg 中的定位

根据自动生成的块 API 文档,core/video的核心元信息如下:

项目
块名称(Name)core/video
类别(Category)media(媒体)
API 版本3
块类型Hybrid(混合块):静态保存(static save)+ 服务端增强(server enhancements)
关键词(Keywords)movie
  • API Version 3:块遵循 block.json 元数据规范($schema指向https://schemas.wp.org/trunk/block.json,见 block.json),使用apiVersion: 3register_block_type_from_metadata注册。
  • Hybrid 块:这是理解视频块的关键。它在编辑器中以 React 组件(edit.jsx)编辑,前端保存为静态 HTML 标记(save.jsx),同时在渲染阶段由 PHP 服务端(index.php中的render_block_core_video)对输出进行增强——例如根据附件元数据补充width/heightaspect-ratio样式。这意味着视频块不依赖服务端动态渲染才能显示,静态标记在无 PHP 处理时也能正常播放。

块本身在 index.js 中通过initBlock({ name, metadata, settings })完成注册,settings中定义了图标、示例(一段中央公园画眉鸟歌声的 webm 视频)、transformsvariationsdeprecatededitsave


二、Attributes 完整解析:13 个属性逐一拆解

2.1 属性总表(继承自官方文档)

所有属性均通过 block.json 的attributes字段定义。下表为完整清单:

AttributeTypeDefaultDescription
autoplaybooleanSource:attribute。Selector:video。HTML attr:autoplay
captionrich-textSource:rich-text。Selector:figcaption。Role:content
controlsbooleantrueSource:attribute。Selector:video。HTML attr:controls
idnumberRole:content(媒体库附件 ID)
loopbooleanSource:attribute。Selector:video。HTML attr:loop
mutedbooleanSource:attribute。Selector:video。HTML attr:muted
posterstringSource:attribute。Selector:video。HTML attr:poster(封面图 URL)
preloadstring"metadata"Source:attribute。Selector:video。HTML attr:preload
blobstringRole:local(临时 blob URL,仅存在于编辑会话)
srcstringSource:attribute。Selector:video。HTML attr:src。Role:content
widthnumber视频显示宽度(无 source 映射,纯存储值)
heightnumber视频显示高度(无 source 映射,纯存储值)
playsInlinebooleanSource:attribute。Selector:video。HTML attr:playsinline
tracksarray[]Role:content(WebVTT 文本轨道数组)

注:原文档表格中部分链接指向 block-attributes 文档,本文以 block.json 的实际 JSON 定义为准进行讲解。

2.2 从源码看属性分类:三种取值来源

block.json中的定义归类,属性通过三种机制与保存的 HTML 绑定:

① attribute source(从 HTML 属性取值)——autoplaycontrolsloopmutedposterpreloadsrcplaysInline。它们的解析路径完全一致:

"muted": { "type": "boolean", "source": "attribute", "selector": "video", "attribute": "muted" }

即:编辑器会从<video>元素上读取/写入对应 HTML 属性(autoplaycontrolsloopmutedposterpreloadsrcplaysinline),这些属性在保存时被序列化进静态标记。

② rich-text source(富文本内容)——caption

"caption": { "type": "rich-text", "source": "rich-text", "selector": "figcaption", "role": "content" }

caption对应<figcaption>元素内的富文本,被标记为role: "content",意味着它是块内容的组成部分(参与内容检查、模板锁定等逻辑)。

③ role 驱动的本地/内容属性

  • idnumber,Role:content):媒体库附件的数字 ID,保存时不直接映射为 HTML 属性,而是供服务端渲染与媒体替换流程使用。
  • blobstring,Role:local):本地临时对象 URL。当用户拖拽/上传本地文件时,浏览器生成blob:开头的临时地址,编辑器用Spinner展示上传中的转圈状态,待上传完成后再替换为正式src
  • tracksarray,Role:content,默认[]):WebVTT 文本轨道列表,保存在内容中(详见第六节)。
  • width/heightnumber):纯存储的尺寸数值,没有 source 映射,由编辑器的尺寸处理逻辑写入。

2.3 默认值设计要点

三个属性带有默认值,其余为可选:

  • controls默认true:常规视频默认显示播放控件,符合大多数使用场景;GIF 变体会显式覆盖为false
  • preload默认"metadata":仅预加载元数据而非整个视频,兼顾性能与首屏体验。
  • tracks默认[]:空轨道数组。

三、Supports:视频块支持的编辑器能力

原文档列出的supports配置同样定义在 block.json:

Support配置说明
anchortrue允许为块设置 HTML 锚点 ID,便于站内跳转
aligntrue支持宽对齐、全宽等对齐方式
spacingmargin: true,padding: true支持外边距与内边距控制;__experimentalDefaultControls将两者的默认控件关闭
interactivityclientNavigation: true启用客户端导航(interactivity API 支持),使视频块在无刷新页面导航场景下正常工作

此外,block.json末尾还声明了样式句柄:

"editorStyle": "wp-block-video-editor", "style": "wp-block-video"

前端与编辑器样式分别由 style.scss 与 editor.scss 提供(另有 theme.scss 处理主题化外观)。


四、Block Markup 与 Hybrid 混合渲染机制

4.1 保存的静态标记结构

原文档给出的core/video保存标记范例如下(block comment 形式):

<!-- wp:core/video --> <figure class="wp-block-video"> <video controls src="data:video/mp4;base64,AAAAH…"></video> <figcaption class="wp-element-caption">My video</figcaption> </figure> <!-- /wp:core/video -->

(示例中src使用了一段 base64 编码的极短视频数据,仅为演示属性结构;实际发布内容会使用媒体库的正式 URL。)

标记结构包含三层:

  1. <figure class="wp-block-video">——由useBlockProps.save()生成的根容器,自动带上wp-block-video类名与对齐等类名;
  2. <video>——承载srccontrolsposterpreloadwidthheightautoplayloopmutedplaysinline等媒体属性;
  3. <figcaption class="wp-element-caption">——字幕/说明文本。wp-element-caption类名来自__experimentalGetElementClassName('caption'),是 #41140 PR 引入的全局样式 caption 元素支持(见 deprecated.jsx 中的注释)。

4.2 save.jsx:静态保存逻辑源码剖析

save.jsx 是 Hybrid 块的“静态”半边,关键实现细节:

export default function save( { attributes } ) { const { autoplay, caption, controls, loop, muted, poster, preload, src, playsInline, tracks, width, height } = attributes; // 显式(非 auto)宽高比避免 GIF 转视频时前端出现瞬时布局抖动 const aspectRatio = width && height ? `${ width } / ${ height }` : undefined; return ( <figure { ...useBlockProps.save() }> { src && ( <video autoPlay={ autoplay } controls={ controls } loop={ loop } muted={ muted } poster={ poster } preload={ preload !== 'metadata' ? preload : undefined } src={ src } playsInline={ playsInline } width={ width } height={ height } style={ aspectRatio ? { aspectRatio } : undefined }> <Tracks tracks={ tracks } /> </video> ) } { ! RichText.isEmpty( caption ) && ( <RichText.Content className={ __experimentalGetElementClassName( 'caption' ) } tagName="figcaption" value={ caption } /> ) } </figure> ); }

值得注意的工程细节:

  • src为空则不渲染<video>:占位状态下仅保留<figure>容器。
  • preload的默认值省略preload !== 'metadata' ? preload : undefined——默认值"metadata"不写入标记,保持输出干净。
  • aspect-ratio 样式:这是 6.9.0 起引入的优化。仅设置width/height属性时,CSS 计算出的aspect-ratio: auto W/H在加载期间并不可靠(Chrome 会先算出数万像素的瞬时高度,造成 GIF 转视频切换时的“图像闪烁”与布局偏移),因此在编辑器与保存端都显式输出style="aspect-ratio: W / H;"(详见 save.jsx 与 edit.jsx 的注释)。

4.3 index.php:服务端增强(Hybrid 的“动态”半边)

lib 侧服务端文件 中的render_block_core_video()是服务端增强的入口,职责是从附件元数据补全宽高与宽高比,执行一系列防御性校验:

  1. 内容中无<video标签则直接返回原内容(stripos大小写不敏感);
  2. id属性缺失、非正整数,或对应文章类型不是attachment,则放弃增强;
  3. 调用wp_get_attachment_metadata()取附件元数据,若width/height缺失或非正整数则放弃;
  4. WP_HTML_Tag_Processor定位<video>标签,写入width/height属性;
  5. 计算并写入style="aspect-ratio: W / H;"(前置追加到原有 style 之前)。

PHP 注释中解释了为何不能直接用attr()的 CSS 规则:aspect-ratio: attr(width type(<number>)) / attr(height type(<number>));目前仅 Chromium 实现(CSSWG issue #7524),因此采用服务端写内联样式的方式保证跨浏览器一致。

块的 PHP 注册通过register_block_type_from_metadata(__DIR__ . '/video', ['render_callback' => 'render_block_core_video'])完成,挂在init钩子上(自 WordPress 6.9.0 起生效)。


五、编辑器行为深度剖析:edit.jsx 与设置面板

5.1 三种媒体来源的完整流程

edit.jsx 定义了编辑体验,围绕onSelectVideoonSelectURL两个核心回调展开:

① 上传 / 媒体库选择(onSelectVideo

  • 无有效媒体时清空全部相关属性(srcidpostercaptionblob);
  • 若 URL 是blob:临时地址(isBlobURL),仅设置temporaryURL并显示Spinner,实际上传由useUploadMediaFromBlobURLHook 完成(限定allowedTypes: ['video']),上传成功后再触发onSelectVideo
  • 正式媒体则写入srcidposter(封面取media.image?.src,若与图标相同则置空)、caption

② 直接输入 URL(onSelectURL

  • prependHTTPS补齐协议头;
  • 调用createUpgradedEmbedBlock检查该 URL 是否可升级为嵌入块(Embed 块),若是则调用onReplace直接替换为嵌入块,否则作为普通视频 URL 写入src

③ 占位状态:当srctemporaryURL均为空时,渲染MediaPlaceholderaccept="video/*"allowedTypes={['video']}),提示语为 "Drag and drop a video, upload, or choose from your library."

选中状态下,工具栏(BlockControls)提供Text tracks(文本轨道编辑,见第六节)与MediaReplaceFlow(替换媒体,支持选择/上传/URL/重置四种操作,variant="toolbar")。

5.2 设置面板(InspectorControls)

常规视频(非 GIF 变体)的侧栏设置面板基于ToolsPanel构建,resetAll将属性恢复为:autoplay: falsecontrols: trueloop: falsemuted: falseplaysInline: falsepreload: 'metadata'poster: undefined

面板内各控件(见 edit-common-settings.jsx)及其联动逻辑:

控件默认显示关键行为
Autoplay开启自动播放时强制联动muted: trueplaysInline: true(后者为支持 iOS 内联播放);关闭时同步muted: false;帮助文案提示“自动播放可能对部分用户造成可用性问题”
Loop切换loop
Mutedautoplay开启时控件被禁用并提示 "Muted because of Autoplay."
Playback controls切换controls
Play inlineautoplay开启时禁用并提示 "Play inline enabled because of Autoplay.";否则解释在移动浏览器上网页内播放、不进入全屏
PreloadSelectControl,选项为auto(Auto)/metadata(Metadata)/none(None);仅当值非metadata时视为“有值”

此外面板还包含PosterImage封面图设置,将选择的封面 URL 写入poster

编辑器内播放体验:编辑态<video>仅应用controlsposter;未选中时设置inert="true"阻止交互。aspectRatio逻辑与 save 端一致,保证编辑与前端行为统一。useEffectposter变化时调用videoPlayer.current.load()刷新预览。


六、GIF 变体:animated GIF 的自动视频化

core/video通过 variations.js 定义了两种变体:

export const isGifVariation = ( { controls, loop, autoplay, muted, playsInline } = {} ) => ! controls && !! loop && !! autoplay && !! muted && !! playsInline;
  • video 变体:常规视频,attributes: { controls: true }isActive!isGifVariation(...);不直接出现在插入器中(scope: ['block', 'transform']),用于标识普通视频或把 GIF 变体切回常规视频。
  • gif 变体:描述“像动图一样自动播放的静音循环视频”,属性组合为controls: false, loop: true, autoplay: true, muted: true, playsInline: true,关键词含animatedgif

工作机制:用户在编辑器中上传的 animated GIF 会被转换为视频(参考 docs/how-to-guides/client-side-media.md 所述的客户端媒体处理管线),并以gif变体属性呈现,从而在行为上完全还原 GIF 的动图效果。编辑态下,edit.jsx检测isGifVariation后:

  • 对预览<video>应用autoPlay/loop/muted/playsInline(浏览器允许程序化播放静音视频),并在源/封面变化后主动调用videoPlayer.current?.play()
  • 隐藏 InspectorControls 中的常规设置面板(GIF 变体无需用户干预)。

七、Transforms:三种来源向视频块的转换

transforms.js 定义了从三类输入转换为core/video的规则:

  1. 文件(files):单个video/*类型文件被拖入编辑器时,通过createBlobURL(file)生成临时 blob 地址存入blob属性,实际上传交由块的挂载逻辑完成。
  2. 短代码(shortcode):兼容传统[video]短代码,映射src(依次回退src/mp4/m4v/webm/ogv/flv命名参数)、posterloopautoplaypreload
  3. 原始 HTML(raw):当粘贴内容为<p><video …></video></p>结构时,提取autoplaycontrolsloopmutedpreloadplaysinlinepostersrc;若src是 blob URL 则转入blob属性。

八、文本轨道(Tracks):字幕、说明、章节的完整编辑器支持

tracks属性配合 tracks.jsx 与 tracks-editor.jsx 实现 WebVTT 文本轨道的添加与管理,是视频块在无障碍(a11y)与多语言场景下的核心能力。

保存端Tracks组件将每个轨道对象渲染为<track>子元素(keyid ?? src),保留除id外的全部属性:

export default function Tracks( { tracks = [] } ) { return tracks.map( ( track ) => { const { id, ...trackAttrs } = track; return <track key={ id ?? trackAttrs.src } { ...trackAttrs } />; } ); }

编辑端TracksEditor,通过工具栏 “Text tracks” 按钮打开 Dropdown):

  • 添加来源:媒体库选择(MediaUploadallowedTypes: ['text/vtt'],支持多选)或本地上传(FormFileUploadaccept=".vtt,text/vtt")。已存在的轨道按id复用,保留用户配置的元数据。
  • 轨道默认结构{ src: '', label: '', srcLang: 'en', kind: 'subtitles', default: false },其中kind可选subtitles(字幕)/captions(说明)/descriptions(描述)/chapters(章节)/metadata(元数据)。
  • 编辑单条轨道:可修改 Label(标题)、Source language(语言标签,如enfr)、Kind、是否设为默认轨道(default);移除轨道与 “Apply” 确认。系统会保证同时只存在一个默认轨道(allowSettingDefault逻辑)。

九、向后兼容:deprecated 版本

deprecated.jsx 中保留了一个v1历史版本,用于自动迁移旧内容。其与当前 save 的差异正是wp-element-caption类名的引入(#41140 为全局样式 caption 元素增加了该类名,见文件头部注释)。旧版本保存的figcaption不带该类名,因此需要 deprecation 机制在用户重新保存时升级标记。


十、实操速查:常见使用方式与验证路径

在编辑器中使用:在块插入器搜索 “Video”(或 “movie” 关键词)→ 拖拽/上传视频、从媒体库选择,或直接粘贴视频 URL(可识别可升级为嵌入块的链接)→ 在侧栏调整 Autoplay/Loop/Muted/Playback controls/Play inline/Preload 与封面图 → 通过工具栏 “Text tracks” 添加字幕与说明。

手动编写块标记(可直接粘贴到代码编辑器或作为模板参考):

<!-- wp:core/video {"id":123,"loop":true,"muted":true} --> <figure class="wp-block-video"><video src="https://example.com/video.mp4" loop muted width="1280" height="720" style="aspect-ratio: 1280 / 720;"></video><figcaption class="wp-element-caption">产品演示视频</figcaption></figure> <!-- /wp:core/video -->

深入验证的源码路径

  • 属性与支持定义:block.json
  • 编辑组件:edit.jsx、edit-common-settings.jsx
  • 保存组件:save.jsx、deprecated.jsx
  • 服务端渲染:index.php
  • 变体与转换:variations.js、transforms.js
  • 文本轨道:tracks.jsx、tracks-editor.jsx
  • 变体测试:test/variations.js

面向二次开发者的要点:若需基于core/video构建自定义视频块,应保持attributes的 source/role 分层设计(attribute 直出、content 参与序列化、local 仅存临时态)、在save端输出显式aspect-ratio以规避加载抖动,并复用Tracks/TracksEditor以低成本获得无障碍字幕能力。

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询