# react-native-omni A library to have real players on android and web. It uses VLC on android and videojs v10 on the web (ios not implemented yet, PR welcome) ## Features - **vlc v4**: to support more codecs than exoplayer, hdr and so on - **Adaptive streaming**: HLS out of the box, with automatic quality (rendition) selection or manual override. - **Multi-track playback**: enumerate and switch video, audio, and subtitle tracks at runtime. - **Rich subtitle support**: vtt, srt, ass (via [jassub](https://github.com/ThaUnknown/jassub)) and pgs (via [libpgs](https://github.com/Arcus92/libpgs-js)) - **Picture-in-Picture**: enter PiP automatically or on demand on Android. - **Chromecast**: cast to a receiver on both web and Android . - **and basic player stuff**: media sessions, playlists, hook based api... ## Installation ```bash bun add react-native-omni react-native-nitro-modules ``` ### Expo config plugin (Android) The library ships an Expo config plugin that wires up media notifications and picture-in-picture. Add it to your `app.json` / `app.config.js`: ```json { "expo": { "plugins": ["react-native-omni"] } } ``` The plugin will: - Register the `OmniPlayerService` media session service and add the `FOREGROUND_SERVICE` / `FOREGROUND_SERVICE_MEDIA_PLAYBACK` permissions. - Enable Picture-in-Picture on your `MainActivity` (declares `supportsPictureInPicture`, adds the required `configChanges`, and hooks the pip lifecycle callbacks). - Register omni's Chromecast `OptionsProvider` If you are not using Expo, replicate those manifest/activity changes manually. ### Web setup Most features are available out of the box, you need custom steps for advanced subtitles rendering:
ass rendering #### Cross-origin isolation jassub's wasm is multi-threaded and relies on `SharedArrayBuffer`, which browsers only expose on a **cross-origin-isolated** page. Serve these response headers on your HTML document: ``` Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: credentialless ``` `credentialless` keeps cross-origin video/subtitle/font requests working without requiring `Cross-Origin-Resource-Policy` headers on every remote asset. Without isolation, JASSUB initializes but silently never renders.
## Quick start Wrap your player UI in an `OmniProvider` with a `source`, then render an `OmniView` and drive it with the hooks. ```tsx import { OmniProvider, OmniView, usePlayer, usePlayerState, useEvent, } from "react-native-omni"; function Player() { const player = usePlayer(); const isPlaying = usePlayerState("isPlaying"); const currentTime = usePlayerState("currentTime"); const duration = usePlayerState("duration"); useEvent("end", () => player.playNext()); return ( <>