Skip to content

Latest commit

 

History

History
502 lines (364 loc) · 18.8 KB

File metadata and controls

502 lines (364 loc) · 18.8 KB

Contributing to html-video

English · 中文

Thank you for your interest in contributing! html-video is an Apache-2.0 project by the Open Design team. We welcome contributions of all kinds — code, docs, templates, bug reports, and ideas.


Community

  • Discord: Join the Open Design Discord — the main hub for questions, design discussions, and real-time help.
  • X (Twitter): Follow @nexudotio for project updates.
  • GitHub Issues: Bug reports, feature requests, and template proposals all go here.

Development Setup

Prerequisites

Requirement Minimum Version How to check
Node.js 20+ node --version
pnpm 9+ pnpm --version
ffmpeg Any recent ffmpeg -version
Chromium (or Playwright browsers) See below npx playwright install chromium

Why Chromium? The default Hyperframes engine renders videos by recording animated HTML in a headless Chromium browser. You need either:

  • A system Chromium/Chrome install (auto-detected), or
  • Playwright's bundled Chromium: npx playwright install chromium

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.

Clone, Install, Build

git clone https://github.com/nexu-io/html-video.git
cd html-video
pnpm install
pnpm -r build

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.

Run Locally

Studio (browser UI):

node packages/cli/dist/bin.js studio
# Opens at http://127.0.0.1:3071

CLI tools:

# Check what's installed and ready
node packages/cli/dist/bin.js doctor

# Search templates by intent
node packages/cli/dist/bin.js search-templates --intent "data chart" --top 5

Project Structure

packages/
├── core/                  Types, registries, orchestrator, MiniMax + ffmpeg audio
├── content-graph/         Multi-frame storyboard IR (nodes + edges, topo-sort)
├── runtime/               Agent runtime — detect / spawn / stream (13 agents)
├── adapter-hyperframes/   Hyperframes engine adapter — Chromium + ffmpeg render
├── cli/                   `html-video` command + studio HTTP server + source fetching
└── project-studio/        Browser studio UI (chat, gallery, frames, soundtrack, export)
templates/                 21 curated, license-clean video templates
research/                  RFCs (engine adapter / template metadata / agent skill / content-graph)

How to Add a New Agent Runtime

Adding support for a new coding agent is the most common contribution. It's a self-contained change in packages/runtime/.

Pattern (from Trae CLI PR #12):

1. Create the agent definition file

packages/runtime/src/defs/<agent>.ts:

import type { AgentDef } from '../types.js';

export const myAgent: AgentDef = {
  id: 'my-agent',              // kebab-case, stable
  name: 'My Agent',            // Human-readable
  bin: 'my-agent-cli',         // CLI binary name (looked up on PATH)
  versionArgs: ['--version'],  // Args to check version (for `doctor`)
  buildArgs(prompt, ctx) {     // Build spawn arguments
    return ['--print', prompt];
  },
  streamFormat: 'plain',       // 'plain' | 'claude-stream' | 'json-event-stream' | 'acp-json-rpc'
  promptViaStdin: false,       // true if sending prompt via stdin
  installUrl: 'https://example.com/install',  // Where users can get it
};

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.

2. Register the agent

In packages/runtime/src/registry.ts, import and add your agent to the AGENT_DEFS array:

import { myAgent } from './defs/my-agent.js';

export const AGENT_DEFS: AgentDef[] = [
  // ... existing agents
  myAgent,
];

Order matters: the first available agent is the default selection in the studio.

3. Test

pnpm --filter @html-video/runtime build
node packages/cli/dist/bin.js doctor  # Your agent should appear if its binary is on PATH

How to Add a New Template

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.

Minimum structure

templates/frame-my-cool-animation/
├── template.html-video.yaml   # Required — see format below
├── source/index.html          # Required — the animated HTML (Hyperframes engine)
├── SKILL.md                   # Agent-readable instructions for filling in the template
├── example.md                 # Example input
└── poster.svg / preview.png   # Static preview image

Provenance rules (RFC-07)

Every template MUST follow the RFC-07 provenance rules:

  1. License gate: Only permissive open-source licenses (MIT, Apache-2.0, BSD, CC-BY, CC-BY-SA). No NC, ND, or unlicensed sources.
  2. Three-layer attribution: L1 (original design studio/designer) → L2 (skill/upstream author) → L3 (our transformation). All three must be recorded in provenance.
  3. Naming: Use descriptive feature names, not studio/designer names. ❌ frame-pentagram-stat → ✅ frame-editorial-anchor
  4. Transformation quality: Must add real animation timeline, use own sample data, and have identifiable redesign from the upstream source.
  5. Deduplication: Check against existing templates from the same upstream. Don't ship near-identical variants.

manifest.yaml skeleton

spec_version: 1
id: frame-my-cool-animation
name: My Cool Animation
description: A short description for agents and the gallery.
engine: hyperframes
category: title-card
tags: [animation, reveal]
best_for:
  - "Product launch teasers"
  - "Social media shorts"
inputs:
  schema:
    type: object
    required: [title]
    properties:
      title: { type: string, description: "Main headline" }
      subtitle: { type: string, description: "Subtitle line" }
  examples:
    - title: "Hello World"
      subtitle: "This is an example"
output:
  formats: [mp4]
  default_format: mp4
  duration: { type: variable, min_sec: 3, max_sec: 15 }
license:
  spdx: Apache-2.0
  attribution_required: false
  redistribution_allowed: true
  commercial_use: true
provenance:
  origin:
    name: "Original Designer / Studio"
    kind: design-studio
    reference: "https://example.com"
  via_skill:
    name: upstream-skill-name
    author: "Author Name"
    url: https://github.com/author/upstream
    license: MIT
    source_file: path/to/source.html
  transformation: >
    Static design → animated Hyperframes timeline with CSS @keyframes.
    Re-colored, original sample data.

See RFC-02 for the complete template.html-video.yaml specification.


How to Add a New Engine Adapter

The engine adapter interface (RFC-01) lets any video rendering backend plug into html-video. The shipped adapter is @html-video/adapter-hyperframes — use it as the reference implementation.

1. Create a new package

packages/adapter-<engine>/
├── package.json
├── src/
│   ├── index.ts          # Export default EngineAdapter instance
│   ├── capabilities.ts   # Static capability declaration
│   ├── validate.ts       # Validate a template for this engine
│   └── render.ts         # Core render implementation
└── tsconfig.json

2. Implement the EngineAdapter interface

The core contract is defined in packages/core/src/types.ts:

export interface EngineAdapter {
  id: EngineId;
  name: string;
  upstreamVersion: string;
  capabilities: EngineCapabilities;
  validate(template: Template): ValidationResult;
  render(input: RenderInput, ctx: RenderContext): Promise<RenderOutput>;
  preview?(template: Template, ctx: PreviewContext): Promise<PreviewHandle>;
  listNativeTemplates?(): Promise<NativeTemplateRef[]>;
}

Key conventions from RFC-01:

  • Process isolation: Each render() spawns an independent subprocess. Subprocess crashes must reject the promise and leave no partial output files.
  • Progress reporting: 0-100% based on current frame / total frames. Stage hints: preparing (0-10%), rendering (10-95%), muxing (95-100%).
  • Cancellation: Respect ctx.signal.aborted — kill subprocess, cleanup workDir temp files, reject with AbortError.
  • Package naming: @html-video/adapter-<name>, peer-depend on the upstream engine.

3. Register in core

The core dynamically loads adapters — once your package is in packages/ and listed in pnpm-workspace.yaml, it will be auto-discovered at runtime.


Code Style

  • Language: TypeScript (strict mode, tsconfig.base.json inheritance)
  • Formatting: Biome — 2 spaces, single quotes, trailing commas, semicolons, LF line endings. Run pnpm format to auto-format.
  • Linting: pnpm lint runs Biome linter with recommended rules.
  • Monorepo tooling: pnpm workspaces, pnpm -r build builds all packages in order.
  • Imports: Use .js extensions in TypeScript imports (for ESM compatibility).

Before submitting

pnpm typecheck    # TypeScript across all packages
pnpm lint         # Biome linter
pnpm format       # Auto-format all files
pnpm test         # Run all tests

How to Submit a Pull Request

  1. Fork the repository and create a branch from main.
  2. Make your changes — keep them focused. One PR = one logical change.
  3. Test your changes — run pnpm typecheck && pnpm lint && pnpm test.
  4. Write a clear commit message — follow conventional commits: feat:, fix:, docs:, refactor:, test:, chore:.
  5. Open a PR against nexu-io/html-video:main.
  6. Describe what you changed, why, and how to verify it.

We review PRs regularly. If your PR adds a new feature, link to or include related tests.


License

By contributing, you agree that your contributions will be licensed under the Apache-2.0 License — same as the rest of the project. No contributor license agreement (CLA) is required.


Questions?


中文 {#中文}

感谢你有意为 html-video 贡献!html-video 是 Open Design 团队维护的 Apache-2.0 项目。我们欢迎所有形式的贡献 —— 代码、文档、模板、bug 反馈和想法。

社区

  • Discord加入 Open Design Discord — 主要的问答、设计讨论和实时求助渠道。
  • X(Twitter):关注 @nexudotio 获取项目动态。
  • GitHub Issues:提 bug、功能建议、模板提案都来这里。

开发环境搭建

前置依赖

依赖 最低版本 检查方式
Node.js 20+ node --version
pnpm 9+ pnpm --version
ffmpeg 任意较新版本 ffmpeg -version
Chromium(或 Playwright 浏览器) 见下文 npx playwright install chromium

为什么需要 Chromium? 默认的 Hyperframes 引擎用无头 Chromium 录制带动画的 HTML 来渲染视频。你需要以下之一:

  • 系统安装的 Chromium/Chrome(自动检测),或
  • Playwright 内置的 Chromium:npx playwright install chromium

为什么需要 ffmpeg? 渲出每帧 WebM 后,ffmpeg 将它们编码为 MP4(libx264)再拼接成最终视频。可选的 AI 配乐混音也要用到它。

克隆、安装、构建

git clone https://github.com/nexu-io/html-video.git
cd html-video
pnpm install
pnpm -r build

这是 pnpm workspace 单体仓库。所有包在 packages/ 下,模板在 templates/ 下。pnpm -r build 按依赖顺序构建所有包。

本地运行

Studio(浏览器界面):

node packages/cli/dist/bin.js studio
# 在 http://127.0.0.1:3071 打开

CLI 工具:

# 查看已安装并可用的 agent 和引擎
node packages/cli/dist/bin.js doctor

# 按意图搜索模板
node packages/cli/dist/bin.js search-templates --intent "数据图表" --top 5

如何添加新的 Agent 运行时

添加对新 coding agent 的支持是最常见的贡献类型。改动集中在 packages/runtime/ 内。

模式(参考 Trae CLI PR #12):

1. 创建 agent 定义文件

packages/runtime/src/defs/<agent>.ts

import type { AgentDef } from '../types.js';

export const myAgent: AgentDef = {
  id: 'my-agent',              // kebab-case,稳定不变
  name: 'My Agent',            // 可读名称
  bin: 'my-agent-cli',         // CLI 二进制名(在 PATH 上查找)
  versionArgs: ['--version'],  // 检查版本的参数(给 `doctor` 用)
  buildArgs(prompt, ctx) {     // 构建启动参数
    return ['--print', prompt];
  },
  streamFormat: 'plain',       // 'plain' | 'claude-stream' | 'json-event-stream' | 'acp-json-rpc'
  promptViaStdin: false,       // 是否通过 stdin 传递 prompt
  installUrl: 'https://example.com/install',  // 安装指引链接
};

完整 AgentDef 接口见 packages/runtime/src/types.ts —— 它支持 ACP JSON-RPC agent、基于 HTTP 的 agent(如 Anthropic API)、二进制回退路径和额外的可用性检查。

2. 注册 agent

packages/runtime/src/registry.ts 中 import 并将你的 agent 加入 AGENT_DEFS 数组:

import { myAgent } from './defs/my-agent.js';

export const AGENT_DEFS: AgentDef[] = [
  // ... 已有 agent
  myAgent,
];

顺序很重要:第一个可用的 agent 是 studio 的默认选项。

3. 测试

pnpm --filter @html-video/runtime build
node packages/cli/dist/bin.js doctor  # 如果二进制在 PATH 上,你的 agent 应该出现

如何添加新模板

模板放在 templates/<id>/ 下,由 template.html-video.yaml 清单描述。studio 启动时扫描模板,agent 读取清单来了解模板用途和输入需求。

最小目录结构

templates/frame-my-cool-animation/
├── template.html-video.yaml   # 必选 —— 格式见下文
├── source/index.html          # 必选 —— 带动画的 HTML(Hyperframes 引擎)
├── SKILL.md                   # Agent 可读的填参说明
├── example.md                 # 示例输入
└── poster.svg / preview.png   # 静态预览图

来源规范(RFC-07)

每个模板必须遵守 RFC-07 来源规范

  1. 许可闸门:只收明确宽松开源的许可(MIT、Apache-2.0、BSD、CC-BY、CC-BY-SA)。不收 NC、ND 或无许可的来源。
  2. 三层署名:L1(原始设计工作室/设计师)→ L2(skill/上游作者)→ L3(我们的转化)。三层都必须记在 provenance 里。
  3. 命名:用描述设计特征的名字,不要挪用工作室/设计师名。❌ frame-pentagram-stat → ✅ frame-editorial-anchor
  4. 转化质量:必须新增真实的动效时间线、用自有示例数据、相比上游有可辨别的再设计。
  5. 查重:跟同一上游来源的已有模板比对,不提交几乎一样的变体。

如何添加新引擎适配器

引擎适配器接口(RFC-01)让任何视频渲染后端都能接入 html-video。已发布的适配器是 @html-video/adapter-hyperframes —— 用它作为参考实现。

1. 创建新包

packages/adapter-<engine>/
├── package.json
├── src/
│   ├── index.ts          # 导出默认 EngineAdapter 实例
│   ├── capabilities.ts   # 静态能力声明
│   ├── validate.ts       # 校验模板能否被本引擎渲染
│   └── render.ts         # 核心渲染实现
└── tsconfig.json

2. 实现 EngineAdapter 接口

核心契约定义在 packages/core/src/types.ts,详见 RFC-01。关键约定:

  • 进程隔离:每次 render() 启动独立子进程。子进程崩溃必须 reject promise,不留下不完整的输出文件。
  • 进度报告:按当前帧/总帧数算 0-100%。阶段提示:preparing(0-10%)、rendering(10-95%)、muxing(95-100%)。
  • 取消:响应 ctx.signal.aborted —— 杀掉子进程,清理 workDir 临时文件,reject AbortError
  • 包命名@html-video/adapter-<name>,peer-depend 上游引擎。

代码风格

  • 语言:TypeScript(strict 模式,继承 tsconfig.base.json
  • 格式化Biome —— 2 空格缩进、单引号、尾逗号、分号、LF 换行。运行 pnpm format 自动格式化。
  • Lintpnpm lint 用 Biome linter 的推荐规则。
  • 单体仓库工具链:pnpm workspace,pnpm -r build 按顺序构建所有包。
  • Import:TypeScript import 使用 .js 扩展名(ESM 兼容)。

提交前检查

pnpm typecheck    # 全仓库 TypeScript 检查
pnpm lint         # Biome linter
pnpm format       # 自动格式化所有文件
pnpm test         # 运行所有测试

如何提交 Pull Request

  1. Fork 仓库,从 main 创建分支。
  2. 做出改动 —— 保持聚焦。一个 PR = 一个逻辑变更。
  3. 测试你的改动 —— 运行 pnpm typecheck && pnpm lint && pnpm test
  4. 写清楚的 commit message —— 遵循 conventional commits:feat:fix:docs:refactor:test:chore:
  5. 发起 PRnexu-io/html-video:main
  6. 描述你改了什么、为什么、怎么验证。

我们会定期 review PR。如果你的 PR 加了新功能,请附带或链接相关测试。

许可

贡献即表示你同意你的贡献将按照 Apache-2.0 许可 授权 —— 和项目其他部分一致。不需要签署贡献者协议(CLA)。

有问题?