2026/9/20 1:49:06

Bilibili-Evolved 快捷键扩展实战:剖析“开关灯“插件从注册到触发播放器灯光的完整链路

Bilibili-Evolved 快捷键扩展实战:剖析“开关灯“插件从注册到触发播放器灯光的完整链路 前端音视频【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved点击查看免费下载本篇技术指南以 Bilibili-Evolved 仓库中的快捷键扩展插件 keymap-toggle-player-light 为切入点深入讲解该插件如何在快捷键扩展keymap组件的动作列表中添加一个开关灯动作以及该动作如何经由播放器适配层最终切换 B 站播放器的灯光模式。读完本文你将掌握 Bilibili-Evolved 中插件注册快捷键动作 预设默认键位的完整机制并能举一反三为自己的功能扩展编写同类插件。插件文档与插件本体该插件的说明文档 index.md 非常简短只有一句话在快捷键的动作列表里添加一个 开关灯。这寥寥数语描述的其实是一个完整的插件式扩展案例它不修改 keymap 组件的任何源码而是通过 Bilibili-Evolved 的插件数据总线addData向快捷键扩展组件动态注册一个新的动作条目并为其配置默认快捷键。插件的全部实现都在 index.ts 中全篇约 20 行结构清晰import { PluginMetadata } from /plugins/plugin import { toggleLight } from /components/video/player-light import type { KeyBindingAction } from ../../../components/utils/keymap/bindings export const plugin: PluginMetadata { name: keymap.actions.togglePlayerLight, displayName: 快捷键扩展 - 开关灯, setup: ({ addData }) { addData(keymap.actions, (actions: Recordstring, KeyBindingAction) { actions.togglePlayerLight { displayName: 开关灯, run: async () { toggleLight() }, } }) addData(keymap.presets, (presetBase: Recordstring, string) { presetBase.togglePlayerLight shift l }) }, }从源码结构可以看到这是一个标准插件PluginMetadata的完整形态namekeymap.actions.togglePlayerLight是插件在注册表中的唯一标识displayName快捷键扩展 - 开关灯展示在用户组件的插件管理界面中setup接收addData函数向两个数据槽data slot注入内容。数据槽机制插件如何接管组件的内部数据理解这个插件首先要理解addData与registerAndGetData这对配套机制。在 Bilibili-Evolved 中组件可以通过 registerAndGetData 声明可被插件扩展的数据槽插件则通过addData向这些槽位追加数据。在 keymap 组件中共有两个与本文相关的数据槽keymap.actions承载动作集合Recordstring, KeyBindingAction。keymap 组件在 actions.ts 中通过registerAndGetData(keymap.actions, builtInActions)注册内置动作如全屏、宽屏、静音、投币、收藏、暂停/播放等插件即可向该集合追加自己的动作。keymap.presets承载预设键位。在 presets.ts 中通过registerAndGetData(keymap.presets, presetBase, builtInPresets)注册默认键位表与内置预设Default、YouTube、HTML5Player、PotPlayer。插件keymap-toggle-player-light正是向这两个槽位各注入一份数据向keymap.actions追加togglePlayerLight动作其displayName为开关灯run回调直接调用播放器灯光切换函数向keymap.presets的presetBase追加默认键位togglePlayerLight shift l即默认按下Shift L即可开关灯也可在设置中修改见下文。这种设计的好处在于插件与组件完全解耦keymap 组件本身并不知道开关灯动作的存在两者通过数据总线松耦合连接插件可以独立启用/禁用且不影响组件主体。动作执行的底层链路从快捷键到播放器灯光动作的run回调只有一行toggleLight()它来自 src/components/video/player-light.ts。该文件对外导出三个函数export const lightOn setLight(true) export const lightOff setLight(false) export const toggleLight setLight()setLight工厂函数做了两件事页面匹配检查通过playerUrls.some(url matchUrlPattern(url))判断当前页面是否为播放器页面非播放器页面直接返回空值不触发惰性加载设置面板并切换灯光在播放器页面中先调用loadLazyPlayerSettingsPanel(buttons.settings.selector, settings.wrap.selector)确保播放器设置面板资源已就绪再调用playerAgentInstance.toggleLight(on)执行实际切换。其中toggleLight未传参数表示无指定参数时直接翻转当前状态。再往下灯光切换的真正执行者是播放器 Agent 的 toggleLight 方法/** true 开灯false 关灯 */ async toggleLight(on?: boolean) { if (!this.nativeApi) { return null } const isCurrentLightOff this.nativeApi.getLightOff() // 无指定参数, 直接 toggle if (on undefined) { this.nativeApi.setLightOff(!isCurrentLightOff) return !isCurrentLightOff } // 关灯状态 要开灯 - 开灯 if (on isCurrentLightOff) { this.nativeApi.setLightOff(false) return true } if (!on !isCurrentLightOff) { this.nativeApi.setLightOff(true) return false } // ... }这里体现了完整的三层调用链快捷键 ShiftL 按下 → keymap 动作 togglePlayerLight.run() → player-light.ts 的 toggleLight()页面匹配 惰性加载设置面板 → playerAgent.toggleLight(on)无参即翻转 → nativeApi.getLightOff() / setLightOff()读写 B 站原生播放器灯光状态需要特别说明的是playerAgent是适配了 B 站多版本播放器的统一代理见 src/components/video/player-agent/nativeApi会随播放器版本如 v2/v3/v4、BPX解析出对应的原生接口。因此插件无需关心播放器内部实现差异统一通过playerAgent这一抽象层操作即可。快捷键触发与按键匹配机制动作注册后如何被按出来这由 keymap 组件的 bindings.ts 负责。其核心逻辑如下KeyBindingAction接口定义了动作的结构displayName动作显示名、run执行函数、prevent是否阻止默认行为、ignoreTyping是否在打字时忽略等loadKeyBindings在document.body与所有被观察的 shadow DOM 上以capture: true方式监听keydown每次按键事件会依次经过多道过滤是否启用、打字状态忽略默认ignoreTyping ! false时跳过、聚焦元素判断允许播放器控制按钮、设置项输入框等场景下继续响应、全景视频禁用 WASD修饰键匹配支持可选修饰键语法binding.keys中写[shift]表示该修饰键按或不按均可见 bindings.ts 的optionalModifyKey处理主键匹配同时支持e.key按键字符与e.code物理按键码例如l与L、方向键arrowUp等均能正确命中动作执行后若返回非空值或显式声明prevent: true则调用stopImmediatePropagation()与preventDefault()阻止页面默认行为如按空格暂停播放等场景。插件注册的togglePlayerLight动作未设置prevent与ignoreTyping因此行为为默认按键在打字时被忽略匹配成功且动作返回非空值时阻止默认事件。默认键位、预设与自定义键位keymap 组件的预设系统分三层合并见 presets.ts 与 index.ts最终键位 presetBase基础默认 ⊕ presets[preset]用户选中的预设如 Default / YouTube / HTML5Player / PotPlayer ⊕ settings.options.customKeyBindings用户自定义键位插件向presetBase注入的shift l属于第一层意味着默认情况下Shift L即可开关灯若用户切换到 YouTube 等预设且预设中覆盖了togglePlayerLight则以预设值为准若用户在快捷键设置面板中手动自定义了该动作的键位则最终以自定义值为准自定义优先级最高。键位字符串以空格分隔例如shift l会被解析为[shift, l]两个按键的组合见 index.ts 的parseBindings。因此该插件注册的键位语义是同时按下 Shift 与 L。在设置面板中查看与修改keymap 组件本身是一个可配置组件其设置界面由 settings/ 目录下的 Vue 组件提供KeymapSettings.vue快捷键设置弹窗主体列出全部动作与当前绑定键位KeymapSettingsRow.vue单个动作的键位行支持录制/修改按键vm.ts提供loadKeymapSettings与toggleKeymapSettings其中toggleKeymapSettings可由启动栏Launch Bar动作keymapSettings触发见 index.ts。keymap 组件的核心选项定义在 index.ts 中选项默认值说明longJumpSeconds85长前进/长后退的跳跃秒数校验最小值为 1volumeStep10音量调整幅度范围 1–100showSeekShortcutstrue是否显示跳转快捷键customKeyBindings{}用户自定义键位表隐藏项presetDefault键位预设隐藏项启用该插件后打开播放器页面在快捷键扩展设置面板中即可看到新增的开关灯动作及其默认键位Shift L也可录制自定义键位覆盖之。小结与扩展思路从这一句话的文档出发我们还原了一个完整的功能链路插件通过addData(keymap.actions, ...)注册名为togglePlayerLight的快捷键动作通过addData(keymap.presets, ...)注册默认键位shift l动作触发后调用 player-light.ts 的toggleLight()经页面匹配与设置面板惰性加载后委托播放器 Agent 的toggleLight方法Agent 再通过nativeApi.getLightOff()/setLightOff()读写 B 站原生播放器灯光状态完成开灯/关灯切换。对于希望为 Bilibili-Evolved 编写同类扩展的开发者本插件是一个极佳的模板只需实现PluginMetadata在setup中向对应数据槽addData注入动作与键位即可无需改动 keymap 组件本体。动作的run可以是任意异步逻辑——切换灯光、跳转进度、调用playerAgent的其他能力如fullscreen、togglePlay、changeTime等详见 actions.ts 的内置动作——从而实现与 B 站原生气播放器无缝集成的自定义快捷键体系。赞分享前端音视频【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved点击查看免费下载相关推荐Bilibili-Evolved 播放时自动关灯功能全解析源码实现、事件流与星光动画Bilibili Evolved 播放时自动关灯功能全解析源码实现、事件流与星光动画 导读 本文围绕 Bilibili Evolved 中的「播放时自动关灯」前端音视频Bilibili-Evolved 快捷键扩展keymap完全指南三套按键体系、自定义语法与插件扩展 APIBilibili Evolved 快捷键扩展keymap完全指南三套按键体系、自定义语法与插件扩展 API 导读 「快捷键扩展keymap」是 Bil前端音视频Bilibili-Evolved 快捷键扩展keymap完整指南按键语法、预设切换与自定义动作开发Bilibili Evolved 快捷键扩展keymap完整指南按键语法、预设切换与自定义动作开发 Bilibili Evolved 的「快捷键扩展」组前端音视频创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考