@twick/browser-render 0.15.6 → 0.15.8
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 +63 -25
- package/dist/index.d.mts +225 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +747 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +708 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +15 -8
- package/public/audio-worker.js +1 -4
- package/public/mp4-wasm.wasm +0 -0
- package/AUDIO_IMPLEMENTATION.md +0 -217
- package/package.json.bak +0 -53
- package/src/audio/audio-processor.ts +0 -239
- package/src/audio/audio-video-muxer.ts +0 -79
- package/src/browser-renderer.ts +0 -495
- package/src/hooks/use-browser-renderer.ts +0 -218
- package/src/index.ts +0 -20
- package/src/mp4-wasm.d.ts +0 -4
- package/tsconfig.json +0 -23
- package/tsup.config.ts +0 -19
package/README.md
CHANGED
|
@@ -46,19 +46,21 @@ a.click();
|
|
|
46
46
|
import { useBrowserRenderer } from '@twick/browser-render';
|
|
47
47
|
|
|
48
48
|
function VideoRenderer() {
|
|
49
|
-
const { render, progress, isRendering, videoBlob, download } =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
const { render, progress, isRendering, videoBlob, download, error, reset } =
|
|
50
|
+
useBrowserRenderer({
|
|
51
|
+
width: 720,
|
|
52
|
+
height: 1280,
|
|
53
|
+
fps: 30,
|
|
54
|
+
includeAudio: true, // enable audio rendering + FFmpeg mux
|
|
55
|
+
autoDownload: true, // auto-download final MP4
|
|
56
|
+
});
|
|
55
57
|
|
|
56
58
|
const handleRender = async () => {
|
|
57
59
|
await render({
|
|
58
60
|
input: {
|
|
59
|
-
properties: { width:
|
|
60
|
-
tracks: [/* ... */]
|
|
61
|
-
}
|
|
61
|
+
properties: { width: 720, height: 1280, fps: 30 },
|
|
62
|
+
tracks: [/* ... */],
|
|
63
|
+
},
|
|
62
64
|
});
|
|
63
65
|
};
|
|
64
66
|
|
|
@@ -69,6 +71,12 @@ function VideoRenderer() {
|
|
|
69
71
|
</button>
|
|
70
72
|
{isRendering && <progress value={progress} max={1} />}
|
|
71
73
|
{videoBlob && <button onClick={download}>Download</button>}
|
|
74
|
+
{error && (
|
|
75
|
+
<div>
|
|
76
|
+
<p>{error.message}</p>
|
|
77
|
+
<button onClick={reset}>Clear error</button>
|
|
78
|
+
</div>
|
|
79
|
+
)}
|
|
72
80
|
</div>
|
|
73
81
|
);
|
|
74
82
|
}
|
|
@@ -92,6 +100,9 @@ function VideoRenderer() {
|
|
|
92
100
|
fps?: number; // Frames per second (default: 30)
|
|
93
101
|
quality?: 'low' | 'medium' | 'high';
|
|
94
102
|
range?: [number, number]; // [start, end] in seconds
|
|
103
|
+
includeAudio?: boolean; // Enable audio rendering and muxing (default: false)
|
|
104
|
+
downloadAudioSeparately?: boolean; // Also download audio.wav when muxing fails
|
|
105
|
+
onAudioReady?: (audioBlob: Blob) => void; // Callback when raw audio is ready
|
|
95
106
|
onProgress?: (progress: number) => void;
|
|
96
107
|
onComplete?: (videoBlob: Blob) => void;
|
|
97
108
|
onError?: (error: Error) => void;
|
|
@@ -112,15 +123,16 @@ const videoBlob = await renderTwickVideoInBrowser({
|
|
|
112
123
|
|
|
113
124
|
**Note**: String paths only work in Node.js. In the browser, you must import and pass the Project object directly.
|
|
114
125
|
|
|
115
|
-
## WASM
|
|
126
|
+
## WASM and public assets
|
|
116
127
|
|
|
117
|
-
|
|
128
|
+
The package ships `public/` with `mp4-wasm.wasm` and `audio-worker.js`. Copy them into your app's public directory so they are served:
|
|
118
129
|
|
|
119
130
|
```bash
|
|
120
|
-
cp node_modules/
|
|
131
|
+
cp node_modules/@twick/browser-render/public/mp4-wasm.wasm public/
|
|
132
|
+
cp node_modules/@twick/browser-render/public/audio-worker.js public/
|
|
121
133
|
```
|
|
122
134
|
|
|
123
|
-
|
|
135
|
+
Alternatively, configure your bundler (e.g. Vite) to serve WASM:
|
|
124
136
|
|
|
125
137
|
```typescript
|
|
126
138
|
// vite.config.ts
|
|
@@ -129,23 +141,49 @@ export default defineConfig({
|
|
|
129
141
|
});
|
|
130
142
|
```
|
|
131
143
|
|
|
144
|
+
### FFmpeg audio/video muxing (optional)
|
|
145
|
+
|
|
146
|
+
When `settings.includeAudio` is enabled, `@twick/browser-render` will render audio in the browser and (by default) try to mux it into the final MP4 using `@ffmpeg/ffmpeg`.
|
|
147
|
+
To match the setup used in `@twick/examples`, you should:
|
|
148
|
+
|
|
149
|
+
1. Install the FFmpeg packages:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm install @ffmpeg/ffmpeg @ffmpeg/util @ffmpeg/core
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. Expose the FFmpeg core files from your app’s `public` folder so they are available at:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
/public/ffmpeg/ffmpeg-core.js
|
|
159
|
+
/public/ffmpeg/ffmpeg-core.wasm
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
For example, you can copy them from `node_modules/@ffmpeg/core/dist`:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
mkdir -p public/ffmpeg
|
|
166
|
+
cp node_modules/@ffmpeg/core/dist/ffmpeg-core.js public/ffmpeg/
|
|
167
|
+
cp node_modules/@ffmpeg/core/dist/ffmpeg-core.wasm public/ffmpeg/
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
In the browser, the muxer loads these files from `${window.location.origin}/ffmpeg`, so the URLs must match that structure.
|
|
171
|
+
If FFmpeg cannot be loaded, the renderer will fall back to returning a video-only file and (optionally) downloading `audio.wav` separately when `downloadAudioSeparately` is true.
|
|
172
|
+
|
|
132
173
|
## Limitations
|
|
133
174
|
|
|
134
|
-
- **Audio**: Audio
|
|
175
|
+
- **Audio**: Audio rendering and FFmpeg-based muxing run entirely in the browser and are still considered experimental. If FFmpeg assets are not available, only video will be muxed and audio may be downloaded as a separate file.
|
|
135
176
|
- **Browser Support**: Requires WebCodecs API (Chrome 94+, Edge 94+)
|
|
136
177
|
|
|
137
|
-
##
|
|
178
|
+
## License
|
|
138
179
|
|
|
139
|
-
This package
|
|
180
|
+
This package is licensed under the **Sustainable Use License (SUL) Version 1.0**.
|
|
140
181
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
| Playback State | `PlaybackState.Rendering` | ✅ Same |
|
|
145
|
-
| Frame Progression | `playback.progress()` | ✅ Same |
|
|
146
|
-
| Variables Assignment | `project.variables = {...}` | ✅ Same |
|
|
147
|
-
| Audio Support | ✅ FFmpeg | ❌ Not yet |
|
|
182
|
+
- Free for use in commercial and non-commercial apps
|
|
183
|
+
- Can be modified and self-hosted
|
|
184
|
+
- Cannot be sold, rebranded, or distributed as a standalone SDK
|
|
148
185
|
|
|
149
|
-
|
|
186
|
+
For commercial licensing inquiries, contact: contact@kifferai.com
|
|
187
|
+
|
|
188
|
+
For full license terms, see the main LICENSE.md file in the project root.
|
|
150
189
|
|
|
151
|
-
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Project } from '@twick/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Browser rendering configuration
|
|
5
|
+
*/
|
|
6
|
+
interface BrowserRenderConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Custom Project object
|
|
9
|
+
* If not provided, defaults to @twick/visualizer project
|
|
10
|
+
*
|
|
11
|
+
* Note: Must be an imported Project object, not a string path.
|
|
12
|
+
* String paths only work in Node.js environments (server renderer).
|
|
13
|
+
*
|
|
14
|
+
* Example:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import myProject from './my-custom-project';
|
|
17
|
+
*
|
|
18
|
+
* await renderTwickVideoInBrowser({
|
|
19
|
+
* projectFile: myProject,
|
|
20
|
+
* variables: { input: {...} }
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
projectFile?: Project;
|
|
25
|
+
/** Input variables containing project configuration */
|
|
26
|
+
variables: {
|
|
27
|
+
input: any;
|
|
28
|
+
playerId?: string;
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
31
|
+
/** Render settings */
|
|
32
|
+
settings?: {
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
fps?: number;
|
|
36
|
+
quality?: 'low' | 'medium' | 'high';
|
|
37
|
+
range?: [number, number];
|
|
38
|
+
includeAudio?: boolean;
|
|
39
|
+
downloadAudioSeparately?: boolean;
|
|
40
|
+
onAudioReady?: (audioBlob: Blob) => void;
|
|
41
|
+
onProgress?: (progress: number) => void;
|
|
42
|
+
onComplete?: (videoBlob: Blob) => void;
|
|
43
|
+
onError?: (error: Error) => void;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Renders a Twick video directly in the browser without requiring a server.
|
|
48
|
+
* Uses WebCodecs API for encoding video frames into MP4 format.
|
|
49
|
+
*
|
|
50
|
+
* This function uses the same signature as the server renderer for consistency.
|
|
51
|
+
*
|
|
52
|
+
* @param config - Configuration object containing variables and settings
|
|
53
|
+
* @param config.projectFile - Optional project file path or Project object (defaults to visualizer project)
|
|
54
|
+
* @param config.variables - Variables containing input configuration (tracks, elements, etc.)
|
|
55
|
+
* @param config.settings - Optional render settings (width, height, fps, etc.)
|
|
56
|
+
* @returns Promise resolving to a Blob containing the rendered video
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```js
|
|
60
|
+
* import { renderTwickVideoInBrowser } from '@twick/browser-render';
|
|
61
|
+
*
|
|
62
|
+
* // Using default visualizer project
|
|
63
|
+
* const videoBlob = await renderTwickVideoInBrowser({
|
|
64
|
+
* variables: {
|
|
65
|
+
* input: {
|
|
66
|
+
* properties: { width: 1920, height: 1080, fps: 30 },
|
|
67
|
+
* tracks: [
|
|
68
|
+
* // Your tracks configuration
|
|
69
|
+
* ]
|
|
70
|
+
* }
|
|
71
|
+
* },
|
|
72
|
+
* settings: {
|
|
73
|
+
* width: 1920,
|
|
74
|
+
* height: 1080,
|
|
75
|
+
* fps: 30,
|
|
76
|
+
* quality: 'high',
|
|
77
|
+
* onProgress: (progress) => console.log(`Rendering: ${progress * 100}%`),
|
|
78
|
+
* }
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* // Using custom project
|
|
82
|
+
* import myProject from './my-custom-project';
|
|
83
|
+
* const videoBlob = await renderTwickVideoInBrowser({
|
|
84
|
+
* projectFile: myProject, // Must be an imported Project object
|
|
85
|
+
* variables: { input: {...} },
|
|
86
|
+
* settings: {...}
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* // Download the video
|
|
90
|
+
* const url = URL.createObjectURL(videoBlob);
|
|
91
|
+
* const a = document.createElement('a');
|
|
92
|
+
* a.href = url;
|
|
93
|
+
* a.download = 'video.mp4';
|
|
94
|
+
* a.click();
|
|
95
|
+
* URL.revokeObjectURL(url);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
declare const renderTwickVideoInBrowser: (config: BrowserRenderConfig) => Promise<Blob>;
|
|
99
|
+
/**
|
|
100
|
+
* Helper function to download a video blob as a file
|
|
101
|
+
*
|
|
102
|
+
* @param videoBlob - The video blob to download
|
|
103
|
+
* @param filename - The desired filename (default: 'video.mp4')
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```js
|
|
107
|
+
* const blob = await renderTwickVideoInBrowser(projectData);
|
|
108
|
+
* downloadVideoBlob(blob, 'my-video.mp4');
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare const downloadVideoBlob: (videoBlob: Blob, filename?: string) => void;
|
|
112
|
+
|
|
113
|
+
interface UseBrowserRendererOptions {
|
|
114
|
+
/**
|
|
115
|
+
* Custom Project object
|
|
116
|
+
* If not provided, defaults to @twick/visualizer project
|
|
117
|
+
*
|
|
118
|
+
* Note: Must be an imported Project object, not a string path.
|
|
119
|
+
* String paths only work in Node.js (server renderer).
|
|
120
|
+
*
|
|
121
|
+
* Example:
|
|
122
|
+
* ```typescript
|
|
123
|
+
* import myProject from './my-custom-project';
|
|
124
|
+
* useBrowserRenderer({ projectFile: myProject })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
projectFile?: any;
|
|
128
|
+
/** Video width in pixels */
|
|
129
|
+
width?: number;
|
|
130
|
+
/** Video height in pixels */
|
|
131
|
+
height?: number;
|
|
132
|
+
/** Frames per second */
|
|
133
|
+
fps?: number;
|
|
134
|
+
/** Render quality */
|
|
135
|
+
quality?: 'low' | 'medium' | 'high';
|
|
136
|
+
/** Time range to render [start, end] in seconds */
|
|
137
|
+
range?: [number, number];
|
|
138
|
+
/** Include audio in rendered video (experimental) */
|
|
139
|
+
includeAudio?: boolean;
|
|
140
|
+
/** Download audio separately as WAV file */
|
|
141
|
+
downloadAudioSeparately?: boolean;
|
|
142
|
+
/** Callback when audio is ready */
|
|
143
|
+
onAudioReady?: (audioBlob: Blob) => void;
|
|
144
|
+
/** Automatically download the video when rendering completes */
|
|
145
|
+
autoDownload?: boolean;
|
|
146
|
+
/** Default filename for downloads */
|
|
147
|
+
downloadFilename?: string;
|
|
148
|
+
}
|
|
149
|
+
interface UseBrowserRendererReturn {
|
|
150
|
+
/** Start rendering the video */
|
|
151
|
+
render: (variables: BrowserRenderConfig['variables']) => Promise<Blob | null>;
|
|
152
|
+
/** Current rendering progress (0-1) */
|
|
153
|
+
progress: number;
|
|
154
|
+
/** Whether rendering is in progress */
|
|
155
|
+
isRendering: boolean;
|
|
156
|
+
/** Error if rendering failed */
|
|
157
|
+
error: Error | null;
|
|
158
|
+
/** The rendered video blob (available after rendering completes) */
|
|
159
|
+
videoBlob: Blob | null;
|
|
160
|
+
/** Download the rendered video */
|
|
161
|
+
download: (filename?: string) => void;
|
|
162
|
+
/** Reset the renderer state */
|
|
163
|
+
reset: () => void;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* React hook for rendering Twick videos in the browser
|
|
167
|
+
*
|
|
168
|
+
* Uses the same pattern as the server renderer for consistency.
|
|
169
|
+
*
|
|
170
|
+
* @param options - Rendering options
|
|
171
|
+
* @returns Renderer state and control functions
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```tsx
|
|
175
|
+
* import { useBrowserRenderer } from '@twick/browser-render';
|
|
176
|
+
*
|
|
177
|
+
* // Using default visualizer project
|
|
178
|
+
* function MyComponent() {
|
|
179
|
+
* const { render, progress, isRendering, videoBlob, download } = useBrowserRenderer({
|
|
180
|
+
* width: 1920,
|
|
181
|
+
* height: 1080,
|
|
182
|
+
* fps: 30,
|
|
183
|
+
* autoDownload: true,
|
|
184
|
+
* });
|
|
185
|
+
*
|
|
186
|
+
* const handleRender = async () => {
|
|
187
|
+
* await render({
|
|
188
|
+
* input: {
|
|
189
|
+
* properties: { width: 1920, height: 1080, fps: 30 },
|
|
190
|
+
* tracks: [
|
|
191
|
+
* // Your tracks configuration
|
|
192
|
+
* ]
|
|
193
|
+
* }
|
|
194
|
+
* });
|
|
195
|
+
* };
|
|
196
|
+
*
|
|
197
|
+
* return (
|
|
198
|
+
* <div>
|
|
199
|
+
* <button onClick={handleRender} disabled={isRendering}>
|
|
200
|
+
* {isRendering ? `Rendering... ${(progress * 100).toFixed(0)}%` : 'Render Video'}
|
|
201
|
+
* </button>
|
|
202
|
+
* {videoBlob && !autoDownload && (
|
|
203
|
+
* <button onClick={() => download('my-video.mp4')}>Download</button>
|
|
204
|
+
* )}
|
|
205
|
+
* </div>
|
|
206
|
+
* );
|
|
207
|
+
* }
|
|
208
|
+
*
|
|
209
|
+
* // Using custom project (must import it first)
|
|
210
|
+
* import myProject from './my-project';
|
|
211
|
+
*
|
|
212
|
+
* function CustomProjectComponent() {
|
|
213
|
+
* const { render } = useBrowserRenderer({
|
|
214
|
+
* projectFile: myProject, // Pass the imported project object
|
|
215
|
+
* width: 1920,
|
|
216
|
+
* height: 1080,
|
|
217
|
+
* });
|
|
218
|
+
*
|
|
219
|
+
* // ... rest of component
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare const useBrowserRenderer: (options?: UseBrowserRendererOptions) => UseBrowserRendererReturn;
|
|
224
|
+
|
|
225
|
+
export { type BrowserRenderConfig, type UseBrowserRendererOptions, type UseBrowserRendererReturn, renderTwickVideoInBrowser as default, downloadVideoBlob, renderTwickVideoInBrowser, useBrowserRenderer };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Project } from '@twick/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Browser rendering configuration
|
|
5
|
+
*/
|
|
6
|
+
interface BrowserRenderConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Custom Project object
|
|
9
|
+
* If not provided, defaults to @twick/visualizer project
|
|
10
|
+
*
|
|
11
|
+
* Note: Must be an imported Project object, not a string path.
|
|
12
|
+
* String paths only work in Node.js environments (server renderer).
|
|
13
|
+
*
|
|
14
|
+
* Example:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import myProject from './my-custom-project';
|
|
17
|
+
*
|
|
18
|
+
* await renderTwickVideoInBrowser({
|
|
19
|
+
* projectFile: myProject,
|
|
20
|
+
* variables: { input: {...} }
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
projectFile?: Project;
|
|
25
|
+
/** Input variables containing project configuration */
|
|
26
|
+
variables: {
|
|
27
|
+
input: any;
|
|
28
|
+
playerId?: string;
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
31
|
+
/** Render settings */
|
|
32
|
+
settings?: {
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
fps?: number;
|
|
36
|
+
quality?: 'low' | 'medium' | 'high';
|
|
37
|
+
range?: [number, number];
|
|
38
|
+
includeAudio?: boolean;
|
|
39
|
+
downloadAudioSeparately?: boolean;
|
|
40
|
+
onAudioReady?: (audioBlob: Blob) => void;
|
|
41
|
+
onProgress?: (progress: number) => void;
|
|
42
|
+
onComplete?: (videoBlob: Blob) => void;
|
|
43
|
+
onError?: (error: Error) => void;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Renders a Twick video directly in the browser without requiring a server.
|
|
48
|
+
* Uses WebCodecs API for encoding video frames into MP4 format.
|
|
49
|
+
*
|
|
50
|
+
* This function uses the same signature as the server renderer for consistency.
|
|
51
|
+
*
|
|
52
|
+
* @param config - Configuration object containing variables and settings
|
|
53
|
+
* @param config.projectFile - Optional project file path or Project object (defaults to visualizer project)
|
|
54
|
+
* @param config.variables - Variables containing input configuration (tracks, elements, etc.)
|
|
55
|
+
* @param config.settings - Optional render settings (width, height, fps, etc.)
|
|
56
|
+
* @returns Promise resolving to a Blob containing the rendered video
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```js
|
|
60
|
+
* import { renderTwickVideoInBrowser } from '@twick/browser-render';
|
|
61
|
+
*
|
|
62
|
+
* // Using default visualizer project
|
|
63
|
+
* const videoBlob = await renderTwickVideoInBrowser({
|
|
64
|
+
* variables: {
|
|
65
|
+
* input: {
|
|
66
|
+
* properties: { width: 1920, height: 1080, fps: 30 },
|
|
67
|
+
* tracks: [
|
|
68
|
+
* // Your tracks configuration
|
|
69
|
+
* ]
|
|
70
|
+
* }
|
|
71
|
+
* },
|
|
72
|
+
* settings: {
|
|
73
|
+
* width: 1920,
|
|
74
|
+
* height: 1080,
|
|
75
|
+
* fps: 30,
|
|
76
|
+
* quality: 'high',
|
|
77
|
+
* onProgress: (progress) => console.log(`Rendering: ${progress * 100}%`),
|
|
78
|
+
* }
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* // Using custom project
|
|
82
|
+
* import myProject from './my-custom-project';
|
|
83
|
+
* const videoBlob = await renderTwickVideoInBrowser({
|
|
84
|
+
* projectFile: myProject, // Must be an imported Project object
|
|
85
|
+
* variables: { input: {...} },
|
|
86
|
+
* settings: {...}
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* // Download the video
|
|
90
|
+
* const url = URL.createObjectURL(videoBlob);
|
|
91
|
+
* const a = document.createElement('a');
|
|
92
|
+
* a.href = url;
|
|
93
|
+
* a.download = 'video.mp4';
|
|
94
|
+
* a.click();
|
|
95
|
+
* URL.revokeObjectURL(url);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
declare const renderTwickVideoInBrowser: (config: BrowserRenderConfig) => Promise<Blob>;
|
|
99
|
+
/**
|
|
100
|
+
* Helper function to download a video blob as a file
|
|
101
|
+
*
|
|
102
|
+
* @param videoBlob - The video blob to download
|
|
103
|
+
* @param filename - The desired filename (default: 'video.mp4')
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```js
|
|
107
|
+
* const blob = await renderTwickVideoInBrowser(projectData);
|
|
108
|
+
* downloadVideoBlob(blob, 'my-video.mp4');
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare const downloadVideoBlob: (videoBlob: Blob, filename?: string) => void;
|
|
112
|
+
|
|
113
|
+
interface UseBrowserRendererOptions {
|
|
114
|
+
/**
|
|
115
|
+
* Custom Project object
|
|
116
|
+
* If not provided, defaults to @twick/visualizer project
|
|
117
|
+
*
|
|
118
|
+
* Note: Must be an imported Project object, not a string path.
|
|
119
|
+
* String paths only work in Node.js (server renderer).
|
|
120
|
+
*
|
|
121
|
+
* Example:
|
|
122
|
+
* ```typescript
|
|
123
|
+
* import myProject from './my-custom-project';
|
|
124
|
+
* useBrowserRenderer({ projectFile: myProject })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
projectFile?: any;
|
|
128
|
+
/** Video width in pixels */
|
|
129
|
+
width?: number;
|
|
130
|
+
/** Video height in pixels */
|
|
131
|
+
height?: number;
|
|
132
|
+
/** Frames per second */
|
|
133
|
+
fps?: number;
|
|
134
|
+
/** Render quality */
|
|
135
|
+
quality?: 'low' | 'medium' | 'high';
|
|
136
|
+
/** Time range to render [start, end] in seconds */
|
|
137
|
+
range?: [number, number];
|
|
138
|
+
/** Include audio in rendered video (experimental) */
|
|
139
|
+
includeAudio?: boolean;
|
|
140
|
+
/** Download audio separately as WAV file */
|
|
141
|
+
downloadAudioSeparately?: boolean;
|
|
142
|
+
/** Callback when audio is ready */
|
|
143
|
+
onAudioReady?: (audioBlob: Blob) => void;
|
|
144
|
+
/** Automatically download the video when rendering completes */
|
|
145
|
+
autoDownload?: boolean;
|
|
146
|
+
/** Default filename for downloads */
|
|
147
|
+
downloadFilename?: string;
|
|
148
|
+
}
|
|
149
|
+
interface UseBrowserRendererReturn {
|
|
150
|
+
/** Start rendering the video */
|
|
151
|
+
render: (variables: BrowserRenderConfig['variables']) => Promise<Blob | null>;
|
|
152
|
+
/** Current rendering progress (0-1) */
|
|
153
|
+
progress: number;
|
|
154
|
+
/** Whether rendering is in progress */
|
|
155
|
+
isRendering: boolean;
|
|
156
|
+
/** Error if rendering failed */
|
|
157
|
+
error: Error | null;
|
|
158
|
+
/** The rendered video blob (available after rendering completes) */
|
|
159
|
+
videoBlob: Blob | null;
|
|
160
|
+
/** Download the rendered video */
|
|
161
|
+
download: (filename?: string) => void;
|
|
162
|
+
/** Reset the renderer state */
|
|
163
|
+
reset: () => void;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* React hook for rendering Twick videos in the browser
|
|
167
|
+
*
|
|
168
|
+
* Uses the same pattern as the server renderer for consistency.
|
|
169
|
+
*
|
|
170
|
+
* @param options - Rendering options
|
|
171
|
+
* @returns Renderer state and control functions
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```tsx
|
|
175
|
+
* import { useBrowserRenderer } from '@twick/browser-render';
|
|
176
|
+
*
|
|
177
|
+
* // Using default visualizer project
|
|
178
|
+
* function MyComponent() {
|
|
179
|
+
* const { render, progress, isRendering, videoBlob, download } = useBrowserRenderer({
|
|
180
|
+
* width: 1920,
|
|
181
|
+
* height: 1080,
|
|
182
|
+
* fps: 30,
|
|
183
|
+
* autoDownload: true,
|
|
184
|
+
* });
|
|
185
|
+
*
|
|
186
|
+
* const handleRender = async () => {
|
|
187
|
+
* await render({
|
|
188
|
+
* input: {
|
|
189
|
+
* properties: { width: 1920, height: 1080, fps: 30 },
|
|
190
|
+
* tracks: [
|
|
191
|
+
* // Your tracks configuration
|
|
192
|
+
* ]
|
|
193
|
+
* }
|
|
194
|
+
* });
|
|
195
|
+
* };
|
|
196
|
+
*
|
|
197
|
+
* return (
|
|
198
|
+
* <div>
|
|
199
|
+
* <button onClick={handleRender} disabled={isRendering}>
|
|
200
|
+
* {isRendering ? `Rendering... ${(progress * 100).toFixed(0)}%` : 'Render Video'}
|
|
201
|
+
* </button>
|
|
202
|
+
* {videoBlob && !autoDownload && (
|
|
203
|
+
* <button onClick={() => download('my-video.mp4')}>Download</button>
|
|
204
|
+
* )}
|
|
205
|
+
* </div>
|
|
206
|
+
* );
|
|
207
|
+
* }
|
|
208
|
+
*
|
|
209
|
+
* // Using custom project (must import it first)
|
|
210
|
+
* import myProject from './my-project';
|
|
211
|
+
*
|
|
212
|
+
* function CustomProjectComponent() {
|
|
213
|
+
* const { render } = useBrowserRenderer({
|
|
214
|
+
* projectFile: myProject, // Pass the imported project object
|
|
215
|
+
* width: 1920,
|
|
216
|
+
* height: 1080,
|
|
217
|
+
* });
|
|
218
|
+
*
|
|
219
|
+
* // ... rest of component
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare const useBrowserRenderer: (options?: UseBrowserRendererOptions) => UseBrowserRendererReturn;
|
|
224
|
+
|
|
225
|
+
export { type BrowserRenderConfig, type UseBrowserRendererOptions, type UseBrowserRendererReturn, renderTwickVideoInBrowser as default, downloadVideoBlob, renderTwickVideoInBrowser, useBrowserRenderer };
|