Editor uploads
When the user drops a file into the timeline or the sidebar, the editor calls onUpload(file). Resolve the promise with a public URL and the editor uses that for all references — playback, rendering, caching.
Signature
type UploadHandler = (file: File) => Promise<string>;S3 example
<VideoEditor
video={v}
onUpload={async (file) => {
const { url, fields } = await fetch('/api/presigned', {
method: 'POST',
body: JSON.stringify({ name: file.name, type: file.type }),
}).then((r) => r.json());
const body = new FormData();
Object.entries(fields).forEach(([k, v]) => body.append(k, v));
body.append('file', file);
await fetch(url, { method: 'POST', body });
return `${url}/${fields.key}`;
}}
/>Cloudflare R2 / Supabase
<VideoEditor
onUpload={async (file) => {
const form = new FormData();
form.append('file', file);
const res = await fetch('/api/upload', { method: 'POST', body: form });
const { url } = await res.json();
return url;
}}
/>Fallback: object URLs
If you don't pass onUpload, the editor wraps dropped files with URL.createObjectURL() and revokes them on unmount. Great for demos — a dead end for anything persisted.
GET policy allowing your app origin.