Skip to content

HLS Playback Guide

Learn how to integrate HLS video playback into your web and mobile applications.

HLS Delivery Flow

HLS URL Format

https://{cdn-host}/live/{streamKey}/hls.m3u8

Example:

https://stream.lunarstream.kozow.com/live/ee04affe2a669854052102fe762bd715/hls.m3u8

Adaptive Bitrate Streaming

Web Player (Video.js)

Basic Setup

html
<!DOCTYPE html>
<html>
<head>
  <link href="https://vjs.zencdn.net/8.0.4/video-js.css" rel="stylesheet">
  <style>
    .video-container { max-width: 800px; margin: 0 auto; }
    .video-js { width: 100%; aspect-ratio: 16/9; }
  </style>
</head>
<body>
  <div class="video-container">
    <video id="live-player" class="video-js vjs-default-skin" controls>
      <source src="https://stream.lunarstream.kozow.com/live/YOUR_STREAM_KEY/hls.m3u8"
              type="application/x-mpegURL">
    </video>
  </div>

  <script src="https://vjs.zencdn.net/8.0.4/video.min.js"></script>
  <script>
    const player = videojs('live-player', {
      liveui: true,
      html5: {
        vhs: {
          overrideNative: true,
          enableLowInitialPlaylist: true
        }
      }
    });
  </script>
</body>
</html>

With CDN Failover

javascript
const player = videojs('live-player');

const cdnUrls = [
  'https://stream.lunarstream.kozow.com/live/STREAM_KEY/hls.m3u8',
  'https://zlmediakit-cdn.b-cdn.net/live/STREAM_KEY/hls.m3u8',
  'https://gcore-zlmediakit.lunarstream.kozow.com/live/STREAM_KEY/hls.m3u8'
];
let currentCdnIndex = 0;

player.on('error', function() {
  console.error('Player error:', player.error());
  tryNextCDN();
});

function tryNextCDN() {
  currentCdnIndex++;
  if (currentCdnIndex < cdnUrls.length) {
    player.src({ src: cdnUrls[currentCdnIndex], type: 'application/x-mpegURL' });
    player.play();
  } else {
    console.error('All CDNs failed');
  }
}

Web Player (HLS.js)

html
<video id="video" controls></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
  const video = document.getElementById('video');
  const hlsUrl = 'https://stream.lunarstream.kozow.com/live/STREAM_KEY/hls.m3u8';

  if (Hls.isSupported()) {
    const hls = new Hls();
    hls.loadSource(hlsUrl);
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED, () => video.play());
  } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    // Safari native HLS support
    video.src = hlsUrl;
    video.play();
  }
</script>

React Native (react-native-video)

javascript
import React, { useState, useRef } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
import Video from 'react-native-video';

const LiveStreamPlayer = ({ hlsSources }) => {
  const videoRef = useRef(null);
  const [currentSourceIndex, setCurrentSourceIndex] = useState(0);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  const handleError = (err) => {
    console.error('Video error:', err);
    // Try next CDN source
    if (currentSourceIndex < hlsSources.length - 1) {
      setCurrentSourceIndex(prev => prev + 1);
      setError(null);
    } else {
      setError('Unable to load stream');
    }
  };

  if (error) {
    return <Text style={{ color: 'red' }}>{error}</Text>;
  }

  return (
    <View style={{ flex: 1 }}>
      {isLoading && <ActivityIndicator />}
      <Video
        ref={videoRef}
        source={{ uri: hlsSources[currentSourceIndex].url }}
        style={{ flex: 1 }}
        resizeMode="contain"
        onError={handleError}
        onLoad={() => setIsLoading(false)}
        onBuffer={({ isBuffering }) => setIsLoading(isBuffering)}
        controls
      />
    </View>
  );
};

export default LiveStreamPlayer;

iOS (AVPlayer)

swift
import AVKit

class StreamPlayerViewController: UIViewController {
    var player: AVPlayer?

    func playStream(hlsUrl: String) {
        guard let url = URL(string: hlsUrl) else { return }

        player = AVPlayer(url: url)
        let playerViewController = AVPlayerViewController()
        playerViewController.player = player

        present(playerViewController, animated: true) {
            self.player?.play()
        }
    }
}

Android (ExoPlayer)

kotlin
val player = ExoPlayer.Builder(context).build()
val mediaItem = MediaItem.fromUri(hlsUrl)
player.setMediaItem(mediaItem)
player.prepare()
player.play()

Released under the MIT License.