Skip to main content

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

PropertyTypeDefaultDescription
minBufferMsnumber5000Minimum duration the player attempts to keep buffered
maxBufferMsnumber10000Maximum duration the player attempts to buffer
bufferForPlaybackMsnumber1000Media that must be buffered before playback starts
bufferForPlaybackAfterRebufferMsnumber2000Media that must be buffered to resume after rebuffering
backBufferDurationMsnumber-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

PropertyTypeDescription
preferredForwardBufferDurationMsnumberPreferred duration to retain ahead of playhead
preferredPeakBitRatenumberDesired network bandwidth limit (bps)
preferredMaximumResolution{width, height}Preferred maximum video resolution
preferredPeakBitRateForExpensiveNetworksnumberBandwidth 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

PropertyPlatformTypeDescription
targetOffsetMsAllnumberTarget live offset the player maintains
minPlaybackSpeedAndroidnumberMinimum playback speed for catching up
maxPlaybackSpeedAndroidnumberMaximum playback speed for catching up
minOffsetMsAndroidnumberMinimum allowed live offset
maxOffsetMsAndroidnumberMaximum 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',
  },
});

Platform-Specific Streaming

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)

  1. Use reasonable buffer sizes to balance startup time and rebuffering
  2. Enable back buffer for smooth seeking
  3. 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

  1. Keep target offset low for minimal latency
  2. Allow playback speed adjustments to catch up
  3. 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

  1. Limit bitrate on cellular to save data
  2. Reduce maximum resolution on expensive networks
  3. 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