<p align="center">
<img src="https://raw.githubusercontent.com/sjkim1127/Dioxuscut/main/assets/logo.svg" alt="Dioxuscut" width="100%" />
</p>
<p align="center">
<b>Browser-free, code-driven video rendering in Rust, with Dioxus preview components.</b>
</p>
<p align="center">
<a href="https://github.com/sjkim1127/Dioxuscut/actions/workflows/ci.yml"><img src="https://github.com/sjkim1127/Dioxuscut/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
<a href="#license"><img src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-4ec9b0?style=flat-square" alt="License" /></a>
<a href="https://dioxuslabs.com/"><img src="https://img.shields.io/badge/Dioxus-0.6-e05c4b?style=flat-square&logo=rust&logoColor=white" alt="Dioxus 0.6" /></a>
<img src="https://img.shields.io/badge/status-early%20development-f59e0b?style=flat-square" alt="Early development" />
</p>
Dioxuscut is an early-stage programmatic video toolkit written in Rust. Its native export path renders a registered `NativeComposition` into a small scene graph, rasterizes frames with `tiny-skia` or `wgpu`, and sends bounded batches of raw RGBA frames to FFmpeg.
The repository also contains Dioxus timeline, media, shape, transition, player, and Studio-preview components. These components currently form the interactive preview layer; arbitrary Dioxus VDOM is **not yet automatically translated** into the native scene graph.
## What works today
- Native scene graph with rectangles, circles, paths, text, gradients, and transformed groups.
- CPU rendering through `tiny-skia`.
- Experimental GPU rendering through `wgpu`; unsupported scene features fall back to the CPU renderer for correctness.
- Bounded-memory parallel frame rendering into an FFmpeg stdin pipe.
- Registry-based Rust compositions and optional sandboxed Rhai compositions, both with JSON props.
- Animation, shape, path, caption, noise, timeline, player, server, encoder, and CLI test coverage.
- Dioxus web example and desktop Studio preview shell.
## Architecture
```text
Native export
RenderRequest
-> CompositionRegistry or compiled Rhai AST
-> Composition::prepare(props, context)
-> PreparedComposition::render(frame)
-> Scene
-> TinySkiaBackend / WgpuBackend with CPU fallback
-> bounded ordered RGBA batches
-> FFmpeg
-> MP4
Dioxus preview
Composition / Sequence / Freeze / media / shapes
-> Player
-> Dioxus web or desktop UI
```
The two paths intentionally have an explicit boundary. A shared declarative adapter between Dioxus components and native `Scene` output remains roadmap work.
## Workspace
| `dioxuscut-animation` | Interpolation, easing, springs, and color interpolation |
| `dioxuscut-core` | Dioxus composition timeline, sequence, freeze, and hooks |
| `dioxuscut-media` | Dioxus image, video, and audio elements for preview |
| `dioxuscut-player` | Interactive Dioxus player and controls |
| `dioxuscut-shapes` | Procedural SVG shapes |
| `dioxuscut-paths` | SVG path parsing, metrics, and transforms |
| `dioxuscut-captions` | SRT parsing and kinetic caption helpers |
| `dioxuscut-noise` | Deterministic simplex noise helpers |
| `dioxuscut-transitions` | Dioxus fade and slide transitions |
| `dioxuscut-rasterizer` | Scene IR, CPU renderer, experimental GPU renderer, FFmpeg pipe |
| `dioxuscut-renderer` | Static server and PNG-sequence encoding utilities |
| `dioxuscut-cli` | Composition registry and `dioxuscut render` command |
| `apps/example` | Dioxus web composition preview |
| `apps/studio` | Desktop preview shell; editing and render queue are planned |
## Prerequisites
- A current stable Rust toolchain.
- FFmpeg available on `PATH` for MP4 output.
- A supported native GPU only when using `--backend gpu`.
Install FFmpeg on common platforms:
```bash
brew install ffmpeg # macOS
sudo apt-get install -y ffmpeg # Debian / Ubuntu
choco install ffmpeg -y # Windows
```
## Quickstart
The standalone CLI ships with the `HelloWorld` native composition:
```bash
printf '%s\n' '{
"title": "Hello Dioxuscut",
"subtitle": "Bounded native rendering",
"background_start": "#0f172a",
"background_end": "#1e1b4b",
"accent_color": "#6c63ff"
}' > props.json
cargo run -p dioxuscut-cli -- render \
--composition HelloWorld \
--props props.json \
--output output.mp4 \
--width 1280 \
--height 720 \
--fps 30 \
--duration 150
```
An unknown composition ID or malformed props file fails before FFmpeg starts.
## Rhai compositions
The optional `rhai` feature adds scriptable composition logic while preserving
JSON as the external data contract. Scripts are compiled once per render job,
receive `ctx` and `props`, and return a restricted native scene builder:
```bash
cargo run -p dioxuscut-cli --features rhai -- render \
--script examples/hello.rhai \
--props examples/hello-props.json \
--output rhai-output.mp4 \
--width 1280 \
--height 720 \
--duration 150
```
Each script defines `fn render(ctx, props)`. The context contains `frame`,
`width`, `height`, `fps`, `duration`, and normalized `progress`. The initial API
exposes `scene()`, `rect`, `round_rect`, `circle`, `text`, `text_bold`, `group`,
and `interpolate`. See [`examples/hello.rhai`](examples/hello.rhai) for a complete
composition.
The runtime disables module imports and limits operations, call depth,
expression depth, variables, functions, strings, arrays, and maps. It does not
expose filesystem, network, clock, or random APIs. A new Rhai scope is created
for every frame so parallel rendering does not share mutable script state.
## Registering a native composition
Applications can use `dioxuscut-cli` as a library and provide their own registry:
```rust,ignore
use dioxuscut_cli::{
execute_render_command_with_registry, CompositionError, CompositionRegistry,
NativeComposition, NativeCompositionContext, RenderRequest,
};
use dioxuscut_rasterizer::{Color, Scene, SceneNode};
use serde_json::Value;
struct TitleCard;
impl NativeComposition for TitleCard {
fn id(&self) -> &str {
"TitleCard"
}
fn render(
&self,
frame: u32,
_props: &Value,
context: NativeCompositionContext,
) -> Result<Scene, CompositionError> {
let mut scene = Scene::new();
scene.push(SceneNode::Rect {
x: 0.0,
y: 0.0,
w: context.width as f32,
h: context.height as f32,
fill: Color::rgb(frame as u8, 24, 48),
stroke: None,
stroke_width: 0.0,
corner_radius: 0.0,
});
Ok(scene)
}
}
// Register TitleCard, construct a RenderRequest, then call:
// execute_render_command_with_registry(&request, ®istry).await?;
```
## CLI reference
```text
-c, --composition <ID> Registered composition ID
--script <PATH> Rhai composition file; requires feature `rhai`
-p, --props <PATH> JSON props file
-o, --output <PATH> Output path [default: out.mp4]
--width <PX> Even output width [default: 1920]
--height <PX> Even output height [default: 1080]
--fps <FPS> Finite positive FPS [default: 30]
--duration <FRAMES> Positive frame count [default: 150]
--backend <BACKEND> native or gpu [default: native]
```
Build GPU support explicitly:
```bash
cargo build -p dioxuscut-cli --features gpu
```
Build Rhai and GPU support together with `--features rhai,gpu`.
## Testing
The project treats default and optional-feature builds as required quality gates:
```bash
cargo fmt --all -- --check
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
cargo check --locked --workspace --all-targets --all-features
cargo test --locked --workspace --all-features
```
The acceptance test requires FFmpeg and produces a real MP4 before checking its container signature.
## Releasing
Releases are driven by a version tag such as `v0.1.0`. The release workflow
validates the tag against the Cargo workspace version, tests the complete
workspace, publishes all public `dioxuscut-*` packages to crates.io in dependency
order, builds Rhai-enabled CLI archives for Linux, macOS, and Windows, and then
creates one GitHub Release with SHA-256 checksums.
Repository maintainers must configure a crates.io API token as the GitHub Actions
secret `CRATES_IO_TOKEN`. Tokens must never be committed, placed in a tag, or
written into workflow files.
## Current limitations
- Dioxus VDOM compositions and native `Scene` compositions are not yet one representation.
- Native video/audio decoding and audio muxing are not implemented.
- GPU acceleration covers a subset of scene primitives and uses whole-frame CPU fallback otherwise.
- Font discovery uses platform fonts, so pixel-identical cross-platform text output is not guaranteed.
- Studio is a preview shell, not yet a full editor.
## Roadmap
1. Shared composition representation for Dioxus preview and native export.
2. Explicit font assets and fallback chains for reproducible text.
3. Native image/video decoding and FFmpeg audio muxing.
4. Full GPU parity for paths, text, groups, strokes, and multi-stop gradients.
5. Studio project loading, editing, and render queue integration.
## License
Licensed under either [Apache License 2.0](LICENSE) or [MIT License](LICENSE-MIT), at your option.