HLS and DASH Streaming
React Native Video supports adaptive bitrate streaming protocols including HLS (HTTP Live Streaming) and DASH (Dynamic Adaptive Streaming over HTTP), enabling high-quality video delivery that adapts to network conditions.
Streaming Protocols
HLS (HTTP Live Streaming)
- Platform: iOS, Android, visionOS
- Format:
.m3u8 playlist files
- Best for: iOS/Apple platforms (native support)
- Features: Adaptive bitrate, live streaming, subtitles
DASH (Dynamic Adaptive Streaming over HTTP)
- Platform: Android (ExoPlayer)
- Format:
.mpd manifest files
- Best for: Android devices
- Features: Adaptive bitrate, live streaming, DRM support
Basic Streaming
HLS Streaming
import { VideoView, useVideoPlayer } from 'react-native-video';
export function HLSPlayer() {
const player = useVideoPlayer('https://example.com/stream.m3u8');
return <VideoView player={player} style={{ width: '100%', height: 300 }} />;
}
DASH Streaming
import { VideoView, useVideoPlayer } from 'react-native-video';
export function DASHPlayer() {
const player = useVideoPlayer('https://example.com/manifest.mpd');
return <VideoView player={player} style={{ width: '100%', height: 300 }} />;
}
Buffer Configuration
Optimize streaming performance by configuring buffer settings. Buffer configuration varies by platform.
Android Buffer Settings
const player = useVideoPlayer({
uri: 'https://example.com/stream.m3u8',
bufferConfig: {
// Minimum buffer duration (ms)
minBufferMs: 5000,
// Maximum buffer duration (ms)
maxBufferMs: 10000,
// Buffer required before playback starts (ms)
bufferForPlaybackMs: 1000,
// Buffer required after rebuffering (ms)
bufferForPlaybackAfterRebufferMs: 2000,
// Back buffer duration for instant rewind (ms)
backBufferDurationMs: 30000,
},
});
Android Buffer Properties
| Property | Type | Default | Description |
|---|
minBufferMs | number | 5000 | Minimum duration the player attempts to keep buffered |
maxBufferMs | number | 10000 | Maximum duration the player attempts to buffer |
bufferForPlaybackMs | number | 1000 | Media that must be buffered before playback starts |
bufferForPlaybackAfterRebufferMs | number | 2000 | Media that must be buffered to resume after rebuffering |
backBufferDurationMs | number | - | Duration kept behind current position for instant rewind |
iOS Buffer Settings
const player = useVideoPlayer({
uri: 'https://example.com/stream.m3u8',
bufferConfig: {
// Preferred forward buffer duration (ms)
preferredForwardBufferDurationMs: 3000,
// Network bandwidth limit (bits per second)
preferredPeakBitRate: 2000000, // 2 Mbps
// Maximum video resolution
preferredMaximumResolution: {
width: 1920,
height: 1080,
},
// Bandwidth limit on cellular networks
preferredPeakBitRateForExpensiveNetworks: 1000000, // 1 Mbps
// Maximum resolution on cellular networks
preferredMaximumResolutionForExpensiveNetworks: {
width: 1280,
height: 720,
},
},
});
iOS Buffer Properties
| Property | Type | Description |
|---|
preferredForwardBufferDurationMs | number | Preferred duration to retain ahead of playhead |
preferredPeakBitRate | number | Desired network bandwidth limit (bps) |
preferredMaximumResolution | {width, height} | Preferred maximum video resolution |
preferredPeakBitRateForExpensiveNetworks | number | Bandwidth limit on cellular (bps) |
preferredMaximumResolutionForExpensiveNetworks | {width, height} | Maximum resolution on cellular |
Live Streaming
For live streams, configure the live playback parameters to control latency and catch-up behavior.
Live Configuration
const player = useVideoPlayer({
uri: 'https://example.com/live.m3u8',
bufferConfig: {
livePlayback: {
// Target live offset (ms) - cross-platform
targetOffsetMs: 500,
// Android-only settings
minPlaybackSpeed: 0.95,
maxPlaybackSpeed: 1.05,
minOffsetMs: 300,
maxOffsetMs: 2000,
},
},
});
Live Playback Properties
| Property | Platform | Type | Description |
|---|
targetOffsetMs | All | number | Target live offset the player maintains |
minPlaybackSpeed | Android | number | Minimum playback speed for catching up |
maxPlaybackSpeed | Android | number | Maximum playback speed for catching up |
minOffsetMs | Android | number | Minimum allowed live offset |
maxOffsetMs | Android | number | Maximum allowed live offset |
Complete Live Streaming Example
import { VideoView, useVideoPlayer } from 'react-native-video';
import { View, Text, StyleSheet } from 'react-native';
export function LivePlayer() {
const player = useVideoPlayer(
{
uri: 'https://example.com/live.m3u8',
bufferConfig: {
livePlayback: {
targetOffsetMs: 500,
minPlaybackSpeed: 0.95,
maxPlaybackSpeed: 1.05,
},
preferredForwardBufferDurationMs: 2000,
},
},
(player) => {
// Auto-play live streams
player.play();
}
);
return (
<View style={styles.container}>
<View style={styles.liveIndicator}>
<Text style={styles.liveText}>🔴 LIVE</Text>
</View>
<VideoView player={player} style={styles.video} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
video: {
width: '100%',
height: 300,
},
liveIndicator: {
position: 'absolute',
top: 20,
right: 20,
backgroundColor: 'rgba(0, 0, 0, 0.7)',
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 4,
zIndex: 10,
},
liveText: {
color: '#fff',
fontWeight: 'bold',
},
});
Monitoring Bandwidth
Track bandwidth changes to display quality information:
import { VideoView, useVideoPlayer } from 'react-native-video';
import { useState } from 'react';
import { View, Text } from 'react-native';
export function BandwidthMonitor() {
const [bandwidth, setBandwidth] = useState<{
bitrate: number;
width?: number;
height?: number;
} | null>(null);
const player = useVideoPlayer('https://example.com/stream.m3u8', (player) => {
player.addEventListener('onBandwidthUpdate', (data) => {
setBandwidth({
bitrate: data.bitrate,
width: data.width,
height: data.height,
});
});
});
return (
<View>
<VideoView player={player} style={{ width: '100%', height: 300 }} />
{bandwidth && (
<Text>
Quality: {bandwidth.width}x{bandwidth.height} @{' '}
{(bandwidth.bitrate / 1000000).toFixed(2)} Mbps
</Text>
)}
</View>
);
}
Handling Buffering
Monitor and display buffering state:
import { VideoView, useVideoPlayer } from 'react-native-video';
import { useState } from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
export function PlayerWithBuffering() {
const [isBuffering, setIsBuffering] = useState(false);
const player = useVideoPlayer('https://example.com/stream.m3u8', (player) => {
player.addEventListener('onBuffer', (buffering) => {
setIsBuffering(buffering);
});
});
return (
<View style={styles.container}>
<VideoView player={player} style={styles.video} />
{isBuffering && (
<View style={styles.bufferingOverlay}>
<ActivityIndicator size="large" color="#fff" />
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
position: 'relative',
},
video: {
width: '100%',
height: 300,
},
bufferingOverlay: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
});
Use platform-specific formats for optimal performance:
import { Platform } from 'react-native';
import { VideoView, useVideoPlayer } from 'react-native-video';
export function AdaptivePlayer() {
const player = useVideoPlayer(
Platform.select({
ios: 'https://example.com/stream.m3u8', // HLS for iOS
android: 'https://example.com/manifest.mpd', // DASH for Android
default: 'https://example.com/stream.m3u8',
})
);
return <VideoView player={player} style={{ width: '100%', height: 300 }} />;
}
Network Quality Adaptation
Adjust quality based on network type:
import { VideoView, useVideoPlayer } from 'react-native-video';
import NetInfo from '@react-native-community/netinfo';
import { useEffect, useState } from 'react';
export function NetworkAwarePlayer() {
const [isCellular, setIsCellular] = useState(false);
useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => {
setIsCellular(state.type === 'cellular');
});
return unsubscribe;
}, []);
const player = useVideoPlayer({
uri: 'https://example.com/stream.m3u8',
bufferConfig: {
preferredPeakBitRate: isCellular ? 1000000 : 5000000,
preferredMaximumResolution: isCellular
? { width: 1280, height: 720 }
: { width: 1920, height: 1080 },
},
});
return <VideoView player={player} style={{ width: '100%', height: 300 }} />;
}
Install @react-native-community/netinfo to use network detection: npm install @react-native-community/netinfo
Progress Tracking
Monitor playback progress and buffer state:
const player = useVideoPlayer('https://example.com/stream.m3u8', (player) => {
player.addEventListener('onProgress', (data) => {
console.log('Current time:', data.currentTime);
console.log('Buffer duration:', data.bufferDuration);
console.log('Buffered until:', data.currentTime + data.bufferDuration);
});
});
Best Practices
For VOD (Video on Demand)
- Use reasonable buffer sizes to balance startup time and rebuffering
- Enable back buffer for smooth seeking
- Consider network conditions when setting bitrate limits
const player = useVideoPlayer({
uri: 'https://example.com/vod.m3u8',
bufferConfig: {
minBufferMs: 5000,
maxBufferMs: 15000,
backBufferDurationMs: 30000,
},
});
For Live Streaming
- Keep target offset low for minimal latency
- Allow playback speed adjustments to catch up
- Use smaller forward buffers
const player = useVideoPlayer({
uri: 'https://example.com/live.m3u8',
bufferConfig: {
livePlayback: {
targetOffsetMs: 500,
minPlaybackSpeed: 0.95,
maxPlaybackSpeed: 1.05,
},
preferredForwardBufferDurationMs: 2000,
},
});
For Mobile Networks
- Limit bitrate on cellular to save data
- Reduce maximum resolution on expensive networks
- Monitor network type changes
const player = useVideoPlayer({
uri: 'https://example.com/stream.m3u8',
bufferConfig: {
preferredPeakBitRateForExpensiveNetworks: 1000000,
preferredMaximumResolutionForExpensiveNetworks: {
width: 1280,
height: 720,
},
},
});
Troubleshooting
Playback Stuttering
- Increase
minBufferMs (Android) or preferredForwardBufferDurationMs (iOS)
- Check network conditions and reduce
preferredPeakBitRate
- Monitor
onBuffer events to identify buffering frequency
Slow Startup
- Decrease
bufferForPlaybackMs (Android)
- Reduce
preferredForwardBufferDurationMs (iOS)
- Use
preload() to start buffering before playback
High Data Usage
- Set
preferredPeakBitRate to limit bandwidth
- Use
preferredMaximumResolution to cap video quality
- Configure separate limits for cellular networks
Live Stream Lag
- Decrease
targetOffsetMs in live playback config
- Increase
maxPlaybackSpeed to allow faster catch-up
- Reduce forward buffer duration
Next Steps
- Learn about DRM for protected streaming content
- Explore Subtitles for multi-language support
- Implement Event Handling to monitor streaming quality