A powerful, web-based tool for annotating video and image media with frame-accurate precision. Built with a modular architecture that separates core annotation logic from the UI, enabling easy integration into any web application.
The ultimate goal is to create a professional-grade, browser-based media annotation suite capable of:
- Frame-Accurate Annotation: Drawing on specific video frames with vector precision.
- Temporal Annotations: defining start and end times for annotations (e.g., "follow this object for 5 seconds").
- Rich Media Support: Handling video playback, audio scrubbing, and potentially multi-track syncing.
- Export Flexibility: Exporting data in standard formats (JSON) or "burning in" annotations for review.
- Extensibility: Allowing developers to add custom tools and rendering logic via plugins.
- Vector Shapes: Draw Squares, Circles, Arrows, and Freehand lines.
- Text Support: Add text labels directly onto frames.
- Selection & Editing:
- Multi-Select: Hold
Ctrl/Cmd+ Click to select multiple items. - Multi-Drag: Move entire selection groups at once.
- Multi-Select: Hold
- Undo/Redo: Robust history support for all actions (synced in collaborative sessions).
- Color Picking: EyeDropper tool to sample colors from the video.
- Delete Shortcuts: Quickly remove selection with
DeleteorBackspace.
- Frame-Accurate Scrubbing: Navigate video frame-by-frame.
- Pan & Zoom:
- Smooth Interaction: Pan (Hand tool) and Zoom (Scroll wheel) with inertia.
- Fit-to-Content: Canvas automatically aligns to the video content, ignoring letterboxing/black bars.
- Pixel-Perfect Sync: Annotations stay locked to video details at any zoom level using CSS transforms.
- Ghosting (Onion Skinning):
- View previous (red) and future (green) frames overlaid on the current frame.
- Configurable range (1-10 frames) and opacity.
- π Audio Scrubbing:
- Real-time audio feedback while scrubbing the timeline, essential for lip-sync and cueing.
- Works with both native video and force-downloaded media.
- Force Download Strategy:
- Option (
preload="force-download") to pre-fetch the entire media file as a Blob. - Delivers instant seeking and zero-buffering playback even on slow connections.
- Option (
- Client-Side Transcoding (FFmpeg WASM):
- Play Anything: Drag & drop
.mkv,.mov(ProRes),.avi, or.heicfiles. - The engine automatically transcodes them locally in the browser to MP4/JPG for frame-accurate annotation.
- No server upload required β 100% private.
- Play Anything: Drag & drop
- Smart Caching:
- efficiently manages large media files in memory for smooth performance.
- Mouse: Middle-click to Pan (temporary), Scroll to Zoom.
- Keyboard:
- Tools:
S,P,A,C,Q,T,E. - Navigation:
Space(Play/Pause), Arrows (Frame step),Ctrl+Arrows (Jump to annotation). - View:
R(Reset Zoom/Pan). - History:
Ctrl+Z(Undo),Ctrl+Y(Redo). - Edit:
Ctrl+C(Copy),Ctrl+V(Paste),Del/Backspace(Delete).
- Tools:
- UI:
- Unified Sidebar: Properties and information accessible in a slide-out drawer.
- Shortcuts Modal: Instant help reference accessible from the toolbar.
- Frame Export: Download current frame (Clean or Burned In) as PNG.
- Bulk Export (ZIP): Download all annotated frames as a ZIP archive (Clean or Burned In) with progress tracking.
- Data Portability: Download/Import annotation data as standard JSON.
- State Management: Centralized store with complete state persistence and SNAPSHOT history.
- P2P Sync: Host or Join sessions via WebRTC (PeerJS).
- Shared State: Real-time synchronization of annotations, onion skin settings, and playback state via Yjs.
- Dynamic Updates: Collaborative undo/redo that respects remote changes.
- Goal: Support basic 3D model annotation (OBJ/GLB).
- Utility: Annotating 3D assets for game development or product visualization.
- Goal: Visualize the audio waveform in the timeline.
- Goal: Finalize the Plugin API for custom tool creation.
The project is structured as a Monorepo:
packages/core: The headless library containing the state management (Store), rendering engine (Renderer), and tool logic (PanTool,FreehandTool, etc.). It has no UI dependencies other than a container element.apps/demo: A reference implementation using purely Vanilla TypeScript/CSS to demonstrate how to build a UI around the core library.
This project is designed to be used in three distinct ways depending on your needs:
-
Static Web App (Quick Reviews)
- Use as a standalone tool running completely in the browser.
- Upload local video/image files which are processed in-memory (no server upload required).
- Ideal for quick, secure reviews of daily work.
-
CDN Integration (Static Files)
- Load the library via a
scripttag from a CDN (or locally hosted static files). - Easily embed an annotation widget into legacy apps or static sites using vanilla HTML/JS/CSS.
- Load the library via a
-
NPM Module (Build Integration)
- Import
@web-media-annotator/coreinto complex React/Vue/Angular applications. - Leverage the full TypeScript API for deep integration and custom UI development.
- Import
- Node.js (v16+)
npm install @web-media-annotator/react @web-media-annotator/embedZero Setup. No Server Required. Perfect for quickly reviewing local files. Just open the HTML file in your browser.
- Demo: quick-review.html
- Drag & Drop interface for local video/image files.
- Runs completely in the browser (using ObjectURLs).
- Static Test: static-test.html
- Simple hardcoded example using a public video URL.
Best for modern React applications.
import { Annotator } from '@web-media-annotator/react';
import '@web-media-annotator/react/dist/style.css'; // If applicable
function App() {
return (
<div style={{ width: '1000px', height: '600px' }}>
<Annotator
src="video.mp4"
fps={24}
preload="force-download" // Optional: fetches entire file for instant seeking
/>
</div>
);
}Works with Vue, Svelte, Angular, or any HTML page.
Using npm:
import '@web-media-annotator/embed';Using HTML:
<web-media-annotator
src="video.mp4"
fps="24"
width="100%"
height="100%"
preload="force-download"
></web-media-annotator>For legacy sites or static usage without a bundler.
<!-- Load the UMD script -->
<script src="https://unpkg.com/@web-media-annotator/embed/dist/web-media-annotator.umd.js"></script>
<!-- Use the custom element -->
<web-media-annotator src="video.mp4"></web-media-annotator>| Key | Action |
|---|---|
Space |
Play / Pause |
β / β |
Prev / Next Frame |
P |
Pencil Tool |
E |
Eraser |
S |
Select Tool |
G |
Toggle Ghosting (Onion Skin) |
H |
Toggle Hold (3 Frames) |
+ / - |
Adjust Stroke Size |
Scroll |
Zoom Canvas |
Mid-Click |
Pan Canvas |
-
Install Dependencies
npm install
-
Run Demo
npm run dev:demo
-
Build Packages
npm run build
Open your browser to the URL shown (usually
http://localhost:5173or similar).
Contributions are welcome! Please focus on the packages/core for functional improvements and apps/demo for UI enhancements.
This project is licensed under the Mozilla Public License 2.0 (MPL-2.0).
Why MPL-2.0? We chose this license specifically to support the Animation and VFX industry pipeline requirements:
- Commercial Safe: Studios can use this tool in commercial pipelines to create content without risking their proprietary IP or pipeline code.
- Pipeline Friendly: Unlike GPL, using this tool in a larger proprietary pipeline does not force you to open-source your entire pipeline.
- Open Contribution: We strongly believe in giving back. Any modifications to the source code files of this project must be open-sourced, ensuring the tool evolves for everyone's benefit.
