Skip to content

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 ​

typescript
type UploadHandler = (file: File) => Promise<string>;

S3 example ​

jsx
<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 ​

jsx
<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.

WARNING

CORS. Whatever URL you return must be reachable with CORS enabled so the editor's renderer can decode it. S3 and R2 both need an explicit GET policy allowing your app origin.

Released under the MIT License.