w

Contoh Kode

Contoh implementasi dan kode sampel untuk Player M3U8 Online.

Contoh HTML/JavaScript Dasar

Player Sederhana

<!DOCTYPE html>
<html lang="id">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Player M3U8 - Contoh Dasar</title>
    <link href="https://vjs.zencdn.net/8.6.1/video-js.css" rel="stylesheet" />
  </head>
  <body>
    <div class="container">
      <h1>Player Stream M3U8</h1>

      <!-- Kontainer Player -->
      <video-js
        id="m3u8-player"
        class="vjs-default-skin"
        controls
        preload="auto"
        width="800"
        height="450"
        data-setup="{}"
      >
        <p class="vjs-no-js">
          Untuk memutar video ini, aktifkan JavaScript.
          <a href="https://videojs.com/html5-video-support/" target="_blank">
            Browser yang mendukung Video.js </a
          >.
        </p>
      </video-js>

      <!-- Panel Kontrol -->
      <div class="controls">
        <input type="url" id="stream-url" placeholder="Masukkan URL M3U8" />
        <button id="load-btn">Muat</button>
        <button id="play-btn">Putar</button>
        <button id="pause-btn">Jeda</button>
      </div>

      <!-- Informasi -->
      <div class="info">
        <p>Waktu saat ini: <span id="current-time">0:00</span></p>
        <p>Durasi: <span id="duration">0:00</span></p>
        <p>Kualitas: <span id="quality">Otomatis</span></p>
      </div>
    </div>

    <script src="https://vjs.zencdn.net/8.6.1/video.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@videojs/http-streaming@3.0.2/dist/videojs-http-streaming.min.js"></script>
    <script>
      // Inisialisasi player
      const player = videojs('m3u8-player', {
        html5: {
          vhs: {
            overrideNative: true,
          },
        },
      });

      // Dapatkan elemen DOM
      const streamUrlInput = document.getElementById('stream-url');
      const loadBtn = document.getElementById('load-btn');
      const playBtn = document.getElementById('play-btn');
      const pauseBtn = document.getElementById('pause-btn');
      const currentTimeSpan = document.getElementById('current-time');
      const durationSpan = document.getElementById('duration');
      const qualitySpan = document.getElementById('quality');

      // Atur event listener
      loadBtn.addEventListener('click', loadStream);
      playBtn.addEventListener('click', () => player.play());
      pauseBtn.addEventListener('click', () => player.pause());

      // Fungsi memuat stream
      function loadStream() {
        const url = streamUrlInput.value.trim();
        if (!url) {
          alert('Silakan masukkan URL');
          return;
        }

        try {
          player.src({
            src: url,
            type: 'application/x-mpegURL',
          });
          console.log('Stream dimuat:', url);
        } catch (error) {
          console.error('Error memuat stream:', error);
          alert('Error memuat stream');
        }
      }

      // Fungsi format waktu
      function formatTime(seconds) {
        const hours = Math.floor(seconds / 3600);
        const minutes = Math.floor((seconds % 3600) / 60);
        const secs = Math.floor(seconds % 60);

        if (hours > 0) {
          return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
        } else {
          return `${minutes}:${secs.toString().padStart(2, '0')}`;
        }
      }

      // Monitor event player
      player.on('loadedmetadata', () => {
        durationSpan.textContent = formatTime(player.duration());
      });

      player.on('timeupdate', () => {
        currentTimeSpan.textContent = formatTime(player.currentTime());
      });

      player.on('error', (error) => {
        console.error('Error player:', error);
        alert('Error pemutaran');
      });

      // Atur URL contoh
      streamUrlInput.value =
        'https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8';
    </script>
  </body>
</html>

Contoh Fitur Lanjutan

Pemilihan Kualitas dan Penanganan Error

<!DOCTYPE html>
<html lang="id">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Player M3U8 - Contoh Lanjutan</title>
    <link href="https://vjs.zencdn.net/8.6.1/video-js.css" rel="stylesheet" />
    <style>
      .quality-selector {
        margin: 10px 0;
      }
      .quality-selector select {
        padding: 5px;
        margin-right: 10px;
      }
      .error-message {
        color: red;
        margin: 10px 0;
      }
      .stats {
        background: #f5f5f5;
        padding: 10px;
        margin: 10px 0;
        border-radius: 5px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>Player M3U8 - Fitur Lanjutan</h1>

      <video-js
        id="advanced-player"
        class="vjs-default-skin"
        controls
        preload="auto"
        width="800"
        height="450"
        data-setup="{}"
      >
      </video-js>

      <!-- Pemilih Kualitas -->
      <div class="quality-selector">
        <label for="quality-select">Pilih Kualitas:</label>
        <select id="quality-select">
          <option value="auto">Otomatis</option>
        </select>
      </div>

      <!-- Pesan Error -->
      <div id="error-message" class="error-message" style="display: none;"></div>

      <!-- Informasi Statistik -->
      <div class="stats">
        <h3>Informasi Statistik</h3>
        <p>Bitrate saat ini: <span id="current-bitrate">-</span></p>
        <p>Kesehatan buffer: <span id="buffer-health">-</span></p>
        <p>Status jaringan: <span id="network-state">-</span></p>
      </div>
    </div>

    <script src="https://vjs.zencdn.net/8.6.1/video.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@videojs/http-streaming@3.0.2/dist/videojs-http-streaming.min.js"></script>
    <script>
      // Inisialisasi player
      const player = videojs('advanced-player', {
        html5: {
          vhs: {
            overrideNative: true,
            enableLowInitialPlaylist: true,
            smoothQualityChange: true,
          },
        },
      });

      const qualitySelect = document.getElementById('quality-select');
      const errorMessage = document.getElementById('error-message');
      const currentBitrateSpan = document.getElementById('current-bitrate');
      const bufferHealthSpan = document.getElementById('buffer-health');
      const networkStateSpan = document.getElementById('network-state');

      // Muat stream contoh
      player.src({
        src: 'https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8',
        type: 'application/x-mpegURL',
      });

      // Ketika level kualitas tersedia
      player.on('loadedmetadata', () => {
        updateQualityOptions();
      });

      // Perbarui opsi kualitas
      function updateQualityOptions() {
        const hls = player.tech().hls;
        if (hls && hls.levels) {
          // Hapus opsi yang ada
          qualitySelect.innerHTML = '<option value="auto">Otomatis</option>';

          // Tambahkan level kualitas
          hls.levels.forEach((level, index) => {
            const option = document.createElement('option');
            option.value = index;
            option.textContent = `${level.height}p (${Math.round(level.bitrate / 1000)}kbps)`;
            qualitySelect.appendChild(option);
          });
        }
      }

      // Ubah kualitas
      qualitySelect.addEventListener('change', (e) => {
        const hls = player.tech().hls;
        if (hls) {
          if (e.target.value === 'auto') {
            hls.currentLevel = -1; // Kualitas otomatis
          } else {
            hls.currentLevel = parseInt(e.target.value);
          }
        }
      });

      // Penanganan error
      player.on('error', (error) => {
        console.error('Error player:', error);
        showError(`Terjadi error: ${error.message || 'Error tidak diketahui'}`);

        // Coba pemulihan otomatis
        setTimeout(() => {
          if (player.error()) {
            player.error(null);
            player.load();
          }
        }, 3000);
      });

      // Tampilkan pesan error
      function showError(message) {
        errorMessage.textContent = message;
        errorMessage.style.display = 'block';
        setTimeout(() => {
          errorMessage.style.display = 'none';
        }, 5000);
      }

      // Perbarui informasi statistik
      function updateStats() {
        const hls = player.tech().hls;
        if (hls) {
          const currentLevel = hls.levels[hls.currentLevel];
          if (currentLevel) {
            currentBitrateSpan.textContent = `${Math.round(currentLevel.bitrate / 1000)}kbps`;
          }

          // Hitung kesehatan buffer
          const buffered = player.buffered();
          const currentTime = player.currentTime();
          const duration = player.duration();

          if (buffered.length > 0) {
            const bufferedEnd = buffered.end(buffered.length - 1);
            const bufferHealth = ((bufferedEnd - currentTime) / duration) * 100;
            bufferHealthSpan.textContent = `${bufferHealth.toFixed(1)}%`;
          }
        }

        // Status jaringan
        const networkState = player.networkState();
        const states = ['Status awal', 'Tidak aktif', 'Memuat', 'Tidak ada sumber'];
        networkStateSpan.textContent = states[networkState] || 'Tidak diketahui';
      }

      // Perbarui statistik secara berkala
      setInterval(updateStats, 1000);

      // Perbarui statistik awal
      player.on('canplay', updateStats);
    </script>
  </body>
</html>

Contoh Komponen React

Player M3U8 di React

import React, { useEffect, useRef, useState } from 'react';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';

const M3U8Player = ({ src, options = {} }) => {
  const videoRef = useRef(null);
  const playerRef = useRef(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    // Inisialisasi player
    if (videoRef.current && !playerRef.current) {
      const videoElement = videoRef.current;

      const playerOptions = {
        controls: true,
        responsive: true,
        fluid: true,
        html5: {
          vhs: {
            overrideNative: true,
            enableLowInitialPlaylist: true,
            smoothQualityChange: true,
          },
        },
        ...options,
      };

      playerRef.current = videojs(videoElement, playerOptions);

      // Penanganan error
      playerRef.current.on('error', (error) => {
        console.error('Error player:', error);
        setError('Error pemutaran');
      });

      // Mulai pemuatan
      playerRef.current.on('loadstart', () => {
        setIsLoading(true);
        setError(null);
      });

      // Pemuatan selesai
      playerRef.current.on('canplay', () => {
        setIsLoading(false);
      });
    }

    return () => {
      if (playerRef.current) {
        playerRef.current.dispose();
        playerRef.current = null;
      }
    };
  }, []);

  // Ketika sumber berubah
  useEffect(() => {
    if (playerRef.current && src) {
      playerRef.current.src({
        src: src,
        type: 'application/x-mpegURL',
      });
    }
  }, [src]);

  return (
    <div className="m3u8-player-container">
      {isLoading && (
        <div className="loading-overlay">
          <div className="loading-spinner">Memuat...</div>
        </div>
      )}

      {error && <div className="error-message">{error}</div>}

      <div data-vjs-player>
        <video
          ref={videoRef}
          className="video-js vjs-default-skin"
          controls
          preload="auto"
          data-setup="{}"
        />
      </div>
    </div>
  );
};

// Contoh penggunaan
const App = () => {
  const [streamUrl, setStreamUrl] = useState('');
  const [currentUrl, setCurrentUrl] = useState('');

  const handleLoadStream = () => {
    if (streamUrl.trim()) {
      setCurrentUrl(streamUrl);
    }
  };

  return (
    <div className="app">
      <h1>Player M3U8 - Contoh React</h1>

      <div className="controls">
        <input
          type="url"
          value={streamUrl}
          onChange={(e) => setStreamUrl(e.target.value)}
          placeholder="Masukkan URL M3U8"
        />
        <button onClick={handleLoadStream}>Muat</button>
      </div>

      {currentUrl && (
        <M3U8Player
          src={currentUrl}
          options={{
            width: 800,
            height: 450,
          }}
        />
      )}
    </div>
  );
};

export default App;

Contoh Komponen Vue.js

Player M3U8 di Vue.js

<template>
  <div class="m3u8-player-wrapper">
    <div class="controls">
      <input
        v-model="streamUrl"
        type="url"
        placeholder="Masukkan URL M3U8"
        @keyup.enter="loadStream"
      />
      <button @click="loadStream" :disabled="!streamUrl.trim()">Muat</button>
    </div>

    <div v-if="error" class="error-message">
      {{ error }}
    </div>

    <div v-if="isLoading" class="loading-message">Memuat...</div>

    <div ref="playerContainer" class="player-container"></div>
  </div>
</template>

<script>
import videojs from 'video.js';
import 'video.js/dist/video-js.css';

export default {
  name: 'M3U8Player',
  props: {
    initialUrl: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      streamUrl: this.initialUrl,
      player: null,
      error: null,
      isLoading: false,
    };
  },
  mounted() {
    this.initializePlayer();
    if (this.initialUrl) {
      this.loadStream();
    }
  },
  beforeUnmount() {
    if (this.player) {
      this.player.dispose();
    }
  },
  methods: {
    initializePlayer() {
      const videoElement = document.createElement('video');
      videoElement.className = 'video-js vjs-default-skin';
      videoElement.controls = true;
      videoElement.preload = 'auto';
      videoElement.width = 800;
      videoElement.height = 450;

      this.$refs.playerContainer.appendChild(videoElement);

      this.player = videojs(videoElement, {
        html5: {
          vhs: {
            overrideNative: true,
            enableLowInitialPlaylist: true,
            smoothQualityChange: true,
          },
        },
      });

      // Atur event listener
      this.player.on('error', this.handleError);
      this.player.on('loadstart', () => {
        this.isLoading = true;
        this.error = null;
      });
      this.player.on('canplay', () => {
        this.isLoading = false;
      });
    },

    loadStream() {
      if (!this.streamUrl.trim()) {
        this.error = 'Silakan masukkan URL';
        return;
      }

      if (!this.player) {
        this.error = 'Player tidak diinisialisasi';
        return;
      }

      try {
        this.player.src({
          src: this.streamUrl,
          type: 'application/x-mpegURL',
        });
      } catch (err) {
        this.handleError(err);
      }
    },

    handleError(error) {
      console.error('Error player:', error);
      this.error = 'Error memuat stream';
      this.isLoading = false;
    },
  },
};
</script>

<style scoped>
.m3u8-player-wrapper {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.controls {
  margin-bottom: 20px;
}

.controls input {
  width: 70%;
  padding: 8px;
  margin-right: 10px;
}

.controls button {
  padding: 8px 16px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.controls button:disabled {
  background: #ccc;
  cursor: not-allowed;
}

.error-message {
  color: red;
  background: #ffe6e6;
  padding: 10px;
  border-radius: 4px;
  margin-bottom: 20px;
}

.loading-message {
  color: #007bff;
  text-align: center;
  padding: 20px;
}

.player-container {
  background: #000;
  border-radius: 8px;
  overflow: hidden;
}
</style>

Contoh-contoh kode ini memungkinkan Anda mengimplementasikan Player M3U8 Online di berbagai lingkungan dan framework.

Apakah halaman ini membantu?