npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

maplibre-gl-video-export

v0.1.1

Published

Video export plugin for MapLibre GL JS

Downloads

158

Readme

MapLibre GL Video Export Plugin

License: BSD-3-Clause npm version MapLibre GL JS

Watch Demo Video

📹 Watch Demo Video (WebM) | MP4 | Heavy 4K | 🚀 Try Live Demo

🎬 Universal video export plugin for MapLibre GL JS with animations that adapt to any map. Export high-quality WebM or MP4 videos.


Features

  • 🎬 Multiple Animations - Various presets from basic rotations to drone shots and wave motions
  • 🗺️ Terrain-Aware - Collision detection for 3D terrain animations (maybe)
  • 🚗 Roads-Aware - Some preset animations can follow roads
  • 🎯 Universal - Works with any MapLibre GL map. Tries to detect features, fonts and icons available in your style.json
  • 🎥 High Quality - Export videos at various resolutions (HD, Full HD, 4K) or with custom dimensions
  • Fast - Hardware-accelerated encoding with modern browsers
  • 📍 Waypoints - Define points of interest to visit or include in animations with custom icons and camera angles
  • 🔒 Geographic Constraints - Define boundaries and zoom limits to keep animations in specific areas (works sometimes)
  • 🎨 Customizable - Choose from presets or provide your own animations

Supported Video Formats

| Format | File Size | Compression | Browser Support | License | Best For | |--------|-----------|-------------|-----------------|---------|----------| | WebM (VP9) ⭐ | Smallest | Excellent | Modern browsers (Chrome 91+, Firefox 89+, Safari 16.4+) | ✅ Royalty-free | Recommended - Best quality, native WebCodecs API | | WebM (VP8) | 30-50% smaller | Good | Modern browsers | ✅ Royalty-free | Good alternative, included encoder | | MP4 (H.264) | Baseline | Standard | Universal | ⚠️ Patent licensing* | Legacy browser compatibility only |


* ⚠️ Important: Format Recommendation

We strongly recommend using WebM format (default). WebM is royalty-free, provides better compression, uses browser's native WebCodecs API.

MP4 (H.264) may require licensing fees from VIA LA for certain commercial uses. While free for non-commercial use and streaming to end users, commercial distribution may incur royalty obligations. See VIA LA licensing for details.

Use WebM unless you specifically need universal compatibility with older browsers.


Requirements

  • MapLibre GL JS v5.11.0 or later (includes time control API)
  • Modern browser with WebAssembly support
  • SIMD support recommended for better performance

Installation

Via CDN

<script src="https://unpkg.com/maplibre-gl-video-export@latest/dist/maplibre-gl-video-export/maplibre-gl-video-export.js"></script>

Note: For production, you can pin to a specific version like @0.1.0 instead of @latest to avoid unexpected updates.

Via NPM

npm install maplibre-gl-video-export
import { VideoExportControl } from 'maplibre-gl-video-export';

Quick Start

// Add the control to your map
map.addControl(new maplibregl.VideoExportControl());

That's it! The plugin will try to automatically detect your map's features and create appropriate animations (happily or not).

Options

const videoExport = new maplibregl.VideoExportControl({
    // Animation type
    animation: 'smart',     // 'smart', 'orbit', 'pulse', 'figure8', 'spiral', or custom function
    duration: 30000,        // Animation duration in milliseconds

    // Video settings
    format: 'webm-vp9',    // 'webm-vp9' (recommended), 'webm-vp8', or 'mp4'
    resolution: 'auto',     // 'auto', 'hd', 'fullhd', '4k', or {width, height}
    fps: 60,               // Frames per second
    bitrate: 8000,         // Video bitrate in kbps

    // Geographic constraints
    maxBounds: null,        // [[west, south], [east, north]] - Limit animation area
    minZoom: null,          // Minimum zoom level (0-24)
    maxZoom: null,          // Maximum zoom level (0-24)
    strictBounds: false,    // Strictly enforce boundaries
    showBoundsOverlay: false,// Show visual boundary on map (will be captured if true)

    // Waypoints (Points of Interest)
    waypoints: null,        // Array of waypoint objects (see below)
    // [{
    //   center: [lng, lat],    // REQUIRED: coordinates
    //   zoom: 15,              // Optional: zoom level
    //   bearing: -45,          // Optional: camera rotation
    //   pitch: 60,             // Optional: camera tilt
    //   duration: 3000,        // Optional: pause duration (ms)
    //   name: 'Eiffel Tower',  // Optional: display name
    //   icon: 'monument'       // Optional: icon type
    // }]

    // UI
    position: 'top-left',  // Control position
    collapsed: true,        // Start collapsed

    // Callbacks
    onStart: () => console.log('Recording started'),
    onProgress: (frame, time) => console.log(`Frame ${frame}`),
    onComplete: (blob, frames) => console.log('Video ready!'),
    onError: (error) => console.error(error)
});

map.addControl(videoExport);

Examples

Basic Usage

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
    <script src="https://unpkg.com/maplibre-gl-video-export@latest/dist/maplibre-gl-video-export/maplibre-gl-video-export.js"></script>
    <link href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" rel="stylesheet" />
</head>
<body>
    <div id="map" style="width: 100%; height: 100vh;"></div>
    <script>
        const map = new maplibregl.Map({
            container: 'map',
            style: 'https://demotiles.maplibre.org/style.json',
            center: [0, 0],
            zoom: 2
        });

        map.on('load', () => {
            map.addControl(new maplibregl.VideoExportControl());
        });
    </script>
</body>
</html>

With Terrain

map.on('load', () => {
    // Add terrain (AWS Terrarium - free, no token required)
    map.addSource('terrarium', {
        type: 'raster-dem',
        tiles: ['https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png'],
        minzoom: 0,
        maxzoom: 15,
        tileSize: 256,
        encoding: 'terrarium'
    });

    map.setTerrain({
        source: 'terrarium',
        exaggeration: 1.5
    });

    // Add video export - will auto-detect terrain
    map.addControl(new maplibregl.VideoExportControl({
        animation: 'smart',     // Will create mountain vistas
        format: 'webm-vp9',     // Recommended format
        resolution: '4k'        // High res for terrain
    }));
});

Waypoints (Points of Interest)

Define specific locations to visit or include in your animations:

map.addControl(new maplibregl.VideoExportControl({
    animation: 'droneShot',
    duration: 60000,

    // Define waypoints to visit
    waypoints: [
        {
            center: [2.294, 48.858],
            zoom: 16,
            bearing: 45,
            pitch: 60,
            duration: 5000,
            name: 'Eiffel Tower',
            icon: 'monument'
        },
        {
            center: [2.337, 48.861],
            zoom: 16,
            name: 'Louvre Museum',
            icon: 'monument',
            duration: 5000
        },
        {
            center: [2.349, 48.853],
            zoom: 17,
            name: 'Notre-Dame',
            icon: 'monument',
            duration: 5000
        }
    ]
}));

Geographic Constraints

Keep your animations within specific boundaries and zoom levels:

map.addControl(new maplibregl.VideoExportControl({
    animation: 'orbit',
    duration: 30000,

    // Constrain to Paris area
    maxBounds: [[2.224, 48.816], [2.469, 48.902]],
    minZoom: 10,  // City level
    maxZoom: 16,  // Street level
    strictBounds: true,  // Hard enforcement
    showBoundsOverlay: true  // Visual feedback
}));

The plugin will automatically:

  • Keep the camera within the specified bounds
  • Limit zoom to the defined range
  • Show a visual overlay of the allowed area
  • Adjust animations to respect constraints

Geographic constraints help keep animations focused on specific areas of interest.

Custom Animation

const customAnimation = async (map, updateStatus) => {
    updateStatus('Starting custom animation...');

    await map.flyTo({
        center: [-122.4, 37.8], // San Francisco
        zoom: 15,
        duration: 5000
    });
    await map.once('moveend');

    updateStatus('Complete!');
};

map.addControl(new maplibregl.VideoExportControl({
    animation: customAnimation
}));

📖 Tutorial - Coming soon! Step-by-step guide on creating custom animation scenarios.

Performance Tips

Optimize Your Map

  • Close other tabs during recording
  • Use lower resolutions for longer animations
  • Disable unnecessary map features during export
  • Record at 24/30fps instead of 60fps for larger maps

SIMD Support

WebAssembly SIMD is enabled by default in modern browsers and provides 2-3x faster encoding for VP8 codec.

The plugin automatically detects SIMD support and falls back gracefully if unavailable.

How It Works

  1. Detects Features - Analyzes your map for terrain, 3D buildings, layers, fonts, icons
  2. Plans Animation - Creates a cinematic sequence based on detected features
  3. Controls Time - Uses setNow() for deterministic frame-by-frame rendering
  4. Captures Frames - Reads WebGL canvas at exact time intervals
  5. Encodes Video - Uses encoder to create video
  6. Downloads File - Automatically downloads the finished video

Data Security

This plugin uses browser localStorage to persist waypoints and settings. The plugin captures canvas data from MapLibre GL for video generation. All this data remains client-side (never transmitted to external servers)

License

BSD-3-Clause

Credits

This plugin was inspired by the original time control idea from @mourner (Vladimir Agafonkin), creator of Leaflet, core contributor to Mapbox GL JS.

Built with:

  • mediabunny by Yahweasel - JavaScript media toolkit for VP9/WebM encoding and muxing (MPL-2.0)
  • webm-wasm by Google Chrome Labs - WebAssembly VP8/WebM video encoding (royalty-free)
  • mp4-h264 package - WebAssembly H.264 video encoding (MIT License, see H.264 patent notice above)
  • wasm-feature-detect by Google Chrome Labs - SIMD capability detection
  • MapLibre GL JS - Open-source map rendering engine

Special thanks:

  • MapLibre community for the amazing open-source mapping library
  • OpenFreeMap for free vector tiles used in the demo
  • OpenStreetMap contributors
  • Mapzen for Terrarium DEM, AWS ODP for hosting those tiles for free
  • ESRI for free high-quality satellite imagery tiles also used in the demo

Created with ❤️, 🐱 & ☕ by Brice Person

Contributing

PRs welcome! Please check the issues for feature requests and bugs.

See CONTRIBUTING.md for guidelines.