Artidor
Proyek dari daftar awesome-indonesia.
This project was built almost entirely by AI (Claude, GPT, and other LLMs). The code, architecture, and documentation were largely generated, reviewed, and iterated by AI agents with human oversight. Use at your own risk — thorough review before production use is strongly recommended.
Local-first · MIT-licensed · No uploads · No paywalls · AI-native
Website · Quick start · Features · AI Co-Pilot · Issues · Discord
Most "free" video editors are paywalled. The rest upload your footage to a server you don't control. The ones that don't are unusable.
Artidor does the obvious things:
No manifesto. No "rethinking the creative process." Just a tool that works.
TICKS_PER_SECOND = 120_000 for lossless time math at 24/25/29.97/30/50/59.94/60/120 fpsMediaRecorder chunks, no full downloadArtidor ships with an AI panel in the left bar (under Assets). The Co-Pilot speaks every command the editor speaks — split, trim, retime, keyframe, transition, color-grade, import, export — and dispatches them as tool calls against the live editor.
Three things set it apart from "AI edits your video" toys:
The Co-Pilot doesn't transcribe your prompt and run a script. It has 40+ typed tools — set_project_fps, insert_text_element, upsert_keyframe, apply_preset, export_project — each one wraps a real EditorCore method. The LLM can't hallucinate outside the editor's surface.
Every command you fire (via mouse, keyboard, or the AI) is logged to a 500-event telemetry store. The Co-Pilot's system prompt includes your last 20 edits — cut pattern, easing, pacing — so its suggestions match your style instead of generic.
Drop a finished video into the AI panel. The style extractor runs entirely client-side:
StyleProfile injected into the promptThe Co-Pilot then imitates that pacing on your timeline.
# .env.local — pick ONE
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
OLLAMA_BASE_URL=http://localhost:11434 # local
If no key is set, the panel still opens — it just tells you on the first send.
Prerequisites: Bun ≥ 1.2.18. Docker is optional (for cloud features like collab).
git clone https://github.com/Aofsnorth/Artidor.git
cd Artidor
bun install
bun dev:web
Open http://localhost:3000. Projects live in IndexedDB; nothing leaves your machine.
git clone https://github.com/Aofsnorth/Artidor.git
cd Artidor
docker compose up -d db redis serverless-redis-http
cp apps/web/.env.example apps/web/.env.local
bun install
bun dev:web
The default .env.example works out of the box — Postgres + Redis are auto-created with dev credentials. The offline editor works without any of this.
# Build the WASM module once
bun run build:wasm
cd rust/wasm/pkg && bun link
cd ../../apps/web && bun link artidor-wasm
# Or: rebuild on every change
bun dev:wasm # in a second terminal
bun dev:web # in the first
apps/desktop uses GPUI. See apps/desktop/README.md for the Rust toolchain.
Artidor/
├─ apps/
│ ├─ web/ Next.js 16 + React 19 frontend
│ │ ├─ src/
│ │ │ ├─ app/ Routes, layouts, server components
│ │ │ │ ├─ api/ API routes (ai, auth, drive, github, …)
│ │ │ │ ├─ editor/ /editor/[project_id] — the workspace
│ │ │ │ └─ projects/ /projects — the dashboard
│ │ │ ├─ components/ UI shell — no domain logic
│ │ │ │ └─ editor/panels/ Asset / properties / timeline
│ │ │ ├─ core/ EditorCore facade + 14 managers
│ │ │ ├─ hooks/ React bindings
│ │ │ ├─ lib/
│ │ │ │ ├─ ai/ AI Co-Pilot (provider, tools, telemetry, style)
│ │ │ │ ├─ timeline/ Timeline types
│ │ │ │ └─ export/ MediaRecorder pipelines
│ │ │ └─ stores/ Zustand stores
│ │ └─ public/ Static assets (logos, fonts, screenshots)
│ └─ desktop/ GPUI shell — same Rust core
│
├─ rust/
│ ├─ wasm/ Compiles to artidor-wasm npm package
│ └─ crates/ Workspace crates
│ ├─ bridge/ #[export] proc-macro → wasm_bindgen
│ ├─ time/ MediaTime, FrameRate, Easing, keyframes
│ ├─ gpu/ wgpu device + pipeline cache
│ ├─ compositor/ Scene graph + draw ordering
│ ├─ effects/ Effect definitions + parameter trees
│ └─ masks/ Mask shapes + compositing
│
├─ docs/ Architecture notes
└─ .github/ CI, issue templates, contributing
Rule of thumb: if it's not a UI concern, it goes in rust/. Every line of business logic in apps/web/src/core/ is a migration in progress.
The app works fully offline with no environment variables. The defaults in apps/web/.env.example cover local dev. Cloud / AI features need these:
| Variable | Required for | Default |
|---|---|---|
OPENAI_API_KEY |
AI Co-Pilot (GPT) | — |
ANTHROPIC_API_KEY |
AI Co-Pilot (Claude) | — |
OLLAMA_BASE_URL |
AI Co-Pilot (local) | http://localhost:11434 |
GITHUB_TOKEN |
Higher GitHub API rate (5k/hr) | — |
DATABASE_URL |
Postgres (cloud features) | postgresql://artidor:artidor@localhost:5432/artidor |
BETTER_AUTH_SECRET |
Auth | dev-only fallback |
UPSTASH_REDIS_REST_URL |
Redis | http://localhost:8079 |
UPSTASH_REDIS_REST_TOKEN |
Redis | dev-only fallback |
FREESOUND_CLIENT_ID |
Sound search | — |
FREESOUND_KEY |
Sound search | — |
rust/crates/time exposes MediaTime(i64) wrapping ticks at TICKS_PER_SECOND = 120_000. That divides cleanly into every supported framerate (24/25/29.97/30/50/59.94/60/120), so frame boundaries are never fractional.rust/. Frontends are replaceable; the core is not. #[export] on a Rust function turns into #[wasm_bindgen(js_name = "camelCase")] automatically.apps/web/src/core/ facade is a thin wrapper over the Rust core. Components own rendering, never domain rules.localStorage. The LLM sees your last 20 edits and matches them.motion/react only for orchestration; everything else is transition + CSS variables.| Script | What it does |
|---|---|
bun dev:web |
Next.js dev server on :3000 |
bun dev:wasm |
cargo watch rebuilds the Rust → WASM package on every change |
bun run build:web |
Production build of the web app |
bun run build:wasm |
One-shot WASM build |
bun run lint:web |
Biome lint |
bun run lint:web:fix |
Biome lint with --write --unsafe |
bun run format:web |
Biome format (renderer dir) |
bun run test |
Bun test runner |
bun run preview:web |
Next.js production preview |
bun run publish:wasm |
Build + publish artidor-wasm to npm |
bun run generate:fonts |
Regenerate the font sprite chunks in public/ |
Two rules:
aria-* beats div. CSS transition beats an animation lib. Postgres constraints beat app code. A Rust iterator beats a JS one.rust/, UI goes in apps/. If you find yourself putting a domain rule in a React component, move it.Before opening a PR:
bun run lint:web (and lint:web:fix for what biome can repair)bun run test (Bun test runner)cd apps/web && bunx tsc --noEmit (no type errors)For larger changes, open an issue first so we can agree on direction. See .github/CONTRIBUTING.md for the rest.
MIT. Use it, fork it, ship a competitor, whatever.
Built on the foundation of OpenCut — same MIT license, same DNA. All Rust core is original Artidor work.
Built in public · The repo is the brand