@sansavision/vidra-player 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -0
- package/dist/engine.d.ts +79 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +183 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/sdk.d.ts +69 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +329 -0
- package/dist/sdk.js.map +1 -0
- package/dist/types.d.ts +150 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
- package/wasm/vidra_wasm.d.ts +91 -0
- package/wasm/vidra_wasm.js +368 -0
- package/wasm/vidra_wasm_bg.wasm +0 -0
- package/wasm/vidra_wasm_bg.wasm.d.ts +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# @sansavision/vidra-player
|
|
2
|
+
|
|
3
|
+
Real-time video rendering in the browser — powered by WebAssembly.
|
|
4
|
+
|
|
5
|
+
Compile VidraScript **or** use the fluent TypeScript/JavaScript SDK to build videos programmatically, then render them at 60fps on a `<canvas>`.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# From the repo root
|
|
11
|
+
cd packages/vidra-player
|
|
12
|
+
npm install
|
|
13
|
+
npm run demo
|
|
14
|
+
# → opens http://localhost:3456/examples/demo.html
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then open **http://localhost:3456/examples/demo.html** in your browser.
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
┌─────────────────────────────────────────────────────┐
|
|
23
|
+
│ Browser │
|
|
24
|
+
│ │
|
|
25
|
+
│ ┌──────────────┐ ┌──────────────────────────┐ │
|
|
26
|
+
│ │ VidraScript │────▶│ WASM Module (vidra-wasm) │ │
|
|
27
|
+
│ │ or JS SDK │ │ │ │
|
|
28
|
+
│ └──────────────┘ │ ┌────────────────────┐ │ │
|
|
29
|
+
│ │ │ Parser + Compiler │ │ │
|
|
30
|
+
│ │ │ (vidra-lang) │ │ │
|
|
31
|
+
│ │ └────────┬───────────┘ │ │
|
|
32
|
+
│ │ ▼ │ │
|
|
33
|
+
│ │ ┌────────────────────┐ │ │
|
|
34
|
+
│ │ │ CPU Renderer │ │ │
|
|
35
|
+
│ │ │ (single-threaded) │ │ │
|
|
36
|
+
│ │ └────────┬───────────┘ │ │
|
|
37
|
+
│ └───────────┼──────────────┘ │
|
|
38
|
+
│ ▼ │
|
|
39
|
+
│ ┌──────────────────────┐ │
|
|
40
|
+
│ │ RGBA pixel data │ │
|
|
41
|
+
│ │ → ImageData │ │
|
|
42
|
+
│ │ → <canvas> │ │
|
|
43
|
+
│ └──────────────────────┘ │
|
|
44
|
+
│ ▲ │
|
|
45
|
+
│ requestAnimationFrame │
|
|
46
|
+
│ (60fps render loop) │
|
|
47
|
+
└─────────────────────────────────────────────────────┘
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Two Input Modes
|
|
51
|
+
|
|
52
|
+
#### 1. VidraScript DSL
|
|
53
|
+
The WASM module includes the full `vidra-lang` parser and compiler. You write `.vidra` syntax, and the WASM module compiles it to IR internally:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
project(1920, 1080, 60) {
|
|
57
|
+
scene("intro", 3s) {
|
|
58
|
+
layer("bg") { solid(#1a1a2e) }
|
|
59
|
+
layer("title") {
|
|
60
|
+
text("Hello!", font: "Inter", size: 100, color: #ffffff)
|
|
61
|
+
position(960, 540)
|
|
62
|
+
animation(opacity, from: 0, to: 1, duration: 1s, easing: easeOut)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### 2. JavaScript/TypeScript SDK
|
|
69
|
+
Build videos using the fluent builder API. The SDK generates IR JSON directly — no VidraScript compilation step needed:
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
import { Project, Scene, Layer, Easing } from "@sansavision/vidra-player";
|
|
73
|
+
|
|
74
|
+
const project = new Project(1920, 1080, 60);
|
|
75
|
+
const scene = new Scene("intro", 3.0);
|
|
76
|
+
scene.addLayers(
|
|
77
|
+
new Layer("bg").solid("#1a1a2e"),
|
|
78
|
+
new Layer("title")
|
|
79
|
+
.text("Hello!", "Inter", 100, "#ffffff")
|
|
80
|
+
.position(960, 540)
|
|
81
|
+
.animate("opacity", 0, 1, 1.0, Easing.EaseOut)
|
|
82
|
+
);
|
|
83
|
+
project.addScene(scene);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Engine API
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { VidraEngine } from "@sansavision/vidra-player";
|
|
90
|
+
|
|
91
|
+
const canvas = document.getElementById("canvas");
|
|
92
|
+
const engine = new VidraEngine(canvas, {
|
|
93
|
+
onReady: () => console.log("WASM loaded"),
|
|
94
|
+
onFrame: (frame) => console.log(`Frame ${frame}`),
|
|
95
|
+
onStateChange: (state) => console.log(`State: ${state}`),
|
|
96
|
+
onError: (err) => console.error(err),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Initialize WASM (call once)
|
|
100
|
+
await engine.init();
|
|
101
|
+
|
|
102
|
+
// Load content (pick one)
|
|
103
|
+
engine.loadSource(vidraScript); // VidraScript string
|
|
104
|
+
engine.loadProject(sdkProject); // SDK Project object
|
|
105
|
+
engine.loadIR(irJsonString); // Raw IR JSON
|
|
106
|
+
|
|
107
|
+
// Playback controls
|
|
108
|
+
engine.play();
|
|
109
|
+
engine.pause();
|
|
110
|
+
engine.stop();
|
|
111
|
+
engine.seekToFrame(120);
|
|
112
|
+
engine.seekToTime(2.0);
|
|
113
|
+
|
|
114
|
+
// State
|
|
115
|
+
engine.getCurrentFrame(); // → number
|
|
116
|
+
engine.getCurrentTime(); // → number (seconds)
|
|
117
|
+
engine.getState(); // → "idle" | "loading" | "playing" | "paused" | "stopped"
|
|
118
|
+
engine.getProjectInfo(); // → { width, height, fps, totalFrames, totalDuration, sceneCount }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Build Commands
|
|
122
|
+
|
|
123
|
+
| Command | Description |
|
|
124
|
+
|---------|-------------|
|
|
125
|
+
| `npm run build` | Compile TypeScript → `dist/` |
|
|
126
|
+
| `npm run build:wasm` | Compile Rust → WASM → `wasm/` |
|
|
127
|
+
| `npm run build:all` | Build WASM + TypeScript |
|
|
128
|
+
| `npm run demo` | Build TS and start local server on port 3456 |
|
|
129
|
+
| `npm run dev` | Alias for `demo` |
|
|
130
|
+
|
|
131
|
+
## Architecture
|
|
132
|
+
|
|
133
|
+
The WASM module (`vidra-wasm`) is a standalone Rust crate that bundles:
|
|
134
|
+
- **vidra-lang**: VidraScript lexer, parser, and compiler
|
|
135
|
+
- **vidra-core**: Frame buffers, color types, duration types
|
|
136
|
+
- **vidra-ir**: Intermediate representation for the scene graph
|
|
137
|
+
- A **CPU-only renderer** (simplified from `vidra-render`, no GPU dependencies)
|
|
138
|
+
|
|
139
|
+
It compiles to ~2MB of WASM via `wasm-pack` and exposes these functions:
|
|
140
|
+
- `parse_and_compile(source)` → IR JSON string
|
|
141
|
+
- `render_frame(irJson, frameIndex)` → RGBA `Uint8Array`
|
|
142
|
+
- `get_project_info(irJson)` → metadata JSON
|
|
143
|
+
- `load_image_asset(id, bytes)` → cache image for rendering
|
|
144
|
+
|
|
145
|
+
The JavaScript `VidraEngine` class wraps these calls in a `requestAnimationFrame` loop, pushing RGBA pixel data to a 2D canvas via `ImageData`.
|
|
146
|
+
|
|
147
|
+
## Requirements
|
|
148
|
+
|
|
149
|
+
- Browser with WebAssembly support (all modern browsers)
|
|
150
|
+
- For rebuilding WASM: Rust + `wasm-pack`
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export interface ProjectInfo {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
fps: number;
|
|
5
|
+
totalFrames: number;
|
|
6
|
+
totalDuration: number;
|
|
7
|
+
sceneCount: number;
|
|
8
|
+
}
|
|
9
|
+
export type PlayerState = "idle" | "loading" | "playing" | "paused" | "stopped";
|
|
10
|
+
export interface EngineEvents {
|
|
11
|
+
onReady?: () => void;
|
|
12
|
+
onFrame?: (frame: number) => void;
|
|
13
|
+
onStateChange?: (state: PlayerState) => void;
|
|
14
|
+
onError?: (error: string) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare class VidraEngine {
|
|
17
|
+
private canvas;
|
|
18
|
+
private ctx2d;
|
|
19
|
+
private irJson;
|
|
20
|
+
private info;
|
|
21
|
+
private currentFrame;
|
|
22
|
+
private animId;
|
|
23
|
+
private state;
|
|
24
|
+
private lastFrameTime;
|
|
25
|
+
private events;
|
|
26
|
+
private wasmReady;
|
|
27
|
+
constructor(canvas: HTMLCanvasElement, events?: EngineEvents);
|
|
28
|
+
/** Initialize the WASM module. Must be called once before any rendering. */
|
|
29
|
+
init(): Promise<void>;
|
|
30
|
+
/** Get the WASM engine version. */
|
|
31
|
+
getVersion(): string;
|
|
32
|
+
/** Load a VidraScript source string, compile it, and prepare for rendering. */
|
|
33
|
+
loadSource(source: string): ProjectInfo;
|
|
34
|
+
/** Load pre-compiled IR JSON directly. */
|
|
35
|
+
loadIR(irJson: string): ProjectInfo;
|
|
36
|
+
/**
|
|
37
|
+
* Load a Project built with the `@sansavision/vidra-sdk` builder API.
|
|
38
|
+
*
|
|
39
|
+
* Accepts any object that has either:
|
|
40
|
+
* - `.toJSONString()` → returns IR JSON string
|
|
41
|
+
* - `.toJSON()` → returns IR object (will be JSON.stringify'd)
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { Project, Scene, Layer } from "@sansavision/vidra-player";
|
|
46
|
+
* const project = new Project(1920, 1080, 60);
|
|
47
|
+
* project.addScene(new Scene("s1", 3).addLayer(new Layer("bg").solid("#1a1a2e")));
|
|
48
|
+
* engine.loadProject(project);
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
loadProject(project: {
|
|
52
|
+
toJSONString?: () => string;
|
|
53
|
+
toJSON?: () => unknown;
|
|
54
|
+
}): ProjectInfo;
|
|
55
|
+
/** Load an image asset into the WASM renderer cache. */
|
|
56
|
+
loadImageAsset(assetId: string, url: string): Promise<void>;
|
|
57
|
+
/** Start playback from the current frame. */
|
|
58
|
+
play(): void;
|
|
59
|
+
/** Pause playback. */
|
|
60
|
+
pause(): void;
|
|
61
|
+
/** Stop playback and reset to frame 0. */
|
|
62
|
+
stop(): void;
|
|
63
|
+
/** Seek to a specific frame. */
|
|
64
|
+
seekToFrame(frame: number): void;
|
|
65
|
+
/** Seek to a specific time in seconds. */
|
|
66
|
+
seekToTime(seconds: number): void;
|
|
67
|
+
/** Get the current frame index. */
|
|
68
|
+
getCurrentFrame(): number;
|
|
69
|
+
/** Get the current time in seconds. */
|
|
70
|
+
getCurrentTime(): number;
|
|
71
|
+
/** Get the player state. */
|
|
72
|
+
getState(): PlayerState;
|
|
73
|
+
/** Get project info. */
|
|
74
|
+
getProjectInfo(): ProjectInfo | null;
|
|
75
|
+
private setState;
|
|
76
|
+
private tick;
|
|
77
|
+
private renderCurrentFrame;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhF,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,qBAAa,WAAW;IACpB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAkB;gBAEvB,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAE,YAAiB;IAMhE,4EAA4E;IACtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,mCAAmC;IACnC,UAAU,IAAI,MAAM;IAIpB,+EAA+E;IAC/E,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;IAmBvC,0CAA0C;IAC1C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;IAkBnC;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,OAAO,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAA;KAAE,GAAG,WAAW;IAa1F,wDAAwD;IAClD,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,6CAA6C;IAC7C,IAAI,IAAI,IAAI;IAOZ,sBAAsB;IACtB,KAAK,IAAI,IAAI;IAKb,0CAA0C;IAC1C,IAAI,IAAI,IAAI;IAOZ,gCAAgC;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMhC,0CAA0C;IAC1C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMjC,mCAAmC;IACnC,eAAe,IAAI,MAAM;IAIzB,uCAAuC;IACvC,cAAc,IAAI,MAAM;IAKxB,4BAA4B;IAC5B,QAAQ,IAAI,WAAW;IAIvB,wBAAwB;IACxB,cAAc,IAAI,WAAW,GAAG,IAAI;IAMpC,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,IAAI,CAkBV;IAEF,OAAO,CAAC,kBAAkB;CAe7B"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// ─── Vidra Engine — WASM Loader & Render Loop ─────────────────────
|
|
2
|
+
// This module loads the WASM module, manages the <canvas>, and drives
|
|
3
|
+
// the requestAnimationFrame render loop.
|
|
4
|
+
import init, { parse_and_compile, render_frame, get_project_info, load_image_asset, version, } from "../wasm/vidra_wasm.js";
|
|
5
|
+
export class VidraEngine {
|
|
6
|
+
canvas;
|
|
7
|
+
ctx2d;
|
|
8
|
+
irJson = null;
|
|
9
|
+
info = null;
|
|
10
|
+
currentFrame = 0;
|
|
11
|
+
animId = 0;
|
|
12
|
+
state = "idle";
|
|
13
|
+
lastFrameTime = 0;
|
|
14
|
+
events;
|
|
15
|
+
wasmReady = false;
|
|
16
|
+
constructor(canvas, events = {}) {
|
|
17
|
+
this.canvas = canvas;
|
|
18
|
+
this.ctx2d = canvas.getContext("2d");
|
|
19
|
+
this.events = events;
|
|
20
|
+
}
|
|
21
|
+
/** Initialize the WASM module. Must be called once before any rendering. */
|
|
22
|
+
async init() {
|
|
23
|
+
await init();
|
|
24
|
+
this.wasmReady = true;
|
|
25
|
+
this.setState("idle");
|
|
26
|
+
this.events.onReady?.();
|
|
27
|
+
}
|
|
28
|
+
/** Get the WASM engine version. */
|
|
29
|
+
getVersion() {
|
|
30
|
+
return version();
|
|
31
|
+
}
|
|
32
|
+
/** Load a VidraScript source string, compile it, and prepare for rendering. */
|
|
33
|
+
loadSource(source) {
|
|
34
|
+
if (!this.wasmReady)
|
|
35
|
+
throw new Error("Engine not initialized. Call init() first.");
|
|
36
|
+
this.setState("loading");
|
|
37
|
+
this.irJson = parse_and_compile(source);
|
|
38
|
+
const rawInfo = get_project_info(this.irJson);
|
|
39
|
+
this.info = JSON.parse(rawInfo);
|
|
40
|
+
// Size the canvas to match the project
|
|
41
|
+
this.canvas.width = this.info.width;
|
|
42
|
+
this.canvas.height = this.info.height;
|
|
43
|
+
this.currentFrame = 0;
|
|
44
|
+
this.setState("paused");
|
|
45
|
+
this.renderCurrentFrame();
|
|
46
|
+
return this.info;
|
|
47
|
+
}
|
|
48
|
+
/** Load pre-compiled IR JSON directly. */
|
|
49
|
+
loadIR(irJson) {
|
|
50
|
+
if (!this.wasmReady)
|
|
51
|
+
throw new Error("Engine not initialized. Call init() first.");
|
|
52
|
+
this.setState("loading");
|
|
53
|
+
this.irJson = irJson;
|
|
54
|
+
const rawInfo = get_project_info(irJson);
|
|
55
|
+
this.info = JSON.parse(rawInfo);
|
|
56
|
+
this.canvas.width = this.info.width;
|
|
57
|
+
this.canvas.height = this.info.height;
|
|
58
|
+
this.currentFrame = 0;
|
|
59
|
+
this.setState("paused");
|
|
60
|
+
this.renderCurrentFrame();
|
|
61
|
+
return this.info;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Load a Project built with the `@sansavision/vidra-sdk` builder API.
|
|
65
|
+
*
|
|
66
|
+
* Accepts any object that has either:
|
|
67
|
+
* - `.toJSONString()` → returns IR JSON string
|
|
68
|
+
* - `.toJSON()` → returns IR object (will be JSON.stringify'd)
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { Project, Scene, Layer } from "@sansavision/vidra-player";
|
|
73
|
+
* const project = new Project(1920, 1080, 60);
|
|
74
|
+
* project.addScene(new Scene("s1", 3).addLayer(new Layer("bg").solid("#1a1a2e")));
|
|
75
|
+
* engine.loadProject(project);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
loadProject(project) {
|
|
79
|
+
let irJson;
|
|
80
|
+
if (typeof project.toJSONString === "function") {
|
|
81
|
+
irJson = project.toJSONString();
|
|
82
|
+
}
|
|
83
|
+
else if (typeof project.toJSON === "function") {
|
|
84
|
+
irJson = JSON.stringify(project.toJSON());
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Last resort — try to stringify the entire object
|
|
88
|
+
irJson = JSON.stringify(project);
|
|
89
|
+
}
|
|
90
|
+
return this.loadIR(irJson);
|
|
91
|
+
}
|
|
92
|
+
/** Load an image asset into the WASM renderer cache. */
|
|
93
|
+
async loadImageAsset(assetId, url) {
|
|
94
|
+
const response = await fetch(url);
|
|
95
|
+
const buffer = await response.arrayBuffer();
|
|
96
|
+
load_image_asset(assetId, new Uint8Array(buffer));
|
|
97
|
+
}
|
|
98
|
+
/** Start playback from the current frame. */
|
|
99
|
+
play() {
|
|
100
|
+
if (!this.irJson || !this.info)
|
|
101
|
+
return;
|
|
102
|
+
this.setState("playing");
|
|
103
|
+
this.lastFrameTime = performance.now();
|
|
104
|
+
this.tick();
|
|
105
|
+
}
|
|
106
|
+
/** Pause playback. */
|
|
107
|
+
pause() {
|
|
108
|
+
this.setState("paused");
|
|
109
|
+
cancelAnimationFrame(this.animId);
|
|
110
|
+
}
|
|
111
|
+
/** Stop playback and reset to frame 0. */
|
|
112
|
+
stop() {
|
|
113
|
+
cancelAnimationFrame(this.animId);
|
|
114
|
+
this.currentFrame = 0;
|
|
115
|
+
this.setState("stopped");
|
|
116
|
+
this.renderCurrentFrame();
|
|
117
|
+
}
|
|
118
|
+
/** Seek to a specific frame. */
|
|
119
|
+
seekToFrame(frame) {
|
|
120
|
+
this.currentFrame = Math.max(0, Math.min(frame, (this.info?.totalFrames ?? 1) - 1));
|
|
121
|
+
this.renderCurrentFrame();
|
|
122
|
+
this.events.onFrame?.(this.currentFrame);
|
|
123
|
+
}
|
|
124
|
+
/** Seek to a specific time in seconds. */
|
|
125
|
+
seekToTime(seconds) {
|
|
126
|
+
if (!this.info)
|
|
127
|
+
return;
|
|
128
|
+
const frame = Math.floor(seconds * this.info.fps);
|
|
129
|
+
this.seekToFrame(frame);
|
|
130
|
+
}
|
|
131
|
+
/** Get the current frame index. */
|
|
132
|
+
getCurrentFrame() {
|
|
133
|
+
return this.currentFrame;
|
|
134
|
+
}
|
|
135
|
+
/** Get the current time in seconds. */
|
|
136
|
+
getCurrentTime() {
|
|
137
|
+
if (!this.info)
|
|
138
|
+
return 0;
|
|
139
|
+
return this.currentFrame / this.info.fps;
|
|
140
|
+
}
|
|
141
|
+
/** Get the player state. */
|
|
142
|
+
getState() {
|
|
143
|
+
return this.state;
|
|
144
|
+
}
|
|
145
|
+
/** Get project info. */
|
|
146
|
+
getProjectInfo() {
|
|
147
|
+
return this.info;
|
|
148
|
+
}
|
|
149
|
+
// ── Internal ─────────────────────────────────────────────────
|
|
150
|
+
setState(state) {
|
|
151
|
+
this.state = state;
|
|
152
|
+
this.events.onStateChange?.(state);
|
|
153
|
+
}
|
|
154
|
+
tick = () => {
|
|
155
|
+
if (this.state !== "playing" || !this.info)
|
|
156
|
+
return;
|
|
157
|
+
const now = performance.now();
|
|
158
|
+
const frameDurationMs = 1000 / this.info.fps;
|
|
159
|
+
if (now - this.lastFrameTime >= frameDurationMs) {
|
|
160
|
+
this.renderCurrentFrame();
|
|
161
|
+
this.events.onFrame?.(this.currentFrame);
|
|
162
|
+
this.currentFrame++;
|
|
163
|
+
if (this.currentFrame >= this.info.totalFrames) {
|
|
164
|
+
this.currentFrame = 0; // Loop
|
|
165
|
+
}
|
|
166
|
+
this.lastFrameTime = now;
|
|
167
|
+
}
|
|
168
|
+
this.animId = requestAnimationFrame(this.tick);
|
|
169
|
+
};
|
|
170
|
+
renderCurrentFrame() {
|
|
171
|
+
if (!this.irJson || !this.info)
|
|
172
|
+
return;
|
|
173
|
+
try {
|
|
174
|
+
const rgba = render_frame(this.irJson, this.currentFrame);
|
|
175
|
+
const imageData = new ImageData(new Uint8ClampedArray(rgba), this.info.width, this.info.height);
|
|
176
|
+
this.ctx2d.putImageData(imageData, 0, 0);
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
this.events.onError?.(String(e));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1E,OAAO,EACH,OAAO,EACP,KAAK,EACL,KAAK,EACL,MAAM,EACN,GAAG,EACH,IAAI,GACP,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// ─── Vidra Player — Main Exports ────────────────────────────────
|
|
2
|
+
// Engine (WASM-powered renderer)
|
|
3
|
+
export { VidraEngine } from "./engine.js";
|
|
4
|
+
// Re-export the entire SDK so devs only need one package
|
|
5
|
+
export { Project, Scene, Layer, Easing, hex, rgba, } from "./sdk.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,iCAAiC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,yDAAyD;AACzD,OAAO,EACH,OAAO,EACP,KAAK,EACL,KAAK,EACL,MAAM,EACN,GAAG,EACH,IAAI,GACP,MAAM,UAAU,CAAC"}
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ProjectIR, SceneIR, LayerIR, AnimatableProperty, Easing as EasingType, Color, AssetType } from "./types.js";
|
|
2
|
+
export type * from "./types.js";
|
|
3
|
+
export declare function rgba(r: number, g: number, b: number, a?: number): Color;
|
|
4
|
+
export declare function hex(hexCode: string): Color;
|
|
5
|
+
export declare const Easing: {
|
|
6
|
+
readonly Linear: EasingType;
|
|
7
|
+
readonly EaseIn: EasingType;
|
|
8
|
+
readonly EaseOut: EasingType;
|
|
9
|
+
readonly EaseInOut: EasingType;
|
|
10
|
+
readonly CubicIn: EasingType;
|
|
11
|
+
readonly CubicOut: EasingType;
|
|
12
|
+
readonly CubicInOut: EasingType;
|
|
13
|
+
readonly Step: EasingType;
|
|
14
|
+
};
|
|
15
|
+
export declare class Layer {
|
|
16
|
+
private _layer;
|
|
17
|
+
constructor(id: string);
|
|
18
|
+
text(content: string, fontFamily?: string, fontSize?: number, color?: string | Color): this;
|
|
19
|
+
solid(color: string | Color): this;
|
|
20
|
+
image(assetId: string): this;
|
|
21
|
+
video(assetId: string, trimStart?: number, trimEnd?: number): this;
|
|
22
|
+
audio(assetId: string, volume?: number, trimStart?: number, trimEnd?: number): this;
|
|
23
|
+
shape(type: "rect", opts: {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
radius?: number;
|
|
27
|
+
fill?: string | Color;
|
|
28
|
+
}): this;
|
|
29
|
+
shape(type: "circle", opts: {
|
|
30
|
+
radius: number;
|
|
31
|
+
fill?: string | Color;
|
|
32
|
+
}): this;
|
|
33
|
+
shape(type: "ellipse", opts: {
|
|
34
|
+
rx: number;
|
|
35
|
+
ry: number;
|
|
36
|
+
fill?: string | Color;
|
|
37
|
+
}): this;
|
|
38
|
+
tts(content: string, voice?: string, volume?: number): this;
|
|
39
|
+
position(x: number, y: number): this;
|
|
40
|
+
scale(factor: number): this;
|
|
41
|
+
scale(x: number, y: number): this;
|
|
42
|
+
rotation(degrees: number): this;
|
|
43
|
+
opacity(value: number): this;
|
|
44
|
+
anchor(x: number, y: number): this;
|
|
45
|
+
animate(property: AnimatableProperty | "positionX" | "positionY" | "scaleX" | "scaleY" | "rotation" | "opacity", from: number, to: number, durationSec: number, easing?: EasingType, delaySec?: number): this;
|
|
46
|
+
blur(radius: number): this;
|
|
47
|
+
dropShadow(offsetX: number, offsetY: number, blur: number, color?: string | Color): this;
|
|
48
|
+
addChild(child: Layer): this;
|
|
49
|
+
build(): LayerIR;
|
|
50
|
+
}
|
|
51
|
+
export declare class Scene {
|
|
52
|
+
private _scene;
|
|
53
|
+
constructor(id: string, durationSec: number);
|
|
54
|
+
addLayer(layer: Layer): this;
|
|
55
|
+
addLayers(...layers: Layer[]): this;
|
|
56
|
+
build(): SceneIR;
|
|
57
|
+
}
|
|
58
|
+
export declare class Project {
|
|
59
|
+
private _project;
|
|
60
|
+
constructor(width: number, height: number, fps: number);
|
|
61
|
+
background(color: string | Color): this;
|
|
62
|
+
addAsset(type: AssetType, id: string, path: string, name?: string): this;
|
|
63
|
+
addScene(scene: Scene): this;
|
|
64
|
+
toJSON(): ProjectIR;
|
|
65
|
+
toJSONString(pretty?: boolean): string;
|
|
66
|
+
toVidraScript(): string;
|
|
67
|
+
private _emitLayer;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
|