Skip to content

Use Cases ​

Real-world applications and industry-specific examples for Movi-Player.

Demuxer Use Cases ​

The lightweight demuxer module (~45KB) is perfect for metadata extraction without playback.

Media Asset Management (MAM) ​

Catalog and index large video libraries:

typescript
import { Demuxer, HttpSource } from "movi-player/demuxer";

async function catalogVideo(url: string) {
  const source = new HttpSource(url);
  const demuxer = new Demuxer(source);
  const info = await demuxer.open();

  const video = demuxer.getVideoTracks()[0];

  const result = {
    duration: info.duration,
    resolution: `${video.width}x${video.height}`,
    codec: video.codec,
    isHDR: video.isHDR,
    hdrFormat: video.isHDR
      ? video.colorTransfer === "smpte2084"
        ? "HDR10"
        : "HLG"
      : null,
    audioTracks: demuxer.getAudioTracks().map((t) => ({
      language: t.language,
      channels: t.channels,
      codec: t.codec,
    })),
    subtitles: demuxer.getSubtitleTracks().map((t) => ({
      language: t.language,
      codec: t.codec,
    })),
  };

  demuxer.close();
  return result;
}

Video File Validator ​

Validate uploaded videos meet platform requirements:

typescript
import { Demuxer, FileSource } from "movi-player/demuxer";

interface ValidationResult {
  valid: boolean;
  errors: string[];
  metadata?: object;
}

async function validateUpload(file: File): Promise<ValidationResult> {
  const source = new FileSource(file);
  const demuxer = new Demuxer(source);

  try {
    const info = await demuxer.open();
    const video = demuxer.getVideoTracks()[0];

    const errors: string[] = [];

    if (video.width > 3840 || video.height > 2160) {
      errors.push("Resolution exceeds 4K limit");
    }

    if (!["h264", "hevc", "vp9", "av1"].includes(video.codec)) {
      errors.push("Unsupported video codec");
    }

    if (info.duration > 3600) {
      errors.push("Duration exceeds 1 hour limit");
    }

    demuxer.close();

    return {
      valid: errors.length === 0,
      errors,
      metadata: {
        duration: info.duration,
        resolution: `${video.width}x${video.height}`,
        codec: video.codec,
      },
    };
  } catch (error) {
    return { valid: false, errors: ["Invalid video file"] };
  }
}

HDR Content Detection ​

Automatically detect and tag HDR content:

typescript
import { Demuxer, HttpSource } from "movi-player/demuxer";

async function detectHDR(videoUrls: string[]) {
  return Promise.all(
    videoUrls.map(async (url) => {
      const source = new HttpSource(url);
      const demuxer = new Demuxer(source);
      await demuxer.open();

      const video = demuxer.getVideoTracks()[0];

      const result = {
        url,
        isHDR: video.isHDR,
        colorSpace: {
          primaries: video.colorPrimaries,
          transfer: video.colorTransfer,
          matrix: video.colorSpace,
        },
        hdrFormat:
          video.colorTransfer === "smpte2084"
            ? "HDR10"
            : video.colorTransfer === "arib-std-b67"
              ? "HLG"
              : null,
      };

      demuxer.close();
      return result;
    }),
  );
}

Player Use Cases ​

The player module (~180KB) provides full playback with custom UI.

Custom Branded Player ​

Build a branded video player:

typescript
import { MoviPlayer, LogLevel } from "movi-player/player";

class CustomVideoPlayer {
  private player: MoviPlayer;
  private canvas: HTMLCanvasElement;

  constructor(container: HTMLElement) {
    this.canvas = document.createElement("canvas");
    container.appendChild(this.canvas);

    MoviPlayer.setLogLevel(LogLevel.ERROR);

    this.player = new MoviPlayer({
      source: { type: "url", url: "" },
      canvas: this.canvas,
      renderer: "canvas",
      decoder: "auto",
    });

    this.setupControls(container);
    this.setupEvents();
  }

  private setupControls(container: HTMLElement) {
    const controls = document.createElement("div");
    controls.innerHTML = `
      <button id="play">Play</button>
      <button id="pause">Pause</button>
      <input type="range" id="seek" min="0" max="100">
      <span id="time">0:00 / 0:00</span>
    `;
    container.appendChild(controls);

    controls.querySelector("#play")!.onclick = () => this.player.play();
    controls.querySelector("#pause")!.onclick = () => this.player.pause();
  }

  private setupEvents() {
    this.player.on("stateChange", (state) => {
      console.log("State:", state);
    });

    this.player.on("error", (error) => {
      console.error("Error:", error);
    });
  }

  async load(url: string) {
    this.player = new MoviPlayer({
      source: { type: "url", url },
      canvas: this.canvas,
    });
    await this.player.load();
  }
}

E-Learning Platform ​

Interactive video with quizzes:

typescript
import { MoviPlayer } from "movi-player/player";

interface QuizPoint {
  timestamp: number;
  question: string;
  answers: string[];
  correct: number;
  completed: boolean;
}

class InteractiveLearningVideo {
  private player: MoviPlayer;
  private quizPoints: QuizPoint[] = [];

  constructor(canvas: HTMLCanvasElement) {
    this.player = new MoviPlayer({
      source: { type: "url", url: "" },
      canvas,
    });
  }

  async loadCourse(url: string, quizzes: QuizPoint[]) {
    this.quizPoints = quizzes;

    this.player = new MoviPlayer({
      source: { type: "url", url },
      canvas: document.getElementById("canvas") as HTMLCanvasElement,
    });

    // Check for quiz points during playback
    setInterval(() => {
      const currentTime = this.player.getCurrentTime();

      const quiz = this.quizPoints.find(
        (q) => Math.abs(currentTime - q.timestamp) < 0.5 && !q.completed,
      );

      if (quiz) {
        this.player.pause();
        this.showQuiz(quiz);
      }
    }, 500);

    await this.player.load();
  }

  private showQuiz(quiz: QuizPoint) {
    // Show quiz UI, pause video until answered
  }
}

Multi-Language Platform ​

Netflix-style audio/subtitle switching:

typescript
import { MoviPlayer } from "movi-player/player";

class MultiLanguagePlayer {
  private player: MoviPlayer;

  async initialize(url: string, canvas: HTMLCanvasElement) {
    this.player = new MoviPlayer({
      source: { type: "url", url },
      canvas,
    });

    await this.player.load();
    this.buildTrackMenu();
  }

  private buildTrackMenu() {
    const audioTracks = this.player.getAudioTracks();
    const subtitleTracks = this.player.getSubtitleTracks();

    console.log(
      "Audio tracks:",
      audioTracks.map((t) => ({
        id: t.id,
        language: t.language,
        channels: t.channels === 6 ? "5.1" : "2.0",
      })),
    );

    console.log(
      "Subtitle tracks:",
      subtitleTracks.map((t) => ({
        id: t.id,
        language: t.language,
      })),
    );
  }

  switchAudio(trackId: number) {
    this.player.selectAudioTrack(trackId);
  }

  switchSubtitle(trackId: number | null) {
    this.player.selectSubtitleTrack(trackId);
  }
}

Thumbnail Generation ​

Generate video thumbnails:

typescript
import { MoviPlayer } from "movi-player/player";

class ThumbnailGenerator {
  async generateThumbnails(url: string, count: number = 10): Promise<Blob[]> {
    const canvas = document.createElement("canvas");
    const player = new MoviPlayer({
      source: { type: "url", url },
      canvas,
      enablePreviews: true,
    });

    await player.load();

    const duration = player.getDuration();
    const interval = duration / (count + 1);
    const thumbnails: Blob[] = [];

    for (let i = 1; i <= count; i++) {
      const timestamp = interval * i;
      const thumbnail = await player.generatePreview(timestamp, 320, 180);
      thumbnails.push(thumbnail);
    }

    player.destroy();
    return thumbnails;
  }
}

Element Use Cases ​

The full element (~410KB) provides drop-in video player.

CMS Integration ​

WordPress/Drupal video player:

html
<movi-player
  src="https://cdn.example.com/videos/tutorial.mp4"
  poster="https://cdn.example.com/thumbnails/tutorial.jpg"
  controls
  width="800"
  height="450"
></movi-player>

E-Commerce Product Videos ​

Shopify product showcase:

html
<div class="product-video">
  <movi-player
    src="https://cdn.shop.com/products/demo.mp4"
    poster="https://cdn.shop.com/products/thumb.jpg"
    hdr
    theme="light"
    objectfit="contain"
    controls
    autoplay
    muted
    loop
  ></movi-player>
</div>

<script type="module">
  import "movi-player";

  const player = document.querySelector("movi-player");

  player.addEventListener("ended", () => {
    showAddToCartButton();
  });
</script>

News & Media ​

Auto-play muted with scroll detection:

html
<article>
  <h1>Breaking News</h1>

  <movi-player
    src="https://news.cdn.com/videos/story.mp4"
    controls
    autoplay
    muted
    theme="dark"
    style="width: 100%; max-width: 800px;"
  ></movi-player>
</article>

<script type="module">
  import "movi-player";

  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        const player = entry.target;
        if (entry.isIntersecting) {
          player.play();
        } else {
          player.pause();
        }
      });
    },
    { threshold: 0.5 },
  );

  document.querySelectorAll("movi-player").forEach((player) => {
    observer.observe(player);
  });
</script>

Online Course Platform ​

Progress tracking:

html
<movi-player
  id="course-video"
  src="https://courses.com/lessons/lesson-01.mp4"
  controls
  theme="dark"
></movi-player>

<script type="module">
  import "movi-player";

  const player = document.getElementById("course-video");

  // Save progress
  player.addEventListener("timeupdate", (e) => {
    const progress = player.currentTime / player.duration;
    localStorage.setItem("course-progress", progress.toString());
  });

  // Resume from last position
  player.addEventListener("loadedmetadata", () => {
    const saved = parseFloat(localStorage.getItem("course-progress") || "0");
    if (saved > 0) {
      player.currentTime = saved * player.duration;
    }
  });

  // Next lesson
  player.addEventListener("ended", () => {
    showNextLessonButton();
  });
</script>

Portfolio Demo Reel ​

HDR with ambient mode:

html
<div class="demo-reel">
  <movi-player
    src="https://portfolio.com/demo-reel.mp4"
    poster="https://portfolio.com/demo-thumb.jpg"
    controls
    hdr
    ambientmode
    theme="dark"
    objectfit="cover"
    style="width: 100%; height: 600px; border-radius: 12px;"
  ></movi-player>
</div>

Industry Applications ​

IndustryModuleKey Features
Streaming PlatformsElement/PlayerMulti-track, HDR, subtitles
E-CommerceElementProduct videos, loop, autoplay
EducationPlayerQuizzes, chapters, progress
News/MediaElementAuto-play muted, scroll detection
MAM SystemsDemuxerMetadata extraction, indexing
Video ValidatorsDemuxerFile validation, codec check
TranscodingDemuxerPre-inspection, preset selection
Digital SignageElementLoop, fullscreen, HDR

Released under the Apache-2.0 License.