@goboss/react-native-video-player-sdk
v1.1.3
Published
GoBOSS React Native video player SDK — HLS/DASH/MP4 streaming, DRM, subtitles, chapters, analytics, Chromecast, Android TV.
Maintainers
Readme
@goboss/react-native-video-player-sdk
A full-featured React Native video player SDK supporting HLS, DASH, and MP4 streaming with DRM, subtitles, chapters, analytics, Chromecast, and overlay ads.
One package, two players. Install a single npm package and get both:
RNVideoPlayer— touch UI for phones/tablets (gestures, fullscreen, Picture-in-Picture)TVVideoPlayer— D-pad UI for Android TV / Fire TV (remote-control navigation, no touch/PiP)
Both share the same underlying VideoPlayerSDK core (playback, DRM, analytics, ad breaks, subtitles), so behavior and events stay consistent across form factors. There is no separate TV package to install — pick the component at runtime with Platform.isTV.
Installation
npm install @goboss/react-native-video-player-sdk
cd ios && pod installThat's it for everything except Chromecast — no other npm install commands needed.
What's included automatically
| Dependency | Why | Install step |
|---|---|---|
| react-native-video | Core <Video> playback | Auto — regular dependency |
| react-native-safe-area-context | Layout insets | Auto — regular dependency |
| lucide-react-native | Control-bar icons | Auto — regular dependency |
| @react-native-async-storage/async-storage | Resume position, watched-ad memory | Auto — regular dependency |
| @react-native-community/netinfo | Network type in analytics | Auto — regular dependency |
| react-native-create-thumbnail | Local seek-preview thumbnails | Auto — regular dependency |
All six ship as real dependencies of the SDK, so npm install @goboss/react-native-video-player-sdk pulls them in with no extra commands. Playback, DRM, subtitles, chapters, key moments, ad breaks, resume-position, thumbnail previews, and analytics all work immediately — for both RNVideoPlayer (mobile) and TVVideoPlayer (Android TV).
What's opt-in: Chromecast
| | |
|---|---|
| Package | react-native-google-cast |
| Auto-installed? | No |
| Why not? | Needs a Cast receiver App ID that belongs to your app — there's no value the SDK could ship that works for every consumer. It also crashes at native launch on Android if its native config is missing, so silently bundling it would risk breaking apps that never asked for Chromecast. |
| What happens if you skip it | Player works normally — the Cast button just doesn't render. |
| How you'll know it's missing | A console.warn fires the moment you import RNVideoPlayer: "[RNVideoPlayer] react-native-google-cast not installed — Chromecast button hidden." |
To enable it:
npm install react-native-google-castThen add a CastOptionsProvider native class and the OPTIONS_PROVIDER_CLASS_NAME meta-data entry to your AndroidManifest.xml — see android/app/src/main/AndroidManifest.xml in this repo for a working reference.
Android TV launcher (optional)
To make the app appear on the Android TV home screen, add to your AndroidManifest.xml:
<uses-feature android:name="android.software.leanback" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />and add <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> to your launcher activity's intent filter. TVVideoPlayer itself works without this — it's only required for TV-store/launcher visibility.
Quick Start
Render RNVideoPlayer on phones/tablets and TVVideoPlayer on Android TV / Fire TV, switching on Platform.isTV:
import React from 'react';
import { View, Platform } from 'react-native';
import { RNVideoPlayer, TVVideoPlayer } from '@goboss/react-native-video-player-sdk';
export default function App() {
if (Platform.isTV) {
return (
<View style={{ flex: 1, backgroundColor: '#000' }}>
<TVVideoPlayer
src="https://example.com/stream.m3u8"
themeColor="#6366f1"
/>
</View>
);
}
return (
<View style={{ flex: 1, backgroundColor: '#000' }}>
<RNVideoPlayer
src="https://example.com/stream.m3u8"
themeColor="#6366f1"
/>
</View>
);
}If your app only targets one form factor, just render that one component directly — no need for the Platform.isTV check.
Props
RNVideoPlayer (mobile/tablet)
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| src | string | Yes | — | Stream URL — HLS (.m3u8), DASH (.mpd), or MP4 |
| themeColor | string | No | #6366f1 | Accent color for controls and progress bar |
| title | string | No | — | Video title shown in the player |
| headers | Record<string, string> | No | — | Custom HTTP headers for stream/segment requests |
| chapters | Chapter[] | No | [] | Chapter markers shown on the seekbar |
| keyMoments | KeyMoment[] | No | — | Key moment markers (fetched from server and updated via onKeyMomentsLoaded) |
| subtitles | SubtitleTrack[] | No | [] | Subtitle/caption tracks |
| subtitleStyle | SubtitleStyle | No | {} | Subtitle appearance — size, background, color |
| thumbnails | ThumbnailConfig | No | — | Sprite sheet config for thumbnail previews on seek |
| drmConfig | object | No | — | Widevine / FairPlay / PlayReady DRM configuration |
| watermark | string | No | — | Watermark text overlaid on the video |
| playerKey | string | No | — | SDK license / package key |
| adTrackingUrl | string | No | — | MediaTailor tracking URL for overlay ad support |
| watchProgressInterval | number | No | 30 | Interval in seconds for watch-progress analytics events |
| enableSecureMode | boolean | No | false | Enables FLAG_SECURE on Android to block screenshots (no-op on iOS) |
| onKeyMomentsLoaded | (keyMoments: KeyMoment[]) => void | No | — | Called when key moments are loaded from the server |
TVVideoPlayer (Android TV / Fire TV)
Same as RNVideoPlayer above, with two differences:
- No
thumbnailsprop — seek-preview thumbnails are a touch/scrub interaction and don't apply to D-pad seeking. - No fullscreen or Picture-in-Picture callbacks — TV playback is always fullscreen; there's no PiP on Android TV.
Navigation is handled entirely via the D-pad (remote) — play/pause, seek, and menu selection all respond to directional + select key events instead of touch gestures.
Delegate Callbacks
Beyond onKeyMomentsLoaded, both RNVideoPlayer and TVVideoPlayer accept per-event delegate callbacks. Each carries only the arguments relevant to that event, rather than the entire player state. TVVideoPlayer accepts every callback below except the fullscreen and Picture-in-Picture ones, which don't apply on TV.
| Callback | Arguments | Fires when |
|----------|-----------|------------|
| playerDidStartPlaying | { startTime, autoplay } | Playback starts for the first time |
| playerDidResumePlaying | { resumedAt } | Playback resumes after a pause |
| playerDidPause | { pausedAt } | Playback is paused |
| playerDidFinishPlaying | { finishedAt, watchDuration } | Playback reaches the end |
| playerDidDismiss | { dismissedAt, watchDuration } | The player is unmounted/closed |
| playerDidStartSeeking | { fromTime } | A seek begins |
| playerDidFinishSeeking | { fromTime, toTime } | A seek completes |
| playerDidUpdateCurrentTime | { currentTime, duration } | The playhead position updates |
| playerDidStartBuffering | { startedAt } | Buffering starts |
| playerDidFinishBuffering | { endedAt } | Buffering ends |
| playerDidChangeQuality | { fromQuality, toQuality, isAutoSwitch } | The rendition changes (manual or ABR) |
| playerDidChangeSubtitle | { fromSubtitle, toSubtitle } | The subtitle track changes |
| playerDidDisableSubtitle | { disabledSubtitle } | Subtitles are turned off |
| playerDidChangeAudioTrack | { fromAudioTrack, toAudioTrack } | The audio track changes |
| playerDidChangePlaybackSpeed | { fromSpeed, toSpeed } | The playback rate changes |
| playerDidSelectKeyMoment | { chapterId, chapterTitle, fromTime, toTime } | A chapter/key moment is selected |
| playerDidEncounterPlaybackError | { errorCode, message, isRecoverable } | A non-network playback error occurs |
| playerDidEncounterNetworkError | { statusCode, message, isRecoverable } | A network-related error occurs |
| playerDidEnterFullscreen (mobile/tablet only) | { orientation? } | The player enters fullscreen |
| playerDidExitFullscreen (mobile/tablet only) | { orientation? } | The player exits fullscreen |
| playerDidEnterPictureInPicture (mobile/tablet only) | { enteredAt? } | The player enters Picture-in-Picture |
| playerDidExitPictureInPicture (mobile/tablet only) | { exitedAt? } | The player exits Picture-in-Picture |
<RNVideoPlayer
src="https://example.com/stream.m3u8"
playerDidStartPlaying={({ startTime, autoplay }) => console.log('started', startTime, autoplay)}
playerDidPause={({ pausedAt }) => console.log('paused at', pausedAt)}
playerDidChangeQuality={({ fromQuality, toQuality, isAutoSwitch }) =>
console.log(`quality ${fromQuality} -> ${toQuality}`, isAutoSwitch ? '(auto)' : '(manual)')
}
playerDidEncounterPlaybackError={({ errorCode, message }) => console.warn(errorCode, message)}
/>Examples
With Subtitles (External VTT)
Pass external .vtt or .srt files via the subtitles prop. The SDK fetches and parses them in JS and renders cues through the built-in overlay — no native configuration needed.
import { RNVideoPlayer } from '@goboss/react-native-video-player-sdk';
import type { SubtitleTrack } from '@goboss/react-native-video-player-sdk';
const subtitles: SubtitleTrack[] = [
{
id: 'en',
label: 'English',
lang: 'en',
src: 'https://cdn.example.com/subtitles/en.vtt',
isDefault: true, // auto-selected on load
},
{
id: 'ta',
label: 'Tamil',
lang: 'ta',
src: 'https://cdn.example.com/subtitles/ta.vtt',
},
];
<RNVideoPlayer
src="https://example.com/stream.m3u8"
subtitles={subtitles}
subtitleStyle={{ size: 'medium', background: 'dim', color: '#ffffff' }}
/>SubtitleTrack fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Unique identifier — used to switch the active track |
| label | string | Yes | Display name shown in the subtitle menu |
| lang | string | Yes | BCP-47 language code (e.g. 'en', 'ta', 'fr') |
| src | string | Yes (for external VTT) | URL of the .vtt or .srt file — fetched and parsed by the SDK |
| absoluteSrc | string | No | Direct CDN URL for Chromecast (without proxy/token rewrites) — required only if you use Chromecast |
| isDefault | boolean | No | Auto-selects this track when the player loads |
| cues | Array<{startTime, endTime, text}> | No | Pre-parsed cues — skip the fetch step if you already have them |
Subtitle sources — how they work
| Source | How to use | Rendered by |
|--------|-----------|-------------|
| External VTT/SRT | Pass src URL in the subtitles prop | JS overlay (SDK) |
| HLS embedded (#EXT-X-MEDIA:TYPE=SUBTITLES) | Nothing — SDK auto-discovers from manifest | JS overlay (SDK) |
| CEA-608/708 closed captions | Nothing — SDK auto-discovers via onTextTracks | Native (ExoPlayer/AVPlayer) |
subtitleStyle options
| Field | Values | Default | Description |
|-------|--------|---------|-------------|
| size | 'small' | 'medium' | 'large' | 'medium' | Subtitle text size |
| background | 'none' | 'dim' | 'solid' | 'dim' | Background behind subtitle text |
| color | CSS color string | '#ffffff' | Subtitle text color |
With Chapters
import type { Chapter } from '@goboss/react-native-video-player-sdk';
const chapters: Chapter[] = [
{ title: 'Intro', startTime: 0, endTime: 30 },
{ title: 'Act 1', startTime: 30, endTime: 300 },
];
<RNVideoPlayer
src="https://example.com/stream.m3u8"
chapters={chapters}
themeColor="#e11d48"
/>With DRM (Widevine / FairPlay)
<RNVideoPlayer
src="https://example.com/protected-stream.m3u8"
drmConfig={{
widevineLicenseUrl: 'https://license.example.com/widevine',
fairplayLicenseUrl: 'https://license.example.com/fairplay',
authToken: 'Bearer your-token',
}}
/>With Thumbnail Previews
<RNVideoPlayer
src="https://example.com/stream.m3u8"
thumbnails={{
spriteUrl: 'https://example.com/thumbnails/sprite.jpg',
tileWidth: 160,
tileHeight: 90,
columns: 10,
rows: 10,
interval: 10,
totalCount: 100,
}}
/>With Custom Headers
<RNVideoPlayer
src="https://example.com/stream.m3u8"
headers={{
Authorization: 'Bearer your-token',
Referer: 'https://yourapp.com',
}}
/>Supported Formats
| Format | Extension | Notes |
|--------|-----------|-------|
| HLS | .m3u8 | Adaptive bitrate, live streams, DVR |
| MPEG-DASH | .mpd | Adaptive bitrate |
| MP4 | .mp4 | Progressive download |
Features
- Adaptive streaming — HLS & DASH with automatic quality switching
- DRM — Widevine (Android), FairPlay (iOS), PlayReady
- Subtitles — VTT, SRT, HLS embedded tracks, CEA-608/708 closed captions
- Chapters — seekbar markers with titles
- Thumbnails — sprite-sheet preview on seek
- Chromecast — cast to Google Cast devices (requires
react-native-google-cast) - Picture-in-Picture — native PiP on Android & iOS
- Overlay Ads — AWS MediaTailor non-linear overlay ads
- Analytics — built-in event tracking delivered via your own
analyticsCallback/ API endpoint - Secure Mode —
FLAG_SECUREon Android to prevent screen capture - Live streams — DVR scrubbing, live-edge seek
Requirements
- React Native >= 0.74
- iOS 13+
- Android API 21+
- Android TV / Fire TV — same Android API 21+ baseline, via
TVVideoPlayer
