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.m3u8Example:
https://stream.lunarstream.kozow.com/live/ee04affe2a669854052102fe762bd715/hls.m3u8Adaptive 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()