A comprehensive React Native video player component with streaming, DRM, and Picture-in-Picture support
—
Platform-specific functionality including Android decoder utilities, iOS-specific features, Windows support, and Web platform capabilities with comprehensive codec support detection and platform optimization features.
Utility object providing codec support detection and decoder information specifically for Android platform.
/**
* Android-specific decoder utilities for codec support detection
* Platform: Android only - throws error on other platforms
*/
declare const VideoDecoderProperties: {
getWidevineLevel(): Promise<number>;
isCodecSupported(mimeType: string, width?: number, height?: number): Promise<'unsupported' | 'hardware' | 'software'>;
isHEVCSupported(): Promise<'unsupported' | 'hardware' | 'software'>;
};Usage Examples:
import { VideoDecoderProperties } from "react-native-video";
import { Platform } from "react-native";
// Check platform before using Android-specific features
if (Platform.OS === 'android') {
try {
// Check Widevine security level
const widevineLevel = await VideoDecoderProperties.getWidevineLevel();
console.log("Widevine security level:", widevineLevel);
// Check HEVC support
const hevcSupported = await VideoDecoderProperties.isHEVCSupported();
console.log("HEVC support:", hevcSupported); // 'unsupported' | 'hardware' | 'software'
// Check specific codec support
const h264Support = await VideoDecoderProperties.isCodecSupported('video/avc');
const vp9Support = await VideoDecoderProperties.isCodecSupported('video/x-vnd.on2.vp9');
console.log("Codec support:", { h264: h264Support, vp9: vp9Support });
} catch (error) {
console.error("Error checking decoder properties:", error);
}
}Get the Widevine DRM security level on Android devices.
/**
* Get Widevine DRM security level
* @returns Promise resolving to security level (1 = L1, 3 = L3)
* @throws Error on non-Android platforms
* Platform: Android only
*/
getWidevineLevel(): Promise<number>;Usage Examples:
// Determine DRM capability based on Widevine level
const checkDRMCapability = async () => {
if (Platform.OS === 'android') {
try {
const level = await VideoDecoderProperties.getWidevineLevel();
switch (level) {
case 1:
console.log("Widevine L1: Hardware-backed security, supports HD content");
return "premium";
case 3:
console.log("Widevine L3: Software-based security, SD content only");
return "standard";
default:
console.log("Unknown Widevine level:", level);
return "unknown";
}
} catch (error) {
console.error("Failed to get Widevine level:", error);
return "unavailable";
}
}
return "not-android";
};Check support for specific video codecs with optional resolution constraints.
/**
* Check if a specific codec is supported
* @param mimeType - MIME type of the codec (e.g., 'video/avc', 'video/hevc')
* @param width - Optional video width constraint
* @param height - Optional video height constraint
* @returns Promise resolving to support level: 'unsupported', 'hardware', or 'software'
* @throws Error on non-Android platforms
* Platform: Android only
*/
isCodecSupported(mimeType: string, width?: number, height?: number): Promise<'unsupported' | 'hardware' | 'software'>;Usage Examples:
// Check codec support for different resolutions
const checkCodecSupport = async () => {
if (Platform.OS === 'android') {
try {
const codecs = [
{ name: 'H.264', mime: 'video/avc' },
{ name: 'H.265/HEVC', mime: 'video/hevc' },
{ name: 'VP8', mime: 'video/x-vnd.on2.vp8' },
{ name: 'VP9', mime: 'video/x-vnd.on2.vp9' },
{ name: 'AV1', mime: 'video/av01' }
];
const support = {};
for (const codec of codecs) {
// Check general support
const generalSupport = await VideoDecoderProperties.isCodecSupported(codec.mime);
// Check 4K support
const uhd4KSupport = await VideoDecoderProperties.isCodecSupported(
codec.mime, 3840, 2160
);
// Check 8K support
const uhd8KSupport = await VideoDecoderProperties.isCodecSupported(
codec.mime, 7680, 4320
);
support[codec.name] = {
general: generalSupport, // 'unsupported' | 'hardware' | 'software'
uhd4K: uhd4KSupport, // 'unsupported' | 'hardware' | 'software'
uhd8K: uhd8KSupport // 'unsupported' | 'hardware' | 'software'
};
}
console.log("Codec support matrix:", support);
return support;
} catch (error) {
console.error("Error checking codec support:", error);
return {};
}
}
};Convenient method to specifically check HEVC/H.265 codec support.
/**
* Check if HEVC/H.265 codec is supported
* @returns Promise resolving to support level: 'unsupported', 'hardware', or 'software'
* @throws Error on non-Android platforms
* Platform: Android only
*/
isHEVCSupported(): Promise<'unsupported' | 'hardware' | 'software'>;Usage Examples:
// Adaptive streaming based on HEVC support
const selectVideoSource = async () => {
if (Platform.OS === 'android') {
try {
const hevcSupported = await VideoDecoderProperties.isHEVCSupported();
if (hevcSupported === 'hardware' || hevcSupported === 'software') {
return {
uri: "https://example.com/video-hevc.mp4", // Higher quality HEVC stream
type: "video/mp4"
};
} else {
return {
uri: "https://example.com/video-h264.mp4", // Fallback H.264 stream
type: "video/mp4"
};
}
} catch (error) {
console.error("Error checking HEVC support:", error);
// Fallback to H.264
return {
uri: "https://example.com/video-h264.mp4",
type: "video/mp4"
};
}
}
// Default for other platforms
return {
uri: "https://example.com/video.mp4",
type: "video/mp4"
};
};Android platform provides additional configuration options and features.
/**
* Android-specific Video component props
*/
interface AndroidVideoProps {
// View configuration
viewType?: 0 | 1 | 2; // TEXTURE | SURFACE | SURFACE_SECURE
useTextureView?: boolean; // Deprecated: use viewType
useSecureView?: boolean; // Deprecated: use viewType
// UI and interaction
focusable?: boolean;
disableFocus?: boolean;
hideShutterView?: boolean;
shutterColor?: string;
// Playback control
currentPlaybackTime?: number;
reportBandwidth?: boolean;
disableDisconnectError?: boolean;
// Controls customization
controlsStyles?: ControlsStyles;
// Subtitle styling
subtitleStyle?: SubtitleStyle;
// Buffer configuration
bufferConfig?: BufferConfig;
minLoadRetryCount?: number;
}
/**
* View types for Android video rendering
*/
enum ViewType {
TEXTURE = 0, // TextureView - supports animation and transformation
SURFACE = 1, // SurfaceView - better performance, limited functionality
SURFACE_SECURE = 2 // Secure SurfaceView - required for DRM content
}Usage Examples:
// Android-specific configuration
<Video
source={{ uri: "https://example.com/video.mp4" }}
viewType={1} // Use SurfaceView for better performance
reportBandwidth={true}
shutterColor="#000000"
controlsStyles={{
hideSeekBar: false,
seekIncrementMS: 15000,
liveLabel: "LIVE"
}}
subtitleStyle={{
fontSize: 16,
paddingTop: 2,
paddingBottom: 2,
opacity: 0.8
}}
/>
// DRM content with secure view
<Video
source={{
uri: "https://example.com/drm-content.mpd",
drm: {
type: "widevine",
licenseServer: "https://license-server.com"
}
}}
viewType={2} // SURFACE_SECURE required for DRM
useSecureView={true}
/>iOS platform provides additional features for media control and presentation.
/**
* iOS-specific Video component props
*/
interface iOSVideoProps {
// Fullscreen configuration
fullscreen?: boolean;
fullscreenAutorotate?: boolean;
fullscreenOrientation?: "all" | "landscape" | "portrait";
// Audio configuration
ignoreSilentSwitch?: "inherit" | "ignore" | "obey";
mixWithOthers?: "inherit" | "mix" | "duck";
playWhenInactive?: boolean;
automaticallyWaitsToMinimizeStalling?: boolean;
disableAudioSessionManagement?: boolean;
// External playback
allowsExternalPlayback?: boolean;
// Video processing
filter?: string;
filterEnabled?: boolean;
preferredForwardBufferDuration?: number;
// Chapter support
chapters?: Chapters[];
}
/**
* Chapter information for iOS
*/
interface Chapters {
title: string;
startTime: number;
endTime: number;
uri?: string;
}Usage Examples:
// iOS-specific configuration
<Video
source={{ uri: "https://example.com/video.mp4" }}
fullscreenOrientation="landscape"
ignoreSilentSwitch="ignore" // Continue playing even when silent switch is on
mixWithOthers="duck" // Duck other audio when playing
allowsExternalPlayback={true} // Enable AirPlay
chapters={[
{ title: "Introduction", startTime: 0, endTime: 30 },
{ title: "Main Content", startTime: 30, endTime: 300 },
{ title: "Conclusion", startTime: 300, endTime: 330 }
]}
filter="CIColorMonochrome"
filterEnabled={true}
/>Windows platform support through MediaPlayerElement.
/**
* Windows-specific features (limited compared to mobile platforms)
*/
interface WindowsVideoProps {
// Basic playback control supported
// Limited event support compared to mobile platforms
}Web platform implementation using HTML5 video element with React Native Web.
/**
* Web-specific Video component props and features
*/
interface WebVideoProps {
// Loader customization
renderLoader?: ReactNode | ((props: ReactVideoRenderLoaderProps) => ReactNode);
// Direct HTML video element access
nativeHtmlVideoRef?: RefObject<HTMLVideoElement | null>; // Via VideoRef
}
/**
* Render loader props for web platform
*/
interface ReactVideoRenderLoaderProps {
source?: ReactVideoSource;
style?: StyleProp<ImageStyle>;
resizeMode?: "none" | "contain" | "cover" | "stretch";
}Usage Examples:
// Web-specific loader
<Video
source={{ uri: "https://example.com/video.mp4" }}
renderLoader={({ style }) => (
<View style={style}>
<Text>Loading video...</Text>
</View>
)}
/>
// Access HTML video element
const videoRef = useRef<VideoRef>(null);
useEffect(() => {
if (Platform.OS === 'web' && videoRef.current?.nativeHtmlVideoRef?.current) {
const htmlVideo = videoRef.current.nativeHtmlVideoRef.current;
// Add custom HTML video event listeners
htmlVideo.addEventListener('canplaythrough', () => {
console.log("HTML video can play through");
});
// Access HTML video properties
console.log("Video element ready state:", htmlVideo.readyState);
}
}, []);import { Platform } from "react-native";
import { VideoDecoderProperties } from "react-native-video";
const detectPlatformCapabilities = async () => {
const capabilities = {
platform: Platform.OS,
drm: {},
codecs: {},
features: {}
};
// Platform-specific capability detection
switch (Platform.OS) {
case 'android':
try {
capabilities.drm.widevineLevel = await VideoDecoderProperties.getWidevineLevel();
capabilities.codecs.hevc = await VideoDecoderProperties.isHEVCSupported();
capabilities.codecs.h264 = await VideoDecoderProperties.isCodecSupported('video/avc');
capabilities.codecs.vp9 = await VideoDecoderProperties.isCodecSupported('video/x-vnd.on2.vp9');
capabilities.features = {
pictureInPicture: true,
backgroundAudio: true,
externalPlayback: false,
customControls: true,
subtitleStyling: true
};
} catch (error) {
console.error("Android capability detection failed:", error);
}
break;
case 'ios':
capabilities.drm = { fairplay: true };
capabilities.features = {
pictureInPicture: true,
backgroundAudio: true,
externalPlayback: true, // AirPlay
customControls: false,
chapters: true,
filters: true
};
break;
case 'web':
capabilities.features = {
pictureInPicture: false,
backgroundAudio: false,
externalPlayback: false,
customLoader: true,
htmlVideoAccess: true
};
break;
case 'windows':
capabilities.features = {
basicPlayback: true,
limitedEvents: true
};
break;
}
return capabilities;
};const selectOptimalVideoSource = async (baseUrl: string) => {
const capabilities = await detectPlatformCapabilities();
// Select best video source based on platform capabilities
if (Platform.OS === 'android' && capabilities.codecs.hevc) {
return {
uri: `${baseUrl}/video-hevc.mp4`,
type: "video/mp4"
};
}
if (Platform.OS === 'ios') {
return {
uri: `${baseUrl}/video-hls.m3u8`,
type: "application/x-mpegURL"
};
}
// Fallback for other platforms
return {
uri: `${baseUrl}/video-h264.mp4`,
type: "video/mp4"
};
};Install with Tessl CLI
npx tessl i tessl/npm-react-native-video