Skip to content

Add a Video in Maptoolkit Maps JS

A video source in Maptoolkit Maps JS lets you project any video file onto a geographic quadrilateral so it stays locked to real-world coordinates as you pan and zoom. You define the corner coordinates of the video overlay and control playback through the source’s play and pause methods. Use this technique to show timelapse footage, drone video, or animated map overlays tied to a specific location.

const API_KEY = 'YOUR_API_KEY';

    const videoStyle = {
        version: 8,
        sources: {
            'raster-map': {
                type: 'raster',
                tiles: [`https://rtc-cdn.maptoolkit.net/rtc/maptoolkit-maptoolkit.summer/{z}/{x}/{y}.png?api_key=${API_KEY}`],
                tileSize: 256
            },
            video: {
                type: 'video',
                urls: [
                    'https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4',
                    'https://static-assets.mapbox.com/mapbox-gl-js/drone.webm'
                ],
                coordinates: [
                    [-122.51596391201019, 37.56238816766053],
                    [-122.51467645168304, 37.56410183312965],
                    [-122.51309394836426, 37.563391708549425],
                    [-122.51423120498657, 37.56161849366671]
                ]
            }
        },
        layers: [
            { id: 'background', type: 'background', paint: { 'background-color': 'rgb(4,7,14)' } },
            { id: 'raster-map', type: 'raster', source: 'raster-map' },
            { id: 'video', type: 'raster', source: 'video' }
        ]
    };

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        minZoom: 14,
        zoom: 17,
        center: [-122.514426, 37.562984],
        bearing: -96,
        style: videoStyle,
        attributionControl: { compact: false }
    });

    map.addControl(new maptoolkit.NavigationControl(), 'top-right');

    let playingVideo = true;

    map.on('click', () => {
        playingVideo = !playingVideo;
        if (playingVideo) map.getSource('video').play();
        else map.getSource('video').pause();
    });
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Add a Video - Maptoolkit Maps JS</title>
    <meta property="og:description" content="Display a video overlay on top of a raster map." />
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
    <style>
        html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
        #map { width: 100%; height: 100%; }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    const API_KEY = 'YOUR_API_KEY';

    const videoStyle = {
        version: 8,
        sources: {
            'raster-map': {
                type: 'raster',
                tiles: [`https://rtc-cdn.maptoolkit.net/rtc/maptoolkit-maptoolkit.summer/{z}/{x}/{y}.png?api_key=${API_KEY}`],
                tileSize: 256
            },
            video: {
                type: 'video',
                urls: [
                    'https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4',
                    'https://static-assets.mapbox.com/mapbox-gl-js/drone.webm'
                ],
                coordinates: [
                    [-122.51596391201019, 37.56238816766053],
                    [-122.51467645168304, 37.56410183312965],
                    [-122.51309394836426, 37.563391708549425],
                    [-122.51423120498657, 37.56161849366671]
                ]
            }
        },
        layers: [
            { id: 'background', type: 'background', paint: { 'background-color': 'rgb(4,7,14)' } },
            { id: 'raster-map', type: 'raster', source: 'raster-map' },
            { id: 'video', type: 'raster', source: 'video' }
        ]
    };

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        minZoom: 14,
        zoom: 17,
        center: [-122.514426, 37.562984],
        bearing: -96,
        style: videoStyle,
        attributionControl: { compact: false }
    });

    map.addControl(new maptoolkit.NavigationControl(), 'top-right');

    let playingVideo = true;

    map.on('click', () => {
        playingVideo = !playingVideo;
        if (playingVideo) map.getSource('video').play();
        else map.getSource('video').pause();
    });
</script>
</body>
</html>

Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.

Use the Maptoolkit Connector. Create an interactive map with zoom level 17, centered around [-122.514426, 37.562984], with bearing -96. Overlay a video source (https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4) on the map with click to play/pause.

How it works

A video source pins a video to four geographic corners, in the order top-left, top-right, bottom-right, bottom-left. The video then behaves like an image layer: it stays locked to the ground as you pan, zoom and rotate.

urls takes several files so the browser can pick a format it supports, which is why both MP4 and WebM are listed. Offering only one format means silent failure in browsers that cannot play it.

Autoplay is the usual trip hazard. Browsers block autoplaying video with sound, so a video layer that must start on its own has to be muted.

The corners are fixed geographic positions, so the footage is stretched to fit them. Drone or satellite footage needs to be georeferenced beforehand; this does not align it for you.

Next steps

Video on a map is niche, and where it works is usually drone or survey footage over the ground it covers. The next step is controls: play, pause and a scrubber, since a looping video with no way to stop it is more distracting than informative.

If the footage moves rather than covers a fixed extent, this is the wrong tool. A moving marker synchronised to playback keeps the map honest about where the camera was.