返回 html-video
CONTRIBUTING.md
根目录 / CONTRIBUTING.md
1 # Contributing to html-video
2
3 > **English** · [中文](#中文)
4
5 Thank you for your interest in contributing! html-video is an Apache-2.0 project by the [Open Design](https://github.com/nexu-io/open-design) team. We welcome contributions of all kinds — code, docs, templates, bug reports, and ideas.
6
7 ---
8
9 ## Community
10
11 - **Discord**: [Join the Open Design Discord](https://github.com/nexu-io/open-design#community) — the main hub for questions, design discussions, and real-time help.
12 - **X (Twitter)**: Follow [@nexudotio](https://x.com/nexudotio) for project updates.
13 - **GitHub Issues**: Bug reports, feature requests, and template proposals all go here.
14
15 ---
16
17 ## Development Setup
18
19 ### Prerequisites
20
21 | Requirement | Minimum Version | How to check |
22 |---|---|---|
23 | **Node.js** | 20+ | `node --version` |
24 | **pnpm** | 9+ | `pnpm --version` |
25 | **ffmpeg** | Any recent | `ffmpeg -version` |
26 | **Chromium** (or Playwright browsers) | See below | `npx playwright install chromium` |
27
28 **Why Chromium?** The default [Hyperframes](https://github.com/heygen-com/hyperframes) engine renders videos by recording animated HTML in a headless Chromium browser. You need either:
29
30 - A system Chromium/Chrome install (auto-detected), or
31 - Playwright's bundled Chromium: `npx playwright install chromium`
32
33 **Why ffmpeg?** After recording each frame as WebM, ffmpeg encodes them to MP4 (libx264) and concatenates them into the final video. It's also used for the optional AI soundtrack mixing.
34
35 ### Clone, Install, Build
36
37 ```bash
38 git clone https://github.com/nexu-io/html-video.git
39 cd html-video
40 pnpm install
41 pnpm -r build
42 ```
43
44 This is a **pnpm workspace monorepo**. All packages live under `packages/` and templates under `templates/`. The `pnpm -r build` command builds every package in dependency order.
45
46 ### Run Locally
47
48 **Studio (browser UI):**
49
50 ```bash
51 node packages/cli/dist/bin.js studio
52 # Opens at http://127.0.0.1:3071
53 ```
54
55 **CLI tools:**
56
57 ```bash
58 # Check what's installed and ready
59 node packages/cli/dist/bin.js doctor
60
61 # Search templates by intent
62 node packages/cli/dist/bin.js search-templates --intent "data chart" --top 5
63 ```
64
65 ---
66
67 ## Project Structure
68
69 ```
70 packages/
71 ├── core/ Types, registries, orchestrator, MiniMax + ffmpeg audio
72 ├── content-graph/ Multi-frame storyboard IR (nodes + edges, topo-sort)
73 ├── runtime/ Agent runtime — detect / spawn / stream (13 agents)
74 ├── adapter-hyperframes/ Hyperframes engine adapter — Chromium + ffmpeg render
75 ├── cli/ `html-video` command + studio HTTP server + source fetching
76 └── project-studio/ Browser studio UI (chat, gallery, frames, soundtrack, export)
77 templates/ 21 curated, license-clean video templates
78 research/ RFCs (engine adapter / template metadata / agent skill / content-graph)
79 ```
80
81 ---
82
83 ## How to Add a New Agent Runtime
84
85 Adding support for a new coding agent is the most common contribution. It's a self-contained change in `packages/runtime/`.
86
87 **Pattern (from Trae CLI PR #12):**
88
89 ### 1. Create the agent definition file
90
91 `packages/runtime/src/defs/<agent>.ts`:
92
93 ```ts
94 import type { AgentDef } from '../types.js';
95
96 export const myAgent: AgentDef = {
97 id: 'my-agent', // kebab-case, stable
98 name: 'My Agent', // Human-readable
99 bin: 'my-agent-cli', // CLI binary name (looked up on PATH)
100 versionArgs: ['--version'], // Args to check version (for `doctor`)
101 buildArgs(prompt, ctx) { // Build spawn arguments
102 return ['--print', prompt];
103 },
104 streamFormat: 'plain', // 'plain' | 'claude-stream' | 'json-event-stream' | 'acp-json-rpc'
105 promptViaStdin: false, // true if sending prompt via stdin
106 installUrl: 'https://example.com/install', // Where users can get it
107 };
108 ```
109
110 See `packages/runtime/src/types.ts` for the full `AgentDef` interface — it supports ACP JSON-RPC agents, HTTP-based agents (like the Anthropic API), binary fallbacks, and extra availability checks.
111
112 ### 2. Register the agent
113
114 In `packages/runtime/src/registry.ts`, import and add your agent to the `AGENT_DEFS` array:
115
116 ```ts
117 import { myAgent } from './defs/my-agent.js';
118
119 export const AGENT_DEFS: AgentDef[] = [
120 // ... existing agents
121 myAgent,
122 ];
123 ```
124
125 Order matters: the first available agent is the default selection in the studio.
126
127 ### 3. Test
128
129 ```bash
130 pnpm --filter @html-video/runtime build
131 node packages/cli/dist/bin.js doctor # Your agent should appear if its binary is on PATH
132 ```
133
134 ---
135
136 ## How to Add a New Template
137
138 Templates live under `templates/<id>/` and are described by a `template.html-video.yaml` manifest. The studio scans templates at startup and the agent reads the manifest to understand what the template does and what inputs it needs.
139
140 ### Minimum structure
141
142 ```
143 templates/frame-my-cool-animation/
144 ├── template.html-video.yaml # Required — see format below
145 ├── source/index.html # Required — the animated HTML (Hyperframes engine)
146 ├── SKILL.md # Agent-readable instructions for filling in the template
147 ├── example.md # Example input
148 └── poster.svg / preview.png # Static preview image
149 ```
150
151 ### Provenance rules (RFC-07)
152
153 Every template MUST follow the [RFC-07 provenance rules](research/2026-06-04-spec-07-ppt-to-template.md):
154
155 1. **License gate**: Only permissive open-source licenses (MIT, Apache-2.0, BSD, CC-BY, CC-BY-SA). No NC, ND, or unlicensed sources.
156 2. **Three-layer attribution**: L1 (original design studio/designer) → L2 (skill/upstream author) → L3 (our transformation). All three must be recorded in `provenance`.
157 3. **Naming**: Use descriptive feature names, not studio/designer names. ❌ `frame-pentagram-stat` → ✅ `frame-editorial-anchor`
158 4. **Transformation quality**: Must add real animation timeline, use own sample data, and have identifiable redesign from the upstream source.
159 5. **Deduplication**: Check against existing templates from the same upstream. Don't ship near-identical variants.
160
161 ### manifest.yaml skeleton
162
163 ```yaml
164 spec_version: 1
165 id: frame-my-cool-animation
166 name: My Cool Animation
167 description: A short description for agents and the gallery.
168 engine: hyperframes
169 category: title-card
170 tags: [animation, reveal]
171 best_for:
172 - "Product launch teasers"
173 - "Social media shorts"
174 inputs:
175 schema:
176 type: object
177 required: [title]
178 properties:
179 title: { type: string, description: "Main headline" }
180 subtitle: { type: string, description: "Subtitle line" }
181 examples:
182 - title: "Hello World"
183 subtitle: "This is an example"
184 output:
185 formats: [mp4]
186 default_format: mp4
187 duration: { type: variable, min_sec: 3, max_sec: 15 }
188 license:
189 spdx: Apache-2.0
190 attribution_required: false
191 redistribution_allowed: true
192 commercial_use: true
193 provenance:
194 origin:
195 name: "Original Designer / Studio"
196 kind: design-studio
197 reference: "https://example.com"
198 via_skill:
199 name: upstream-skill-name
200 author: "Author Name"
201 url: https://github.com/author/upstream
202 license: MIT
203 source_file: path/to/source.html
204 transformation: >
205 Static design → animated Hyperframes timeline with CSS @keyframes.
206 Re-colored, original sample data.
207 ```
208
209 See [RFC-02](research/2026-05-26-spec-02-template-metadata.md) for the complete `template.html-video.yaml` specification.
210
211 ---
212
213 ## How to Add a New Engine Adapter
214
215 The engine adapter interface ([RFC-01](research/2026-05-26-spec-01-engine-adapter.md)) lets any video rendering backend plug into html-video. The shipped adapter is `@html-video/adapter-hyperframes` — use it as the reference implementation.
216
217 ### 1. Create a new package
218
219 ```
220 packages/adapter-<engine>/
221 ├── package.json
222 ├── src/
223 │ ├── index.ts # Export default EngineAdapter instance
224 │ ├── capabilities.ts # Static capability declaration
225 │ ├── validate.ts # Validate a template for this engine
226 │ └── render.ts # Core render implementation
227 └── tsconfig.json
228 ```
229
230 ### 2. Implement the EngineAdapter interface
231
232 The core contract is defined in `packages/core/src/types.ts`:
233
234 ```ts
235 export interface EngineAdapter {
236 id: EngineId;
237 name: string;
238 upstreamVersion: string;
239 capabilities: EngineCapabilities;
240 validate(template: Template): ValidationResult;
241 render(input: RenderInput, ctx: RenderContext): Promise<RenderOutput>;
242 preview?(template: Template, ctx: PreviewContext): Promise<PreviewHandle>;
243 listNativeTemplates?(): Promise<NativeTemplateRef[]>;
244 }
245 ```
246
247 Key conventions from RFC-01:
248
249 - **Process isolation**: Each `render()` spawns an independent subprocess. Subprocess crashes must reject the promise and leave no partial output files.
250 - **Progress reporting**: 0-100% based on current frame / total frames. Stage hints: `preparing` (0-10%), `rendering` (10-95%), `muxing` (95-100%).
251 - **Cancellation**: Respect `ctx.signal.aborted` — kill subprocess, cleanup workDir temp files, reject with `AbortError`.
252 - **Package naming**: `@html-video/adapter-<name>`, peer-depend on the upstream engine.
253
254 ### 3. Register in core
255
256 The core dynamically loads adapters — once your package is in `packages/` and listed in `pnpm-workspace.yaml`, it will be auto-discovered at runtime.
257
258 ---
259
260 ## Code Style
261
262 - **Language**: TypeScript (strict mode, `tsconfig.base.json` inheritance)
263 - **Formatting**: [Biome](https://biomejs.dev/) — 2 spaces, single quotes, trailing commas, semicolons, LF line endings. Run `pnpm format` to auto-format.
264 - **Linting**: `pnpm lint` runs Biome linter with recommended rules.
265 - **Monorepo tooling**: pnpm workspaces, `pnpm -r build` builds all packages in order.
266 - **Imports**: Use `.js` extensions in TypeScript imports (for ESM compatibility).
267
268 ### Before submitting
269
270 ```bash
271 pnpm typecheck # TypeScript across all packages
272 pnpm lint # Biome linter
273 pnpm format # Auto-format all files
274 pnpm test # Run all tests
275 ```
276
277 ---
278
279 ## How to Submit a Pull Request
280
281 1. **Fork** the repository and create a branch from `main`.
282 2. **Make your changes** — keep them focused. One PR = one logical change.
283 3. **Test your changes** — run `pnpm typecheck && pnpm lint && pnpm test`.
284 4. **Write a clear commit message** — follow conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
285 5. **Open a PR** against `nexu-io/html-video:main`.
286 6. **Describe** what you changed, why, and how to verify it.
287
288 We review PRs regularly. If your PR adds a new feature, link to or include related tests.
289
290 ---
291
292 ## License
293
294 By contributing, you agree that your contributions will be licensed under the [Apache-2.0 License](LICENSE) — same as the rest of the project. No contributor license agreement (CLA) is required.
295
296 ---
297
298 ## Questions?
299
300 - **Real-time chat**: Join the [Open Design Discord](https://github.com/nexu-io/open-design#community)
301 - **Bugs & features**: Open an issue on [GitHub](https://github.com/nexu-io/html-video/issues)
302 - **Design decisions**: Read the RFCs in [`research/`](research/)
303
304 ---
305
306 ## 中文 {#中文}
307
308 感谢你有意为 html-video 贡献!html-video 是 [Open Design](https://github.com/nexu-io/open-design) 团队维护的 Apache-2.0 项目。我们欢迎所有形式的贡献 —— 代码、文档、模板、bug 反馈和想法。
309
310 ### 社区
311
312 - **Discord**:[加入 Open Design Discord](https://github.com/nexu-io/open-design#community) — 主要的问答、设计讨论和实时求助渠道。
313 - **X(Twitter)**:关注 [@nexudotio](https://x.com/nexudotio) 获取项目动态。
314 - **GitHub Issues**:提 bug、功能建议、模板提案都来这里。
315
316 ### 开发环境搭建
317
318 #### 前置依赖
319
320 | 依赖 | 最低版本 | 检查方式 |
321 |---|---|---|
322 | **Node.js** | 20+ | `node --version` |
323 | **pnpm** | 9+ | `pnpm --version` |
324 | **ffmpeg** | 任意较新版本 | `ffmpeg -version` |
325 | **Chromium**(或 Playwright 浏览器)| 见下文 | `npx playwright install chromium` |
326
327 **为什么需要 Chromium?** 默认的 [Hyperframes](https://github.com/heygen-com/hyperframes) 引擎用无头 Chromium 录制带动画的 HTML 来渲染视频。你需要以下之一:
328
329 - 系统安装的 Chromium/Chrome(自动检测),或
330 - Playwright 内置的 Chromium:`npx playwright install chromium`
331
332 **为什么需要 ffmpeg?** 渲出每帧 WebM 后,ffmpeg 将它们编码为 MP4(libx264)再拼接成最终视频。可选的 AI 配乐混音也要用到它。
333
334 #### 克隆、安装、构建
335
336 ```bash
337 git clone https://github.com/nexu-io/html-video.git
338 cd html-video
339 pnpm install
340 pnpm -r build
341 ```
342
343 这是 **pnpm workspace 单体仓库**。所有包在 `packages/` 下,模板在 `templates/` 下。`pnpm -r build` 按依赖顺序构建所有包。
344
345 #### 本地运行
346
347 **Studio(浏览器界面):**
348
349 ```bash
350 node packages/cli/dist/bin.js studio
351 # 在 http://127.0.0.1:3071 打开
352 ```
353
354 **CLI 工具:**
355
356 ```bash
357 # 查看已安装并可用的 agent 和引擎
358 node packages/cli/dist/bin.js doctor
359
360 # 按意图搜索模板
361 node packages/cli/dist/bin.js search-templates --intent "数据图表" --top 5
362 ```
363
364 ### 如何添加新的 Agent 运行时
365
366 添加对新 coding agent 的支持是最常见的贡献类型。改动集中在 `packages/runtime/` 内。
367
368 **模式(参考 Trae CLI PR #12):**
369
370 #### 1. 创建 agent 定义文件
371
372 `packages/runtime/src/defs/<agent>.ts`:
373
374 ```ts
375 import type { AgentDef } from '../types.js';
376
377 export const myAgent: AgentDef = {
378 id: 'my-agent', // kebab-case,稳定不变
379 name: 'My Agent', // 可读名称
380 bin: 'my-agent-cli', // CLI 二进制名(在 PATH 上查找)
381 versionArgs: ['--version'], // 检查版本的参数(给 `doctor` 用)
382 buildArgs(prompt, ctx) { // 构建启动参数
383 return ['--print', prompt];
384 },
385 streamFormat: 'plain', // 'plain' | 'claude-stream' | 'json-event-stream' | 'acp-json-rpc'
386 promptViaStdin: false, // 是否通过 stdin 传递 prompt
387 installUrl: 'https://example.com/install', // 安装指引链接
388 };
389 ```
390
391 完整 `AgentDef` 接口见 `packages/runtime/src/types.ts` —— 它支持 ACP JSON-RPC agent、基于 HTTP 的 agent(如 Anthropic API)、二进制回退路径和额外的可用性检查。
392
393 #### 2. 注册 agent
394
395 在 `packages/runtime/src/registry.ts` 中 import 并将你的 agent 加入 `AGENT_DEFS` 数组:
396
397 ```ts
398 import { myAgent } from './defs/my-agent.js';
399
400 export const AGENT_DEFS: AgentDef[] = [
401 // ... 已有 agent
402 myAgent,
403 ];
404 ```
405
406 顺序很重要:第一个可用的 agent 是 studio 的默认选项。
407
408 #### 3. 测试
409
410 ```bash
411 pnpm --filter @html-video/runtime build
412 node packages/cli/dist/bin.js doctor # 如果二进制在 PATH 上,你的 agent 应该出现
413 ```
414
415 ### 如何添加新模板
416
417 模板放在 `templates/<id>/` 下,由 `template.html-video.yaml` 清单描述。studio 启动时扫描模板,agent 读取清单来了解模板用途和输入需求。
418
419 #### 最小目录结构
420
421 ```
422 templates/frame-my-cool-animation/
423 ├── template.html-video.yaml # 必选 —— 格式见下文
424 ├── source/index.html # 必选 —— 带动画的 HTML(Hyperframes 引擎)
425 ├── SKILL.md # Agent 可读的填参说明
426 ├── example.md # 示例输入
427 └── poster.svg / preview.png # 静态预览图
428 ```
429
430 #### 来源规范(RFC-07)
431
432 每个模板必须遵守 [RFC-07 来源规范](research/2026-06-04-spec-07-ppt-to-template.md):
433
434 1. **许可闸门**:只收明确宽松开源的许可(MIT、Apache-2.0、BSD、CC-BY、CC-BY-SA)。不收 NC、ND 或无许可的来源。
435 2. **三层署名**:L1(原始设计工作室/设计师)→ L2(skill/上游作者)→ L3(我们的转化)。三层都必须记在 `provenance` 里。
436 3. **命名**:用描述设计特征的名字,不要挪用工作室/设计师名。❌ `frame-pentagram-stat` → ✅ `frame-editorial-anchor`
437 4. **转化质量**:必须新增真实的动效时间线、用自有示例数据、相比上游有可辨别的再设计。
438 5. **查重**:跟同一上游来源的已有模板比对,不提交几乎一样的变体。
439
440 ### 如何添加新引擎适配器
441
442 引擎适配器接口([RFC-01](research/2026-05-26-spec-01-engine-adapter.md))让任何视频渲染后端都能接入 html-video。已发布的适配器是 `@html-video/adapter-hyperframes` —— 用它作为参考实现。
443
444 #### 1. 创建新包
445
446 ```
447 packages/adapter-<engine>/
448 ├── package.json
449 ├── src/
450 │ ├── index.ts # 导出默认 EngineAdapter 实例
451 │ ├── capabilities.ts # 静态能力声明
452 │ ├── validate.ts # 校验模板能否被本引擎渲染
453 │ └── render.ts # 核心渲染实现
454 └── tsconfig.json
455 ```
456
457 #### 2. 实现 EngineAdapter 接口
458
459 核心契约定义在 `packages/core/src/types.ts`,详见 [RFC-01](research/2026-05-26-spec-01-engine-adapter.md)。关键约定:
460
461 - **进程隔离**:每次 `render()` 启动独立子进程。子进程崩溃必须 reject promise,不留下不完整的输出文件。
462 - **进度报告**:按当前帧/总帧数算 0-100%。阶段提示:`preparing`(0-10%)、`rendering`(10-95%)、`muxing`(95-100%)。
463 - **取消**:响应 `ctx.signal.aborted` —— 杀掉子进程,清理 workDir 临时文件,reject `AbortError`。
464 - **包命名**:`@html-video/adapter-<name>`,peer-depend 上游引擎。
465
466 ### 代码风格
467
468 - **语言**:TypeScript(strict 模式,继承 `tsconfig.base.json`)
469 - **格式化**:[Biome](https://biomejs.dev/) —— 2 空格缩进、单引号、尾逗号、分号、LF 换行。运行 `pnpm format` 自动格式化。
470 - **Lint**:`pnpm lint` 用 Biome linter 的推荐规则。
471 - **单体仓库工具链**:pnpm workspace,`pnpm -r build` 按顺序构建所有包。
472 - **Import**:TypeScript import 使用 `.js` 扩展名(ESM 兼容)。
473
474 #### 提交前检查
475
476 ```bash
477 pnpm typecheck # 全仓库 TypeScript 检查
478 pnpm lint # Biome linter
479 pnpm format # 自动格式化所有文件
480 pnpm test # 运行所有测试
481 ```
482
483 ### 如何提交 Pull Request
484
485 1. **Fork** 仓库,从 `main` 创建分支。
486 2. **做出改动** —— 保持聚焦。一个 PR = 一个逻辑变更。
487 3. **测试你的改动** —— 运行 `pnpm typecheck && pnpm lint && pnpm test`。
488 4. **写清楚的 commit message** —— 遵循 conventional commits:`feat:`、`fix:`、`docs:`、`refactor:`、`test:`、`chore:`。
489 5. **发起 PR** 到 `nexu-io/html-video:main`。
490 6. **描述**你改了什么、为什么、怎么验证。
491
492 我们会定期 review PR。如果你的 PR 加了新功能,请附带或链接相关测试。
493
494 ### 许可
495
496 贡献即表示你同意你的贡献将按照 [Apache-2.0 许可](LICENSE) 授权 —— 和项目其他部分一致。不需要签署贡献者协议(CLA)。
497
498 ### 有问题?
499
500 - **实时聊天**:加入 [Open Design Discord](https://github.com/nexu-io/open-design#community)
501 - **Bug 和功能**:在 [GitHub](https://github.com/nexu-io/html-video/issues) 提 issue
502 - **设计决策**:阅读 [`research/`](research/) 中的 RFC
503
503 lines MARKDOWN