Community编程与开发github.com

businessbaum/vedit

当用户要求制作屏幕图形、标题或叠加层时使用此技能——例如“bau eine Bauchbinde”、“mach ein Lower Third”、“blend meinen Namen ein”、“build a lower third”、“add a title card”。涵盖HTML模板合约、Chrome无头帧渲染、保留Alpha的影片编码以及project.json中的叠加区块。

vedit 是什么?

此技能定义了一种确定性的图形渲染管线,用于在视频编辑工作流中生成叠加层(如底栏、标题卡、覆盖文字或动态数字)。其核心原则是:**每个图形都是 `?t=<秒数>` 的纯函数**,完全通过算术计算位置与不透明度,严禁使用CSS动画、GSAP时间线或`requestAnimationFrame`。这种设计保证了渲染结果的可缓存性与可重现性,克服了无头Chrome快照机制中缺乏虚拟时钟的固有限制。 技能涉及的平台包括:通过`python engine/ve.py gfx <slug>`命令调用的构建引擎,利用Chrome无头模式逐帧渲染HTML模板,并以保留Alpha通道的方式编码为QuickTime RLE(`qtrle` argb)或ProRes 4444格式。流程包含五个步骤:选择或编写模板、渲染帧、编码影片、将叠加层锚定到`{segment_id, offset_frames}`而非绝对时间线位置,以及通过Alpha探针、空白页检测和确定性校验进行质量检查。 此技能特别适用于实时图形叠加场景,其缓存机制(基于模板内容、时间参数及渲染器版本的SHA256哈希)使未更改的图形几乎可以即时重渲染。用户应当注意:首次渲染约需430-470毫秒/帧(含7.9秒冷启动),因此建议优先使用短图形(如0.4秒入场+停留+0.4秒出场),并提前告知用户帧数与预估耗时。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/businessbaum/vedit/tree/HEAD/.agents/skills/gfx-html

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

gfx-html

图形是由无头Chrome逐帧渲染并编码为Alpha影片的HTML页面。完整请求文本位于$ARGUMENTS中;第一个标记通常是项目slug。动词名称遵循构建合约;如有冲突,以python engine/ve.py --help为准。

使这条通道生效的规则

每个图形都是 ?t=<秒数> 的纯函数。 没有CSS动画、没有GSAP时间线、没有requestAnimationFrame、没有过渡效果。页面从location.search读取t,计算布局,并渲染一个静态帧。

这不是风格偏好。chrome --headless --screenshot 在“页面看起来已加载”时触发——此构建中没有虚拟时钟,没有Emulation.setVirtualTimePolicy,没有beginFrame。使用CSS动画的页面若以这种方式采样,每次运行都会产生不同的像素点。这会破坏内容寻址缓存(相同的键,不同的像素)并产生可见的抖动。

由相同朴素循环采样的t的纯函数是确定性和可缓存的,这就是全部区别。

提前说明的预算

Chrome稳定状态下的渲染速度约为每帧430-470毫秒,冷启动需7.9秒。一个5秒的图形以30 fps计算,共150帧,单线程大约需要65秒。引擎并行化四个Chrome进程并缓存每帧PNG,因此未更改的图形可以免费重新渲染——但首次渲染并非瞬间完成。

在开始长时间渲染前,告知用户帧数和预估时间。优先使用短图形:一个停留6秒的底栏并不需要6秒的运动,它只需要0.4秒入场、停留和0.4秒出场。

第一步——选择或编写模板

模板位于presets/graphics/*.html。优先复用再编写。模板是一个独立的HTML文件,需满足:

  • 从location.search读取t(秒)及其属性。
  • 使用纯算术从t计算所有位置/不透明度。缓动函数也可以——它们本身就是纯函数。
  • 在透明背景上渲染。绝不能绘制背景颜色。
  • 使用来自assets/fonts/的字体,通过file:/// URL的@font-face加载。不要依赖系统字体——此Chrome解析到的字体与QC控制渲染假设的不同。
  • 在1920x1080分辨率下清晰可读,并位于平台的标题安全区域内。检查output.platform:位于底部三分之一的底栏会被TikTok UI遮挡。

布局细节、缓动约定和属性合约见docs/graphics.md。此处不再赘述。

第二步——渲染帧

python engine/ve.py gfx <slug>

每帧引擎将Chrome作为参数列表调用,大致如下:

chrome.exe --headless=new --disable-gpu --no-sandbox --hide-scrollbars
           --user-data-dir=<win-path>\prof --default-background-color=00000000
           --window-size=1920,1080 --screenshot=<win-path>\frame_0007.png
           "file:///C:/.../template.html?t=0.233&title=..."

两个标志决定了整个流程:

  • --default-background-color=00000000 用于生成真实的Alpha通道。已验证:角落像素读取为0 0 0 0。缺少该标志会产生不透明的黑色,叠加层会覆盖视频。
  • file:/// URL必须是真实的Windows路径。Git Bash的$PWD路径会静默失败——三个不同的HTML文件产生了完全相同的md5值(一个空白深色模式错误页面),退出码为0,文件大小也合理。这就是为什么QC检查(g)需要与已知空白哈希值进行比较。

帧缓存在.cache/html/下,键为sha256(html_content + t + params + renderer + renderer_version)。更改模板会使所有帧失效,这是正确的行为。

第三步——保留Alpha编码

同一命令。ve gfx一次性渲染帧并进行编码——没有单独的编码动词,因为仅有PNG序列而没有配套影片的产物是半成品,下游无法使用。

PNG序列编码为QuickTime RLE(qtrle,argb)。ProRes 4444和原始PNG序列也能正确保留Alpha通道。此构建中,VP9-in-WebM静默丢弃Alpha通道,即使使用-metadata alpha_mode=1也是如此——不要使用它,也不要未经检测就接受用户提供的此类素材。

输出文件位于.cache/ovl/<xx>/<key>.mov,并附带<key>.json副产物。

第四步——锚定叠加层

编写overlays[]条目:id、kind: "html"、template、props、anchor、duration_frames、layer、render。

anchor始终为{segment_id, offset_frames}——绝不能使用绝对时间线位置。 时间线位置由已启用片段的累计和推导得出。一旦有人禁用了上游的某个片段,所有绝对位置都会出错,每个图形都会漂移。锚定叠加层会随其片段自动移动,这正是编辑器期望的行为。

layer控制合成顺序,数值越大越靠上。字幕最后合成,位于所有图形之上。

第五步——验证完成后再宣布完成

三项检查,均成本低廉:

  1. Alpha探测。 从角落帧读取一个原始rgba像素,断言a = 0。QC(d)。
  2. 空白页检查。 断言帧不是每帧都是纯色。QC(g)。这能捕获错误的file:/// URL、字体加载失败和JS错误,这些情况否则都会以退出码0和看似合理的文件大小结束。它采样第一帧、中间帧和四分之三帧,仅当所有帧都是均匀颜色时才失败——此处每个模板都以不透明度0开始,因此正常工作图形的第0帧确实应为空白,仅凭此判断会错误地判定正确渲染。

ve gfx会自动对其生成的产物运行这两项检查,如果失败则退出码为2。 3. 确定性。 将同一帧渲染两次并比较哈希值。如果不同,模板中就存在不是t纯函数的内容——找出来。此项检查的存在是因为它捕获的故障是不可见的,直到缓存渲染与全新渲染出现差异。

然后向用户展示中点静帧。当截图只需一条命令即可获得时,不要用文字描述图形。

故障模式

症状原因修复方法
叠加层以黑色覆盖视频缺少--default-background-color,或模板绘制了背景添加标志;使主体透明
每帧相同,文件大小看似合理错误的file:/// URL导致空白错误页使用真实Windows路径;针对空白哈希值进行断言
相同键,不同运行间像素不同模板不是t的纯函数移除所有CSS动画和rAF
文本以错误的字体渲染系统字体回退通过file:/// URL在assets/fonts/中使用@font-face
编码后Alpha丢失VP9/WebM使用qtrle argb或ProRes 4444
上游编辑后图形漂移绝对时间线锚点锚定到{segment_id, offset_frames}
渲染耗时数分钟430毫秒/帧是下限缩短图形或接受此耗时;缓存使第二次运行免费

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

businessbaum/vedit

This skill should be used when the user asks for subtitles or on-screen text of what is being said - "brenn die Untertitel ein", "mach Untertitel", "Untertitel drauf", "leg Untertitel drüber", "brenn die Subs ein", "mach die Captions", "Wort für Wort Untertitel", "Karaoke-Untertitel", "korrigier den Untertitel-Text", "burn in the captions", "add subtitles", "burn the subs", "word-by-word captions", "fix a caption typo". Covers ASS generation, the pixel-width grouping rule for German, the font table, and burn-in through libass.

businessbaum/vedit

This skill should be used when the user asks for mechanical tightening of material that is already selected - "mach den Rohschnitt", "bau den Rohschnitt", "schneid die Ähms raus", "nimm die Füllwörter raus", "entferne die Pausen", "kürz die Pausen", "schneid die Versprecher raus", "mach den Radioschnitt", "straff das", "build the rough cut", "cut the fillers", "remove the ums", "tighten the pauses", "trim the dead air", "cut the retakes", "radio edit". Turns kept story blocks into enabled segments in project.json. Does not decide what the video is about - that is cut-story.

businessbaum/vedit

This skill should be used when the user asks to decide what the video is actually about before any mechanical cutting - "bau die Story", "was soll ins Video", "was kann raus", "welche Themen bleiben", "kürz das auf 6 Minuten", "mach daraus ein kurzes Video", "wo ist der Hook", "sortier die Themen", "worum geht es hier eigentlich", "build the story", "decide what stays", "structure this", "cut this down to N minutes", "find the hook", "reorder the topics". This is the CONTENT-selection pass that writes the "story" block in project.json; it runs after transcribe and before cut-rough.

businessbaum/vedit

This skill should be used when the user asks for the finished video file - "exportier das", "render das fertig", "mach das final", "renderte das Video", "mach den Endexport", "bau das Video zusammen", "mach es fertig für YouTube", "gib mir die MP4", "export the final", "render the final cut", "make the master", "export for TikTok", "give me the mp4". Covers segment rendering with the cache, guarded concat, the one-pass audio, loudness normalisation and the single mux.

相关技能