HLS Playback Guide
Learn how to integrate HLS video playback into your web and mobile applications.
HLS Playback Flow
HLS URL Format
https://{cdn-host}/live/{streamKey}/hls.m3u8Example:
https://stream.lunarstream.kozow.com/live/ee04affe2a669854052102fe762bd715/hls.m3u8Available CDN Endpoints
Each stream is available through multiple CDN endpoints for redundancy:
| CDN | URL Pattern | Coverage |
|---|---|---|
| Primary | https://stream.lunarstream.kozow.com/live/{streamKey}/hls.m3u8 | Global |
| BunnyCDN | https://zlmediakit-cdn.b-cdn.net/live/{streamKey}/hls.m3u8 | Global |
| Gcore | https://gcore-zlmediakit.lunarstream.kozow.com/live/{streamKey}/hls.m3u8 | Global |
Best Practice
Implement CDN failover in your player to automatically switch between endpoints if one becomes unavailable.
Adaptive Bitrate Streaming
Lunar Stream automatically provides multiple quality levels for adaptive bitrate streaming:
| Quality | Resolution | Bitrate |
|---|---|---|
| High | 1080p | ~6 Mbps |
| Medium | 720p | ~3 Mbps |
| Low | 480p | ~1.5 Mbps |
| Mobile | 360p | ~800 Kbps |
The player automatically selects the best quality based on viewer's network conditions.
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()Troubleshooting
| Issue | Possible Cause | Solution |
|---|---|---|
| Stream not loading | Stream not started | Check stream status via API |
| Playback buffering | Network issues | Try lower quality or different CDN |
| No video/audio | Codec incompatibility | Ensure player supports HLS |
| CORS errors | Cross-origin blocked | Use CDN URLs provided by API |
Next Steps
- Multi-CDN Setup - Advanced CDN failover configuration
- RTMP Streaming - Configure broadcaster
- API Reference - Get stream details programmatically