# Best Alternatives to ArtPlayer for Video Playback in LunaTV

> Explore top ArtPlayer alternatives for LunaTV like Video.js, Plyr, and Shaka Player. Easily integrate them to enhance your video playback experience while keeping HLS compatibility and custom controls.

- Repository: [MoonTechLab/LunaTV](https://github.com/MoonTechLab/LunaTV)
- Tags: comparison
- Published: 2026-09-08

---

**LunaTV currently ships only with ArtPlayer, but you can replace it with Video.js, Plyr, or Shaka Player by modifying the initialization logic in [`src/app/play/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/play/page.tsx) while preserving HLS streaming compatibility and custom UI controls like skip-intro and wake-lock.**

LunaTV is an open-source streaming platform built around ArtPlayer for HTML5 video delivery. While ArtPlayer handles adaptive streaming through its tight integration with HLS.js, developers seeking different UI paradigms, DRM support, or enterprise-grade error handling often explore alternatives to ArtPlayer for video playback in LunaTV. This guide examines three production-ready video players and provides the exact integration steps needed to swap the default player without disrupting the application's stream management or feature set.

## How ArtPlayer is Currently Integrated in LunaTV

LunaTV instantiates ArtPlayer in the main playback pages, specifically within [`src/app/play/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/play/page.tsx) and [`src/app/live/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/live/page.tsx). The player lifecycle is managed through a `cleanupPlayer` function that destroys instances when components unmount or stream URLs change. The project relies on `artplayer-plugin-hls` for adaptive bitrate streaming, consuming URLs generated by [`src/lib/downstream.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/downstream.ts) and metadata from [`src/lib/fetchVideoDetail.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/fetchVideoDetail.ts).

Because the repository contains no abstraction layer for player swapping, switching to an alternative requires replacing the ArtPlayer initialization block while maintaining the same `videoUrl` prop pipeline and HLS.js-compatible manifest sources.

## Top 3 Alternatives to ArtPlayer for Video Playback in LunaTV

### Video.js

**Video.js** offers the most mature ecosystem for HTML5 video, with native HLS support and extensive plugin architecture. It fits LunaTV’s React codebase through its robust API for programmatic control.

To integrate Video.js:

1. Install the dependency:

```bash
pnpm add video.js

```

2. Replace the ArtPlayer import and initialization in [`src/app/play/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/play/page.tsx):

```tsx
import videojs from 'video.js';
import 'video.js/dist/video-js.css';

// Inside your component
const videoRef = useRef<HTMLVideoElement>(null);
const playerRef = useRef<any>(null);

useEffect(() => {
  if (!videoUrl || !videoRef.current) return;
  
  playerRef.current = videojs(videoRef.current, {
    autoplay: true,
    fluid: true,
    html5: {
      vhs: {
        overrideNative: true,
        limitRenditionByPlayerDimensions: true
      }
    }
  });
  
  playerRef.current.src({
    src: videoUrl,
    type: 'application/x-mpegURL'
  });
  
  // Replicate cleanupPlayer behavior
  return () => {
    if (playerRef.current) {
      playerRef.current.dispose();
      playerRef.current = null;
    }
  };
}, [videoUrl]);

```

3. Map LunaTV’s custom controls (skip-intro, wake-lock) to Video.js’s event system using `player.on('timeupdate', ...)` and `player.requestFullscreen()`.

### Plyr

**Plyr** provides a lightweight, customizable interface with built-in HLS support via native HTML5 video elements. It is ideal if you want a cleaner default UI without sacrificing streaming capabilities.

To implement Plyr:

1. Add the package:

```bash
pnpm add plyr

```

2. Insert a standard video element and instantiate Plyr in [`src/app/play/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/play/page.tsx):

```tsx
import Plyr from 'plyr';
import 'plyr/dist/plyr.css';

useEffect(() => {
  if (!videoRef.current || !videoUrl) return;
  
  const player = new Plyr(videoRef.current, {
    autoplay: true,
    muted: false,
    controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'settings', 'pip', 'airplay', 'fullscreen']
  });
  
  // Load HLS manifest directly
  if (Hls.isSupported()) {
    const hls = new Hls();
    hls.loadSource(videoUrl);
    hls.attachMedia(videoRef.current);
  } else {
    videoRef.current.src = videoUrl;
  }
  
  return () => player.destroy();
}, [videoUrl]);

```

3. Wire LunaTV’s episode selection and skip-config features to Plyr’s API methods like `player.currentTime` and `player.on('seeked', ...)`.

### Shaka Player

**Shaka Player** is Google’s enterprise-grade streaming library, offering superior DRM support and robust error recovery for DASH and HLS manifests. Choose this alternative if LunaTV requires Widevine or FairPlay integration.

To configure Shaka Player:

1. Install via package manager:

```bash
pnpm add shaka-player

```

2. Initialize the player in the playback page:

```tsx
import shaka from 'shaka-player';

useEffect(() => {
  if (!videoRef.current || !videoUrl) return;
  
  const player = new shaka.Player(videoRef.current);
  
  // Check browser support
  if (shaka.Player.isBrowserSupported()) {
    player.load(videoUrl).catch(error => {
      console.error('Error loading manifest:', error);
    });
  }
  
  // Replicate cleanupPlayer
  return () => {
    player.destroy();
  };
}, [videoUrl]);

```

3. Implement skip-intro/outro logic using Shaka’s `player.seekRange()` to determine valid seek boundaries and `player.getMediaElement().currentTime` for precise positioning.

## Step-by-Step Migration Guide

Migrating from ArtPlayer to any alternative requires modifying exactly one critical code block in [`src/app/play/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/play/page.tsx). Locate the function that currently calls `new ArtPlayer({...})` and replace it with your chosen player’s initialization pattern.

Preserve these LunaTV dependencies during migration:

- **Stream sources**: Continue consuming `videoUrl` values from [`src/lib/downstream.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/downstream.ts), as all three alternatives support the HLS manifests already generated by LunaTV’s backend.
- **Metadata**: Retain imports from [`src/lib/fetchVideoDetail.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/fetchVideoDetail.ts) to populate episode titles and thumbnails.
- **Cleanup logic**: Ensure your new player implementation mirrors the `cleanupPlayer` pattern to prevent memory leaks when switching episodes or navigating away from [`src/app/live/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/live/page.tsx).

Update [`package.json`](https://github.com/MoonTechLab/LunaTV/blob/main/package.json) to remove `artplayer` and `artplayer-plugin-hls` if eliminating ArtPlayer entirely, or keep them alongside new dependencies if supporting multiple players concurrently.

## Preserving LunaTV Features During Player Migration

When implementing alternatives to ArtPlayer for video playback in LunaTV, you must manually reconnect three core features:

- **Skip Intro/Outro**: Store timestamp offsets in your component state and call `player.currentTime(skipEndTimestamp)` when the playhead reaches the intro start time. Video.js uses `player.currentTime()`, Plyr uses `player.forward()`, and Shaka uses `player.getMediaElement().currentTime = value`.

- **Wake Lock**: Maintain the existing `WakeLock` API calls in your page component, independent of the video player instance, since this feature relies on browser permissions rather than player APIs.

- **Episode Selection**: Continue using the episode data from [`fetchVideoDetail.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/fetchVideoDetail.ts) to populate your UI controls. When users select a new episode, update the `videoUrl` state; your player’s `useEffect` dependency array will trigger the cleanup and re-initialization cycle automatically.

## Summary

- LunaTV hardcodes ArtPlayer in [`src/app/play/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/play/page.tsx) and [`src/app/live/page.tsx`](https://github.com/MoonTechLab/LunaTV/blob/main/src/app/live/page.tsx) with no built-in abstraction for alternative players.
- **Video.js**, **Plyr**, and **Shaka Player** all support LunaTV’s existing HLS stream URLs generated by [`src/lib/downstream.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/downstream.ts).
- Replacement requires swapping the ArtPlayer initialization block and `cleanupPlayer` logic while preserving the `videoUrl` prop pipeline.
- Custom features like skip-intro, wake-lock, and episode selection must be mapped to the new player’s specific API methods.
- All three alternatives can coexist with LunaTV’s React architecture and streaming infrastructure without modifying backend endpoints.

## Frequently Asked Questions

### Does LunaTV support multiple video players out of the box?

No. According to the MoonTechLab/LunaTV source code, the repository ships exclusively with ArtPlayer and `artplayer-plugin-hls`. There is no configuration toggle or plugin system to enable alternative players without modifying the playback page source files.

### Which video player is best for HLS streaming in LunaTV?

**Video.js** is generally the best drop-in replacement for HLS streaming due to its mature VHS engine and extensive documentation. However, if you require DRM support for protected content, **Shaka Player** provides superior Widevine and FairPlay integration compared to both ArtPlayer and Video.js.

### How do I replace ArtPlayer without breaking existing features?

Focus on three integration points: maintain the `videoUrl` consumption pattern from [`src/lib/downstream.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/downstream.ts), replicate the `cleanupPlayer` disposal logic to prevent memory leaks, and remap LunaTV’s custom controls (skip-intro, airplay, wake-lock) to the new player’s event system. The underlying episode metadata from [`src/lib/fetchVideoDetail.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/fetchVideoDetail.ts) remains compatible regardless of which player you choose.

### Will switching players affect the HLS stream URLs?

No. The stream URLs generated by [`src/lib/downstream.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/downstream.ts) are standard HLS manifests compatible with any HTML5 video player. Video.js, Plyr, and Shaka Player all support the same `videoUrl` format currently used by ArtPlayer, ensuring your backend configuration remains unchanged during migration.