Media, fonts and models
What imports
The engine reads the first sixteen bytes of a file to find its container. The file name does not matter. Decoding uses the browser's WebCodecs, so the codec must be one the browser decodes.
| Kind | Containers | Codecs | Read by |
|---|---|---|---|
| Video | MP4, MOV, M4V | H.264, H.265, VP9, AV1 | mp4box; mediabunny when mp4box fails |
| Video | WebM, MKV | VP8, VP9, AV1, H.264, where the browser decodes them | mediabunny |
| Sound of a video, or an M4A | MP4, MOV, M4A | AAC, MP3, FLAC, Opus, AC-3, where the browser decodes them | mp4box and WebCodecs |
| Audio files | MP3, WAV, Ogg, FLAC, WebM, MKV | what the browser decodes | mediabunny and WebCodecs, then the browser's decodeAudioData |
| Images | PNG, JPEG, WebP, GIF, BMP, SVG | none | the browser's image decoder |
Things to know:
- H.264 decodes everywhere. H.265 depends on the browser and the hardware. Firefox refuses it, and the error names Chrome or Edge.
- A phone video with a rotation tag plays upright. The rotation is applied when drawing, never baked into the file.
- A fragmented MP4 (written with
moofboxes) can import with fewer frames than it holds. - A sound file is decoded whole into memory, about ten megabytes per minute of stereo.
- A GIF imports as a still picture, its first frame. An image clip lasts five seconds unless you pass
durationSec.
The editor's file pickers accept fewer types than the engine does. The video picker lists MP4 and WebM. The audio picker lists any audio type. The image picker lists PNG, JPEG, WebP, SVG, GIF and BMP. The backend methods importVideo, importAudio and importImage accept any file the engine can read.
Proxies
A proxy is a lighter copy of a video, made for the preview. The engine makes one in the background after an import and when a project opens.
| Rule | Value |
|---|---|
| Made when the video is wider than | 1280 pixels |
| Or taller than | 720 pixels |
| Or when the keyframes are further apart than | 2 seconds on average |
| Never on | iPhone, iPad, Android |
Clips read the original until the proxy is done, then switch to it. Export and transcription always read the original. Progress arrives as the proxy-progress event, from 0 to 1, then null when the proxy is finished, failed or stopped. When a proxy fails, the original keeps playing. Nothing else changes.
Media from a web address
importFromUrl downloads a file into file storage as a stream. It then adds the file to the project's media, like a picked file.
import type { EditorBackend } from "@vidstudio/engine";
export async function addFromServer(backend: EditorBackend): Promise<void> {
const asset = await backend.importFromUrl("https://media.example.com/clips/intro.mp4");
await backend.addTrackFromAsset(asset.id, "video");
const sound = await backend.importFromUrl("https://media.example.com/clips/intro.mp4", { type: "audio" });
await backend.addTrackFromAsset(sound.id, "audio");
}
type: "audio" keeps only the sound of a video. type: "video" on a file without video rejects with the code type-mismatch. A failed download rejects with import-failed. The file takes its name from the last part of the address. A name without an extension gets one from the content type. The download sends no cookies to another origin.
An address on your own origin needs nothing. An address on another origin needs headers from that server.
| Your page | Headers the file server must send |
|---|---|
| Without cross-origin isolation | Access-Control-Allow-Origin: https://your-site.example (or *) |
| With cross-origin isolation (the two headers from Getting started) | The header above, plus Cross-Origin-Resource-Policy: cross-origin |
The same rules apply to a web address returned by a resolver in Save and load.
Fonts
Text clips use twelve fonts, one regular weight each, as .woff2 files under node_modules/@vidstudio/engine/assets/fonts. All twelve are under the SIL Open Font License, included as OFL.txt.
| Category | Fonts |
|---|---|
| Sans serif | Inter (the default), Roboto, Montserrat, Open Sans, Poppins |
| Serif | Playfair Display, Lora |
| Display | Bebas Neue, Oswald |
| Handwriting | Dancing Script, Pacifico |
| Monospace | JetBrains Mono |
The editor loads a font the first time a clip uses it, from /fonts/ by default. Copy the folder there, or serve it elsewhere and set options.assets.fonts to that address, ending in a slash. A font that fails to load logs a warning, and the text draws in the browser's fallback font.
cp -r node_modules/@vidstudio/engine/assets/fonts public/fonts
Models
Captions come from Whisper speech models that run on the device. The editor picks the model by device. Both are English only: the .en models accept no other language.
| Device | Model | Size |
|---|---|---|
| Desktop | onnx-community/whisper-base.en |
294 MB |
| iPhone, iPad, Android | onnx-community/whisper-tiny.en |
154 MB |
vidstudio-fetch-models puts the files into a folder you serve. It downloads from Hugging Face at pinned revisions and skips files already present. It writes the Apache 2.0 licence and a notice file beside them.
npx vidstudio-fetch-models public/models
| Flag | Effect |
|---|---|
--models base.en |
Only the models named, comma separated |
--models all |
Every model in the manifest, including three word-timestamped variants the editor does not use |
--from <folder> |
Copy from an existing models folder instead of downloading |
--no-whisper |
Skip the speech models |
--no-mediapipe |
Skip the background removal files |
The engine loads the models from /models/ by default. Serve the folder elsewhere and set options.assets.models, ending in a slash. With a full web address, the files are fetched on first use and cached in the browser's cache storage. With features={{ captions: false }} the editor never downloads a model.
Transcription also loads the onnxruntime runtime files from cdn.jsdelivr.net on first use. A page that is offline, or whose content security policy blocks that address, cannot transcribe.
Background removal files
vidstudio-fetch-models also writes mediapipe/wasm/ and mediapipe/selfie_segmenter.tflite, about 19 MB together, under the models folder. The editor's effect list has no background removal today. The engine draws the effect only for a loaded document that already carries an effect of type background-removal. Such an export runs on the page thread instead of the worker. Pass --no-mediapipe if you never load such a document.