tokimeki-video-editor
v0.1.1
Published
A browser video editor for Svelte 5 built on WebCodecs.
Readme
tokimeki-video-editor
A browser video editor for Svelte 5, built on WebCodecs. Designed for TOKIMEKI, a Bluesky client — but usable in any Svelte 5 app.
Zero runtime media dependencies: the MP4/MOV demuxer, MP4 muxer (faststart), and the whole decode → composite → encode pipeline are implemented in TypeScript on top of WebCodecs, running in a Web Worker.
Features
- Trim — timeline with draggable handles, frame stepping, keyboard shortcuts (
Space,←/→,[,]) - Lossless trim — keyframe-snapped sample copy with no re-encoding, finishes almost instantly
- Crop — freeform or aspect presets (1:1, 16:9, 9:16, 4:3, 3:4)
- Audio — mute the original track, adjust volume, insert audio files (BGM) and mix with per-track volume
- Text & stamps — draggable/resizable/rotatable overlays with time ranges
- Compression — target-size bitrate calculation, resolution presets, Bluesky limits (3 min / 300 MB) surfaced in the UI
- Format absorption — MP4/MOV are demuxed natively; WebM and fragmented MP4 fall back to
<video>-element decoding; output is always faststart MP4 (H.264 + AAC, or Opus where AAC encoding is unavailable) - Dark / light / system themes, i18n (en/ja) via tokimeki-i18n
Install
npm install tokimeki-video-editorsvelte >= 5 and tokimeki-i18n >= 0.2 are peer dependencies.
Usage
<script lang="ts">
import { VideoEditor, type VideoExportResult } from 'tokimeki-video-editor';
let file: File;
async function handleComplete(result: VideoExportResult) {
const video = {
aspectRatio: { width: result.width, height: result.height },
blob: result.blob,
bytes: await result.blob.arrayBuffer(),
mimeType: result.mimeType,
ext: 'mp4'
};
}
</script>
<VideoEditor
initialVideo={file}
isStandalone={false}
theme="dark"
onComplete={handleComplete}
onCancel={() => {}}
/>Props
| prop | type | default | |
|---|---|---|---|
| initialVideo | File \| string | – | video file or URL to load |
| isStandalone | boolean | false | true shows a drop zone and downloads exports; false is the host-embedded mode |
| theme | 'dark' \| 'light' \| 'system' | 'dark' | |
| maxDurationSec | number | 180 | duration limit shown/enforced in the export UI |
| maxSizeBytes | number | 300_000_000 | size limit shown/enforced in the export UI |
| onComplete | (result: VideoExportResult) => void | – | called with the exported MP4 |
| onCancel | () => void | – | |
interface VideoExportResult {
blob: Blob;
width: number;
height: number;
duration: number;
mimeType: 'video/mp4';
sizeBytes: number;
}Browser support
Requires the WebCodecs API (VideoDecoder / VideoEncoder / AudioEncoder): Chrome/Edge 94+, Safari 16.4+, Firefox 130+. Unsupported browsers get an explanatory notice instead of the editor.
Development
npm run dev # demo app (/, /embed)
npm run test:run # unit tests (demuxer/muxer/planner/state)
npm run test:e2e # Playwright E2E — real-Chrome export verification (see docs/QA.md)
npm run check # svelte-check
npm run package # build dist/ for publishingLicense
MIT
