Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d5996f7
feat: add Vue SFC project support
ubugeeei May 17, 2026
df32df8
chore: add typecheck script
ubugeeei May 18, 2026
3190140
chore: ignore playwright mcp artifacts
ubugeeei May 18, 2026
c888e5d
style: format backend rust sources
ubugeeei May 18, 2026
b10679b
fix: reset backend health cache on failures
ubugeeei May 18, 2026
dacc746
fix: validate render ipc payload
ubugeeei May 18, 2026
7419136
fix: remove missing favicon reference
ubugeeei May 18, 2026
929e3b5
build: include render bundle in production build
ubugeeei May 18, 2026
0236725
build: pin supported node and npm versions
ubugeeei May 18, 2026
548e318
ci: add pull request validation
ubugeeei May 18, 2026
94a4e08
Merge pull request #36 from ubugeeei/codex/prod-typecheck-script
ubugeeei May 18, 2026
c3605a1
Merge pull request #44 from ubugeeei/codex/prod-ci-checks
ubugeeei May 18, 2026
99b4040
Merge pull request #37 from ubugeeei/codex/prod-ignore-playwright-art…
ubugeeei May 18, 2026
62ad751
Merge pull request #38 from ubugeeei/codex/prod-backend-cargo-fmt
ubugeeei May 18, 2026
07afbed
Merge pull request #39 from ubugeeei/codex/prod-electron-health-reset
ubugeeei May 18, 2026
48d342c
merge codex/vue-support into render ipc validation
ubugeeei May 18, 2026
9aa0599
Merge pull request #40 from ubugeeei/codex/prod-render-ipc-validation
ubugeeei May 18, 2026
1b82512
Merge pull request #41 from ubugeeei/codex/prod-favicon
ubugeeei May 18, 2026
d7f2208
Merge pull request #42 from ubugeeei/codex/prod-node-engines
ubugeeei May 18, 2026
8861255
Merge pull request #43 from ubugeeei/codex/prod-build-all
ubugeeei May 18, 2026
9cf4498
fix: complete issue backlog hardening
ubugeeei May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: CI

on:
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
node:
name: Node builds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: |
package-lock.json
docs/package-lock.json

- name: Install app dependencies
run: npm ci

- name: Install docs dependencies
run: npm --prefix docs ci

- name: Typecheck
run: npm run typecheck

- name: Lint
run: npm run lint

- name: Unit tests
run: npm run test

- name: Build app
run: npm run build

- name: Build render bundle
run: npm run build:render

- name: Build docs
run: npm run docs:build

rust:
name: Rust check
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
crate:
- backend
- render
steps:
- uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
${{ matrix.crate }}/target
key: ${{ runner.os }}-cargo-${{ matrix.crate }}-${{ hashFiles(format('{0}/Cargo.lock', matrix.crate)) }}

- name: Check ${{ matrix.crate }}
run: cargo check --manifest-path ${{ matrix.crate }}/Cargo.toml
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dist-render
docs/.docusaurus
docs/build
docs/.cache
.playwright-mcp

target
frames
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ frames
bin
docs/build
docs/.docusaurus
.playwright-mcp
output.mp4
output.gif
output_youtube.mp4
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Instructions for AI agents

This project is a bundle of the FrameScript video editor & motion graphics tool and its project.
The files the user should mainly edit are in the `project/` directory and `project/project.tsx`, while the FrameScript core and libraries are in `src/`.
The files the user should mainly edit are in the `project/` directory. `project/project.vue` is the primary Vue SFC authoring surface, and `project/project.tsx` is the React/FrameScript entrypoint that mounts it.
Please read the code under `src/` carefully and comprehensively.
As a rule, it is preferable not to edit code under `src/` except for contributing to FrameScript. (If the user explicitly wants edits, follow that.)
142 changes: 68 additions & 74 deletions README.ja.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,102 @@
![](./frame-script.gif)

FrameScriptはReact + CSSで描画・編集する動画編集 & モーショングラフィックスソフトです
FrameScript.vue は Vue SFC + CSS で動画を記述できる FrameScript の fork です

<a href="https://discord.gg/Gpjvht3BqM" data-size="large">
<img alt="Discord" src="https://img.shields.io/discord/1454040226594033728.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge">
</a>

## FrameScriptの特徴
## FrameScript の特徴

- React+CSSに代表されるWebのフロントエンド技術を用いて動画を構築
- `useAnimation`のAPIを用いた細かなアニメーション制御
- Rustによって構築された効率的なレンダリングシステム
- Vue SFC + CSS に代表される Web のフロントエンド技術を用いて動画を構築
- フレーム値を使った Vue の `computed` による細かなアニメーション制御
- Rust によって構築された効率的なレンダリングシステム

## Reactで動画を構成
## Vue SFC で動画を構成

```tsx
import { Clip } from "../src/lib/clip"
import { Project, type ProjectSettings } from "../src/lib/project"
import { TimeLine } from "../src/lib/timeline"
import { Video } from "../src/lib/video/video"
Vue SFC で書く場合は `project/project.vue` を編集します。`project/project.tsx` は Vue プロジェクトをマウントする React/FrameScript 側のエントリポイントで、高度な統合が必要な場合に編集します。

// プロジェクトの設定
export const PROJECT_SETTINGS: ProjectSettings = {
name: "framescript-minimal",
width: 1920,
height: 1080,
fps: 60,
}
```vue
<script setup lang="ts">
import { Clip, Project, TimeLine, Video } from "../src/lib/vue"
</script>

// プロジェクトの定義
// ここに要素を付け足していくことで動画を構築する
export const PROJECT = () => {
return (
<Project>
<TimeLine>
{/* <Clip> はタイムラインに表示される要素 */}
{/* タイムライン上の長さは <Video/> の長さを自動で反映する(指定も可能) */}
<Clip label="Clip Name">
{/* <Video/> は動画を読み込む */}
<Video video={{ path: "~/Videos/example.mp4" }} />
</Clip>
</TimeLine>
</Project>
)
}
<template>
<Project>
<TimeLine>
<Clip label="Clip Name">
<Video video="~/Videos/example.mp4" />
</Clip>
</TimeLine>
</Project>
</template>
```

## アニメーションAPI
## アニメーション API

`useAnimation`を使うと`async/await`を用いてアニメーションの細かな操作を実現できます
Vue SFC ではフレーム値を reactive に読み、`computed` と scoped CSS でアニメーションを書けます。

```tsx
import { useAnimation, useVariable } from "../src/lib/animation"
```vue
<script setup lang="ts">
import { computed } from "vue"
import { BEZIER_SMOOTH } from "../src/lib/animation/functions"
import { FillFrame } from "../src/lib/layout/fill-frame"
import { seconds } from "../src/lib/frame"

const CircleScene = () => {
// 位置と不透明度をアニメーション可能な変数として保持
const position = useVariable({ x: -300, y: 0 })
const opacity = useVariable(0)

useAnimation(async (ctx) => {
// 同時に動かしたい処理は handle を作って並列で待つ
const move = ctx
.move(position)
.to({ x: 240, y: 0 }, seconds(1.2), BEZIER_SMOOTH)
const fade = ctx.move(opacity).to(1, seconds(0.6), BEZIER_SMOOTH)
await ctx.parallel([move, fade])
}, [])

// 現在フレームに対応した値を取得
const pos = position.use()

return (
<FillFrame style={{ alignItems: "center", justifyContent: "center" }}>
<div
style={{
width: 120,
height: 120,
borderRadius: "999px",
background: "#38bdf8",
opacity: opacity.use(),
transform: `translate(${pos.x}px, ${pos.y}px)`,
boxShadow: "0 20px 60px rgba(56,189,248,0.35)",
}}
/>
import { Clip, FillFrame, seconds, useCurrentFrame } from "../src/lib/vue"

const frame = useCurrentFrame()
const duration = seconds(2)
const circleVars = computed(() => {
const t = BEZIER_SMOOTH(Math.min(1, frame.value / duration))
return {
"--circle-opacity": String(t),
"--circle-x": `${-300 + 540 * t}px`,
}
})
</script>

<template>
<Clip label="Circle" :duration="duration">
<FillFrame class="scene" :style="circleVars">
<div class="circle" />
</FillFrame>
)
</Clip>
</template>

<style scoped>
.scene {
align-items: center;
justify-content: center;

& .circle {
width: 120px;
height: 120px;
border-radius: 999px;
background: #38bdf8;
opacity: var(--circle-opacity);
transform: translateX(var(--circle-x));
box-shadow: 0 20px 60px rgb(56 189 248 / 0.35);
}
}
</style>
```

<img src="circle.gif" alt="circle_move" loop=infinite>

## QuickStart

(実行にはNode.jsが必要です)
実行には Node.js `^20.19.0 || >=22.12.0` と npm `>=10` が必要です。

```bash
npm init @frame-script/latest
cd <project-path>
npm run start
```

`npm run start` はクリーン checkout から動く source/dev モードを起動します。Rust バイナリと render アセットを含む production 近い経路は `npm run start:bin` を使います。

## ドキュメント

- [FrameScript Docs](https://frame-script.github.io/FrameScript/ja)
- [FrameScript.vue docs](./docs/docs/index.md)
- [Production runbook](./docs/docs/production.md)
- [Third-party binary notices](./THIRD_PARTY_NOTICES.md)

FrameScript.vue は upstream FrameScript の考え方を引き継ぎつつ、このリポジトリでは Vue SFC + CSS によるプロジェクト記述を主軸にしています。
Loading
Loading