@cinecrew/cinecrew-player 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CineCrewPlayer.podspec +22 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +6 -0
  4. package/README.md +574 -0
  5. package/android/build.gradle +48 -0
  6. package/android/proguard-rules.pro +29 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/java/com/yuanzhou/vlc/ReactVlcPlayerPackage.java +28 -0
  9. package/android/src/main/java/com/yuanzhou/vlc/vlcplayer/ReactVlcPlayerView.java +988 -0
  10. package/android/src/main/java/com/yuanzhou/vlc/vlcplayer/ReactVlcPlayerViewManager.java +208 -0
  11. package/android/src/main/java/com/yuanzhou/vlc/vlcplayer/VideoEventEmitter.java +136 -0
  12. package/android/src/main/res/values/strings.xml +3 -0
  13. package/app.plugin.cjs +1 -0
  14. package/assets/cinecrew-player-logo.svg +44 -0
  15. package/package.json +132 -0
  16. package/packages/react-native-vlc-media-player/LICENSE +21 -0
  17. package/packages/react-native-vlc-media-player/VLCPlayer.js +207 -0
  18. package/packages/react-native-vlc-media-player/expo/android/withGradleTasks.cjs +49 -0
  19. package/packages/react-native-vlc-media-player/expo/ios/withMobileVlcKit.cjs +28 -0
  20. package/packages/react-native-vlc-media-player/expo/withVlcMediaPlayer.cjs +10 -0
  21. package/packages/react-native-vlc-media-player/index.d.ts +354 -0
  22. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayer.h +36 -0
  23. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayer.m +635 -0
  24. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayerManager.h +5 -0
  25. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayerManager.m +100 -0
  26. package/src/native/InlineLivePlayer.js +321 -0
  27. package/src/native/MediaPlayerView.js +3093 -0
  28. package/src/native/customization.js +44 -0
  29. package/src/native/index.js +107 -0
  30. package/src/native/media/ElectronVideoPlayer.js +288 -0
  31. package/src/native/media/EmojiPickerModal.js +30 -0
  32. package/src/native/media/LiveChatDrawer.js +1177 -0
  33. package/src/native/media/LiveRecordingOverlay.js +319 -0
  34. package/src/native/media/WebVideoPlayer.js +320 -0
  35. package/src/native/media/YouTubeVideoPlayer.native.js +120 -0
  36. package/src/native/media/YouTubeVideoPlayer.web.js +169 -0
  37. package/src/native/media/player/AudioOnlyView.js +337 -0
  38. package/src/native/media/player/CenterControls.js +94 -0
  39. package/src/native/media/player/ExoVideoFallback.js +329 -0
  40. package/src/native/media/player/PipOverlay.js +1 -0
  41. package/src/native/media/player/PlayerBottomBar.js +295 -0
  42. package/src/native/media/player/PlayerTopBar.js +255 -0
  43. package/src/native/media/player/VLCBoundary.js +41 -0
  44. package/src/native/media/player/VerticalIndicator.js +184 -0
  45. package/src/native/media/player/index.js +9 -0
  46. package/src/native/media/player/playerConstants.js +159 -0
  47. package/src/native/media/web/useWebAc3AudioPlayback.native.js +6 -0
  48. package/src/native/media/web/useWebAc3AudioPlayback.web.js +219 -0
  49. package/src/native/media/web/useWebHlsPlayback.native.js +3 -0
  50. package/src/native/media/web/useWebHlsPlayback.web.js +66 -0
  51. package/src/native/media/web/useWebMediaSession.js +90 -0
  52. package/src/native/media/web/useWebMpegTsPlayback.native.js +3 -0
  53. package/src/native/media/web/useWebMpegTsPlayback.web.js +356 -0
  54. package/src/native/media/web/useWebVideoAspectRatio.js +52 -0
  55. package/src/native/media/web/webPlaybackErrors.js +4 -0
  56. package/src/utils/layoutUtils.js +12 -0
  57. package/src/utils/mediaUtils.js +7 -0
  58. package/src/utils/recording.js +8 -0
  59. package/src/utils/runtimePlatform.js +19 -0
  60. package/src/utils/sourceUtils.js +99 -0
  61. package/src/utils/youtubeHtml.js +34 -0
  62. package/src/web/index.js +1129 -0
  63. package/src/web/styles.css +378 -0
  64. package/types/index.d.ts +268 -0
  65. package/vendor/mpegts.js/LICENSE +202 -0
  66. package/vendor/mpegts.js/mpegts.js +3 -0
@@ -0,0 +1,22 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |spec|
6
+ spec.name = 'CineCrewPlayer'
7
+ spec.version = package.fetch('version')
8
+ spec.summary = 'Customizable cross-platform video player with native VLC playback.'
9
+ spec.description = 'CineCrew Player includes its native VLC adapter for React Native playback.'
10
+ spec.homepage = 'https://github.com/nahushr/cinecrew-player'
11
+ spec.license = { :type => 'MIT', :file => 'packages/react-native-vlc-media-player/LICENSE' }
12
+ spec.author = { 'CineCrew' => 'https://github.com/nahushr' }
13
+ spec.source = { :git => 'https://github.com/nahushr/cinecrew-player.git' }
14
+ spec.source_files = 'packages/react-native-vlc-media-player/ios/RCTVLCPlayer/*.{h,m}'
15
+ spec.requires_arc = true
16
+ spec.static_framework = true
17
+ spec.ios.deployment_target = '11.0'
18
+ spec.tvos.deployment_target = '10.2'
19
+ spec.dependency 'React-Core'
20
+ spec.ios.dependency 'MobileVLCKit', '3.5.1'
21
+ spec.tvos.dependency 'TVVLCKit', '3.5.1'
22
+ end
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nahush Niraj Raichura
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,6 @@
1
+ This package includes a modified distribution build of mpegts.js.
2
+ mpegts.js is Copyright (c) its respective authors and is distributed under
3
+ the Apache License, Version 2.0. See vendor/mpegts.js/LICENSE.
4
+
5
+ The native VLC adapter is based on react-native-vlc-media-player and retains
6
+ its upstream MIT license and notices in packages/react-native-vlc-media-player.
package/README.md ADDED
@@ -0,0 +1,574 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/nahushr/cinecrew-player/main/assets/cinecrew-player-logo.svg" alt="CineCrew app logo and wordmark" width="470" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/nahushr/cinecrew-player/actions"><img src="https://github.com/nahushr/cinecrew-player/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
7
+ <a href="https://www.npmjs.com/package/@cinecrew/cinecrew-player"><img src="https://img.shields.io/npm/v/@cinecrew/cinecrew-player.svg" alt="npm version" /></a>
8
+ </p>
9
+
10
+ <h3 align="center">One player layer. Your app. Every screen.</h3>
11
+
12
+ <p align="center">
13
+ A customizable playback experience for <strong>React</strong>, <strong>React Native</strong>, and <strong>Electron</strong>—from on-demand movies to Live TV previews, with the controls and integrations your product needs.
14
+ </p>
15
+
16
+ <p align="center">
17
+ <img alt="React" src="https://img.shields.io/badge/React-18%2B-61DAFB?logo=react&logoColor=111827" />
18
+ <img alt="React Native" src="https://img.shields.io/badge/React_Native-0.73%2B-61DAFB?logo=react&logoColor=111827" />
19
+ <img alt="TypeScript declarations" src="https://img.shields.io/badge/TypeScript-types%20included-3178C6?logo=typescript&logoColor=white" />
20
+ <a href="LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-16a085.svg" /></a>
21
+ </p>
22
+
23
+ <p align="center"><a href="#install">Install</a> · <a href="#feature-portfolio">Features</a> · <a href="#platform--playback-matrix">Platforms</a> · <a href="#props">API reference</a> · <a href="#roadmap">Roadmap</a></p>
24
+
25
+ <p align="center"><strong>🎬 Movies</strong> &nbsp; <strong>📡 Live TV</strong> &nbsp; <strong>📱 Native</strong> &nbsp; <strong>🖥️ Web & Electron</strong></p>
26
+
27
+ | **2 player components** | **5 target environments** | **16 visibility controls** | **20 action hooks** |
28
+ |:---:|:---:|:---:|:---:|
29
+ | Full player + inline live preview | Web · Electron · Android · iOS · React Native Web | Choose what appears | Override default actions |
30
+
31
+ > **The product promise:** use ready-to-play defaults first; customize the interface, playback actions, and app-service adapters only where your product needs them.
32
+
33
+ ## Playback at a glance
34
+
35
+ ```mermaid
36
+ flowchart LR
37
+ A[Playable URL or local media] --> B{Optional app resolver}
38
+ B --> C{Host platform}
39
+ C -->|React web / Electron / RN Web| D[Browser media element]
40
+ D --> E[Native formats · hls.js · patched MPEG-TS]
41
+ C -->|React Native Android / iOS| F[VLC adapter]
42
+ F --> G[Expo Video fallback where available]
43
+ E --> H[Shared player controls]
44
+ G --> H
45
+ H --> I[Theme · icons · callbacks]
46
+ H --> J[Optional app adapters: chat · EPG · recording]
47
+ ```
48
+
49
+ <p align="center"><sub>CineCrew Player handles the player surface and platform playback path. Your app remains in charge of authorization, link resolution, CORS, and service backends.</sub></p>
50
+
51
+ ## Feature portfolio
52
+
53
+ | Area | Included capabilities | Designed for |
54
+ |---|---|---|
55
+ | 🎞️ **Playback** | On-demand and live media; URLs and local URIs; HLS and MPEG-TS paths on web; native VLC path; embedded YouTube playback | Movies, episodes, trailers, and channels |
56
+ | 🎛️ **Player controls** | Play/pause, seek, restart, mute, aspect ratio, lock, video-only/audio-only modes, audio tracks, playback speed, fullscreen, back, minimize | A complete control surface without hard-wiring your app navigation |
57
+ | 🎨 **Branding** | Theme colors, radius, platform styles, replaceable icons, custom panel render slots | Match your app without forking the player |
58
+ | 📡 **Live TV extensions** | Inline preview component; optional chat and EPG panels; recording adapter hooks | Channel browsing and live-viewing workflows |
59
+ | 🔌 **App integration** | Per-action callbacks, imperative ref API, source resolver, progress/presence/events hooks, sleep timer callback | Keep account, IPTV, analytics, and storage logic in your app |
60
+ | 🧭 **Playback lifecycle** | Ready, playing, buffering, progress, ended, error, fullscreen, next-episode, and playback-route callbacks | App-owned navigation, telemetry, and resume state |
61
+
62
+ <details>
63
+ <summary><strong>🎛️ Control inventory — all 16 visibility switches</strong></summary>
64
+
65
+ | Icon | `controls` key | What it controls | Notes |
66
+ |:---:|---|---|---|
67
+ | ↩️ | `back` | Back / close | Can be owned by app navigation |
68
+ | ▶️ | `playPause` | Play / pause | Center playback action |
69
+ | 🔁 | `restart` | Restart | Primarily useful for on-demand media |
70
+ | 🔒 | `lock` | Lock / unlock controls | Prevent accidental touches |
71
+ | 🔊 | `mute` | Mute / unmute | Volume prop also sets initial level |
72
+ | 🖼️ | `aspectRatio` | Fit / fill / stretch | Available choices depend on renderer |
73
+ | 🔇 | `videoOnly` | Video-only mode | Keeps video presentation while muting audio |
74
+ | 🎧 | `audioOnly` | Audio-only presentation | Playback continues behind the audio card |
75
+ | 🎚️ | `audioTracks` | Audio-track selection | Depends on exposed tracks / platform engine |
76
+ | ⏩ | `playbackRate` | Playback speed | On-demand experience |
77
+ | ⤵️ | `minimize` | Minimize action | App supplies its navigation or sheet behavior |
78
+ | ⛶ | `fullscreen` | Fullscreen / promote preview | Native full-player presentation is platform-specific |
79
+ | ⏺️ | `recording` | Recording controls | Requires an app recording adapter or callback |
80
+ | 💬 | `liveChat` | Live chat panel | Requires an adapter, render slot, or callback |
81
+ | 📅 | `epg` | Electronic program guide | Requires an adapter, render slot, or callback |
82
+ | ⏱️ | `seek` | Seek bar | Meaningful for seekable media |
83
+
84
+ </details>
85
+
86
+ <details>
87
+ <summary><strong>🧩 Customization inventory</strong></summary>
88
+
89
+ | Customize | How |
90
+ |---|---|
91
+ | 🎨 Colors and shape | `theme`: accent, background, control, surface, error colors, border radius, and native palette |
92
+ | 🪄 Icons | `icons`: provide a glyph/string, React node, or icon component; omitted icons keep CineCrew defaults |
93
+ | 🧠 Per-control behavior | `actions`: override only the actions your app wants to own; built-in behavior remains the default otherwise |
94
+ | 🧱 App-owned panels | `renderLiveChat`, `renderEpg`, or integration render callbacks |
95
+ | 🔗 Source handling | `resolveSource` for share pages or host-specific resolution; direct media sources pass through unchanged |
96
+ | 📐 Layout | `style`, web `className`, inline preview geometry, and `InlineLivePlayer` height |
97
+ | 📣 Events and state | Lifecycle callbacks plus progress, presence, analytics, and sleep-timer integrations |
98
+
99
+ </details>
100
+
101
+ ## Platform & playback matrix
102
+
103
+ | Host | Public entry | Rendering / engine path | Key considerations |
104
+ |---|---|---|---|
105
+ | 🌐 React in browser | `@cinecrew/cinecrew-player` or `@cinecrew/cinecrew-player/react` | DOM player; browser media, hls.js, patched mpegts.js; YouTube embed | Browser codec support and origin CORS still apply |
106
+ | 🖥️ Electron | `@cinecrew/cinecrew-player/electron` | Same web renderer inside Electron Chromium | Chromium’s codec and network rules still apply |
107
+ | 🤖 React Native Android | `@cinecrew/cinecrew-player/native` or `@cinecrew/cinecrew-player/react-native` | Native React Native surface with bundled VLC adapter; Expo Video fallback where available | Native dependencies must be compiled into the app |
108
+ | 📱 React Native iOS | `@cinecrew/cinecrew-player/native` or `@cinecrew/cinecrew-player/react-native` | Native React Native surface with bundled VLC adapter; Expo Video fallback where available | Native dependencies must be compiled into the app |
109
+ | 🧪 React Native Web / Expo Web | `@cinecrew/cinecrew-player/react-native-web` | Browser renderer from a React Native Web host | Uses web media paths, not native VLC |
110
+
111
+ | Media / source | Web & Electron | React Native | What the app may need to provide |
112
+ |---|---|---|---|
113
+ | MP4 / browser-native media | ✅ Browser media element | ✅ Native engine | A directly playable URL or local URI |
114
+ | HLS (`.m3u8`) | ✅ hls.js / native HLS where available | ✅ Native engine | Origin access, valid playlist/segments, compatible codecs |
115
+ | MPEG-TS (`.ts`) | ✅ Bundled patched MPEG-TS client, when browser conditions permit | ✅ VLC path | Browser codecs and CORS; native module availability |
116
+ | YouTube watch / Shorts / `youtu.be` | ✅ Embedded YouTube player | ✅ Embedded native WebView | Video must allow embedding; network access to YouTube |
117
+ | Local files | ✅ Platform-supported local/blob URI | ✅ Platform-supported file URI | App obtains and passes the platform-readable URI |
118
+ | Share pages / cloud-drive pages | ⚙️ Optional `resolveSource` | ⚙️ Optional `resolveSource` | Your app resolves authentication and obtains a playable media URL |
119
+
120
+ **Compatibility is not a promise that every URL plays everywhere.** A browser needs a compatible container/codec and any required CORS permission. Arbitrary web pages are not necessarily media files. For known browser-incompatible MPEG-TS audio such as AC3, use native playback when supported or handle the browser error in the consuming app.
121
+
122
+ ## Tech stack
123
+
124
+ | Layer | Technologies in this package |
125
+ |---|---|
126
+ | UI & API | React · React Native · TypeScript declarations |
127
+ | Web playback | HTML video · hls.js · patched mpegts.js · YouTube IFrame API |
128
+ | Native playback | VLC adapter bundled in `@cinecrew/cinecrew-player` · `expo-video` fallback |
129
+ | Native UI / utilities | React Native · Expo config plugins · safe-area context · SVG · community slider |
130
+ | Optional media utilities | Mediabunny / AC3 parsing support in relevant web playback paths |
131
+ | Packaging | Platform-specific entry points · npm exports · bundled styles · native autolinking |
132
+
133
+ ## Why this can be the player layer for a movie or IPTV app
134
+
135
+ | Your app owns | CineCrew Player supplies |
136
+ |---|---|
137
+ | 🔐 User accounts, subscriptions, authorization, and provider credentials | 🎛️ Shared player UI and default controls |
138
+ | 🔗 Turning provider/share links into playable sources; CORS and networking policy | 🔀 Platform-aware browser/native playback adapters |
139
+ | 💬 Chat service, 📅 EPG service, and ⏺️ recording implementation | 🧩 Integration surfaces and optional built-in presentation |
140
+ | 🗃️ Catalog, favorites, watch history, and backend storage | 🎨 Customizable theme, icons, control visibility, callbacks, and lifecycle events |
141
+
142
+ **The result:** one player integration can serve movie and Live TV product flows across web, Electron, and native mobile, while provider-specific and account-specific code stays in the host app.
143
+
144
+ > CineCrew Player is a playback component—not an IPTV service, media relay, DRM system, or universal URL-to-video converter. The package does not require a CineCrew account, worker, backend, or proxy.
145
+
146
+ ## Roadmap
147
+
148
+ The items below are planned for more consistent, user-facing support across platforms. Some playback engines may already expose related low-level capabilities.
149
+
150
+ | Status | Planned feature |
151
+ |:---:|---|
152
+ | [ ] | ☀️ Cross-platform brightness control |
153
+ | [ ] | 🔉 In-player volume slider (in addition to mute / unmute) |
154
+ | [ ] | ✨ AI-generated subtitles |
155
+ | [ ] | 🎧 Broader client-side audio demuxing across codecs and stream types |
156
+ | [ ] | 🪟 Consistent picture-in-picture controls across platforms |
157
+
158
+ [![Open React demo in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/fork/github/nahushr/cinecrew-player/tree/main/examples/web-demo?startScript=dev)
159
+
160
+ [Try the Android demo in Expo Snack](https://snack.expo.dev/?name=CineCrew%20Player%20Android&dependencies=%40cinecrew%2Fcinecrew-player%2Cexpo-document-picker&sourceUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fnahushr%2Fcinecrew-player%2Fmain%2Fexamples%2Fsnack%2FApp.js&platform=android&supportedPlatforms=android) · [Try the iOS demo in Expo Snack](https://snack.expo.dev/?name=CineCrew%20Player%20iOS&dependencies=%40cinecrew%2Fcinecrew-player%2Cexpo-document-picker&sourceUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fnahushr%2Fcinecrew-player%2Fmain%2Fexamples%2Fsnack%2FApp.js&platform=ios&supportedPlatforms=ios)
161
+
162
+ ## Demos
163
+
164
+ - **[React + Vite web demo](examples/web-demo)** — try YouTube, MPEG-TS, MP4, MKV, or a local video file. Switch between the full player (all controls and demo chat/EPG/recording adapters enabled) and the compact inline player. [Open a fresh StackBlitz copy](https://stackblitz.com/fork/github/nahushr/cinecrew-player/tree/main/examples/web-demo?startScript=dev).
165
+ - **[Expo / React Native Web demo](examples/expo-web-demo)** — the same source tests and controls in an Expo app rendered for the web.
166
+ - **[Android and iOS Expo Snack demos](examples/snack/App.js)** — both platform links load the same five-test native playground (YouTube, `.ts`, `.mp4`, `.mkv`, and local-file upload), with full-player and inline-player modes. Snack runs in Expo Go, which cannot load this package's custom VLC module; MPEG-TS and MKV playback should be tested in a native development build. [Expo documents this Expo Go limitation](https://docs.expo.dev/faq/#what-can-i-do-or-cannot-do-with-expo-go).
167
+
168
+ The React/Vite and Expo Web demos use the single package in this repository (`file:../..`) so they can build before and after the public release. Snack loads the native example from this repository's `main` branch and installs `@cinecrew/cinecrew-player` from npm, so those links become runnable once the example is pushed and the package is published. The React DOM entry resolves to the browser renderer; it does not evaluate React Native or VLC code. The Expo native entry bundles VLC into the same installed package. External media hosts must allow browser CORS requests; format/codec support also depends on the browser. MKV playback is generally more reliable through the native VLC adapter than a browser video element.
169
+
170
+ Run either demo:
171
+
172
+ ```sh
173
+ cd examples/web-demo
174
+ npm install
175
+ npm run dev
176
+ ```
177
+
178
+ ```sh
179
+ cd examples/expo-web-demo
180
+ npm install
181
+ npm run web
182
+ ```
183
+
184
+ > Direct media sources are passed through to the platform engine. A page/share URL is not necessarily a playable media source; use `resolveSource` to resolve it. The player does not rewrite protocols, proxy media, or impose host-specific CORS rules.
185
+
186
+ ## Install
187
+
188
+ Install the player from the public npm registry:
189
+
190
+ ```sh
191
+ npm install @cinecrew/cinecrew-player
192
+ ```
193
+
194
+ React is the shared peer dependency. Native React Native builds use the VLC adapter bundled in this package plus the `expo-video` fallback; native code is autolinked and compiled into the app binary. Plain React web consumers use the browser entry and do not execute or compile the bundled Android/iOS source.
195
+
196
+ ### Supported targets and entry points
197
+
198
+ The package has one public player API with a renderer selected for the host. The React DOM/Electron entry has no React Native renderer or WebView import; bundled Android/iOS files are only compiled when a React Native host selects the native entry and autolinks the native module.
199
+
200
+ | Host app | Import | Renderer / playback |
201
+ | --- | --- | --- |
202
+ | React DOM in a browser | `@cinecrew/cinecrew-player` or `@cinecrew/cinecrew-player/react` | HTML video, hls.js, patched mpegts.js, and the browser YouTube embed. |
203
+ | React DOM inside Electron (macOS `.dmg`, Windows `.exe`) | `@cinecrew/cinecrew-player/electron` | Same renderer as React web, using Electron's Chromium media stack. No WebView or custom Electron IPC bridge is needed. |
204
+ | React Native Android / iOS | `@cinecrew/cinecrew-player` or `@cinecrew/cinecrew-player/react-native` | React Native UI with the bundled VLC adapter and Expo video fallback; YouTube uses `react-native-webview`. |
205
+ | React Native Web / Expo Web | `@cinecrew/cinecrew-player` or `@cinecrew/cinecrew-player/react-native-web` | React DOM adapter hosted inside the React Native Web app; uses browser playback engines and does not load native VLC or WebView code. |
206
+
207
+ Metro selects the React Native entry for native builds; regular React bundlers select the React DOM entry. The explicit subpaths let you pin the renderer when preferred.
208
+
209
+ ### React Native / Expo
210
+
211
+ ```tsx
212
+ import CineCrewPlayer from '@cinecrew/cinecrew-player/native';
213
+
214
+ export function WatchScreen() {
215
+ return (
216
+ <CineCrewPlayer
217
+ source={{ uri: 'https://media.example.com/live/channel.m3u8', isLive: true }}
218
+ title="Example channel"
219
+ controls={{ liveChat: false, epg: false, recording: false }}
220
+ />
221
+ );
222
+ }
223
+ ```
224
+
225
+ For an Expo prebuild project, add the CineCrew Player config plugin and rebuild the native app (a JavaScript reload cannot add a native module). The VLC native implementation ships inside this same package; there is no second VLC package to install. `react-native-webview` is used only as the native YouTube embed surface; regular native streams use VLC / `expo-video`. Browser and Electron YouTube playback use the YouTube IFrame API instead.
226
+
227
+ ```json
228
+ {
229
+ "expo": {
230
+ "plugins": ["@cinecrew/cinecrew-player"]
231
+ }
232
+ }
233
+ ```
234
+
235
+ Then run `npx expo prebuild` as appropriate for your project and rebuild/install the development or production client. Expo Go does not contain the VLC native module; the player uses its `expo-video` fallback where available. In bare React Native projects, install the native dependencies, run CocoaPods on iOS, and rebuild the app.
236
+
237
+ The component opens the native player as a full-screen player. To show a compact live preview in a channel list, use the companion component:
238
+
239
+ ```tsx
240
+ import { InlineLivePlayer } from '@cinecrew/cinecrew-player/native';
241
+
242
+ <InlineLivePlayer
243
+ url={channelUrl}
244
+ title="Example channel"
245
+ height={220}
246
+ isActive={selected}
247
+ paused={!selected}
248
+ onFullscreen={() => openFullPlayer(channelUrl)}
249
+ />
250
+ ```
251
+
252
+ The web entry exports the same compact preview component:
253
+
254
+ ```tsx
255
+ import { InlineLivePlayer } from '@cinecrew/cinecrew-player/web';
256
+ import '@cinecrew/cinecrew-player/styles.css';
257
+
258
+ <InlineLivePlayer
259
+ source={{ uri: channelUrl, isLive: true }}
260
+ title="Example channel"
261
+ isActive={selected}
262
+ paused={!selected}
263
+ onFullscreen={() => openFullPlayer(channelUrl)}
264
+ />
265
+ ```
266
+
267
+ ### React (web)
268
+
269
+ ```tsx
270
+ import CineCrewPlayer from '@cinecrew/cinecrew-player';
271
+ import '@cinecrew/cinecrew-player/styles.css';
272
+
273
+ export function WatchScreen() {
274
+ return (
275
+ <CineCrewPlayer
276
+ source={{ uri: 'https://media.example.com/live/channel.m3u8', isLive: true }}
277
+ title="Example channel"
278
+ autoPlay
279
+ theme={{ accentColor: '#35d7ff', borderRadius: 16 }}
280
+ />
281
+ );
282
+ }
283
+ ```
284
+
285
+ Web playback is direct from the supplied URL. HLS and MPEG-TS clients fetch playlists and segments from the stream origin, so the origin must permit those browser requests.
286
+
287
+ ### YouTube and share links
288
+
289
+ Pass a YouTube watch, Shorts, or `youtu.be` URL as the source to play it inside the player rather than opening another app:
290
+
291
+ ```tsx
292
+ <CineCrewPlayer source="https://www.youtube.com/watch?v=dQw4w9WgXcQ" title="Trailer" />
293
+ ```
294
+
295
+ The video must allow embedding. Other URLs are passed unchanged to the platform engine. A Google Drive/share page or other webpage is not itself a media stream; resolve it in your app and provide the playable URL, or use the optional `resolveSource` callback. This keeps provider authentication, CORS policy, and URL extraction under the consuming app’s control.
296
+
297
+ ```tsx
298
+ <CineCrewPlayer
299
+ source={{ uri: driveShareUrl, title: 'My video' }}
300
+ resolveSource={async (source, { platform }) => ({
301
+ ...source,
302
+ uri: await resolveMyDriveMediaUrl(source.uri, platform),
303
+ })}
304
+ />
305
+ ```
306
+
307
+ ## Media support
308
+
309
+ | Platform | Playback path | Notes |
310
+ | --- | --- | --- |
311
+ | Web | Native `<video>`, hls.js, and the bundled patched mpegts.js client | MP4 and browser-native formats, HLS (`.m3u8`), and MPEG-TS (`.ts`) when the stream, codecs, and CORS policy permit it. |
312
+ | React Native Android / iOS | VLC native module; `expo-video` fallback when VLC is unavailable | VLC supports a broader range of containers/codecs, including common AC3 streams. Native module availability depends on the app binary. |
313
+ | Electron renderer | Chromium `<video>`, hls.js, and patched mpegts.js | Same browser codec/CORS constraints as React web; packages with the app's `.dmg` / `.exe`. |
314
+
315
+ Browser codec support varies. The web player reports an AC3 compatibility message only when its MPEG-TS probe identifies unsupported AC3 audio; native playback does not apply this browser-only restriction. YouTube sources use the embedded YouTube player and remain subject to the video’s embed settings.
316
+
317
+ ## How CineCrew Player differs from established players
318
+
319
+ This is a comparison of each project’s **documented focus and out-of-the-box integration surface**, not a claim that another library cannot be extended to do these things. HLS, YouTube playback, custom styling, and player controls are established capabilities in this space—not unique CineCrew claims.
320
+
321
+ | Player | Documented focus | Where CineCrew’s focus differs |
322
+ | --- | --- | --- |
323
+ | [Vidstack](https://vidstack.io/docs/player/) | A feature-rich **web** media framework with React and Web Component APIs, customizable/headless components, production layouts, and providers including HLS, DASH, YouTube, and Vimeo. | CineCrew packages web playback together with a React Native renderer for Android/iOS, an Electron web entry, and adapter slots for app-owned IPTV services. |
324
+ | [Video.js](https://github.com/videojs/video.js/) | A mature **web-based HTML5 player** supporting common web media and streaming formats such as HLS/DASH, with a broad plugin ecosystem. | CineCrew’s package-level scope also includes native React Native playback and app-oriented control/integration props, rather than being centered on the browser player ecosystem. |
325
+ | [React Native Video](https://docs.thewidlarzgroup.com/react-native-video/docs/v7/fundamentals/intro/) | A **React Native playback library** for native platforms. Its v7 documentation describes a player/view split; its view API includes native controls and a PiP option where supported. | CineCrew combines native playback with its own customizable player shell and web/Electron renderers, and documents optional live-chat, EPG, and recording adapters. |
326
+
327
+ In short: CineCrew’s intended distinction is **one app-facing player package for movie and IPTV product flows across web and native mobile**, with Electron support and app-owned service adapters. Vidstack and Video.js have more mature, broader web ecosystems; React Native Video is a strong native playback option. CineCrew is not claiming to replace every specialized player or to have feature parity with those ecosystems.
328
+
329
+ ## Props
330
+
331
+ `CineCrewPlayer` accepts the following common props. `source` can be a URL string or an object; `url` is a convenience alias.
332
+
333
+ | Prop | Type | Default | Description |
334
+ | --- | --- | --- | --- |
335
+ | `source` | `string \| PlayerSource` | — | Media URL and optional metadata. `uri` and `url` are accepted. |
336
+ | `url` | `string` | — | Alias for `source`. |
337
+ | `title` | `string` | `source.title \| ''` | Display title. |
338
+ | `poster` / `posterUrl` | `string` | `source.posterUrl` | Poster displayed where supported and in audio-only mode. |
339
+ | `mediaType` | `string` | inferred | For example `live`, `movie`, or `series`. |
340
+ | `isLive` | `boolean` | `source.isLive \| false` | Marks a live source. |
341
+ | `visible` | `boolean` | URL present | Show or hide the native player. |
342
+ | `autoPlay` | `boolean` | `true` | Start playback automatically. Browser autoplay policies may still require muted playback or a user gesture. |
343
+ | `paused` | `boolean` | `!autoPlay` | Initial paused state; web also observes changes. |
344
+ | `muted` | `boolean` | `false` | Initial mute state. |
345
+ | `volume` | `number` | `1` | Initial volume from `0` to `1`. |
346
+ | `playbackRate` | `number` | `1` | Initial playback speed; the on-demand speed control can change it afterward. |
347
+ | `controls` | `PlayerControls` | defaults below | Show/hide individual control buttons. |
348
+ | `actions` | `PlayerActions` | `{}` | Replace the built-in behavior for individual actions. If a callback is provided, that callback owns the action. |
349
+ | `integrations` | `PlayerIntegrations` | `{}` | Inject user identity, chat, EPG, recording, analytics, and presence services. |
350
+ | `theme` | `PlayerTheme` | built-in theme | Customize player colors, borders, and shape. |
351
+ | `icons` | `PlayerIcons` | built-in icons | Override any control icon by key. |
352
+ | `style` | platform style | — | Outer player style. On web this is a CSS style object; native uses React Native style props. |
353
+ | `className` | `string` | `''` | Web-only class name for the player root. |
354
+ | `videoOnly` | `boolean` | `false` | Start muted in video-only mode. |
355
+ | `audioOnly` | `boolean` | `false` | Start in audio-only presentation. Playback continues while the visual card is shown. |
356
+ | `resolveSource` | callback | — | Optional synchronous or asynchronous resolver for share pages and provider-specific links. Receives `{ uri, ...source }` and `{ platform }`; return a playable URL or `PlayerSource`. Without it, the original source is passed through unchanged. |
357
+ | `audioTracks` | `AudioTrack[]` | detected | Optional supplied track list (web). Native tracks are read from the native player. |
358
+ | `selectedAudioTrack` | `string \| number` | first/default track | Initial or preferred audio track. |
359
+ | `resumePosition` | `number` | `0` | Resume position in seconds for on-demand playback. |
360
+ | `durationSecs` | `number` | `0` | Known duration in seconds. |
361
+ | `mediaId`, `episodeLabel`, `season`, `episode`, `genre`, `categoryName` | metadata | — | Optional item metadata for the player and integrations. |
362
+ | `playlist` | `object[]` | — | Episode list used for automatic next-episode behavior. |
363
+ | `shuffle` | `boolean` | `false` | Select a random next episode when the current episode ends. |
364
+ | `onClose`, `onBack`, `onMinimize` | callbacks | — | Player lifecycle/navigation callbacks. |
365
+ | `onReady`, `onProgress`, `onPlaying`, `onBuffering`, `onError`, `onEnded`, `onPlaybackRoute` | callbacks | — | Playback lifecycle callbacks. Progress payloads are platform-specific native/browser events. |
366
+ | `onNextEpisode`, `onCwRefresh` | callbacks | — | Episode advancement and post-close refresh hooks. |
367
+ | `renderLiveChat`, `renderEpg` | render functions | — | Web custom-panel render slots. On native, use the chat/EPG integration adapters. |
368
+ | `initialShowLiveChat`, `liveChatNonce` | `boolean`, `number` | `false`, `0` | Open or re-open the live-chat panel (when available). |
369
+ | `inlinePreview`, `inlinePreviewRect`, `onInlinePreviewWheel`, `onPromotePreview`, `onPlayerHostRef` | preview options and callbacks | — | Embed/manage the player as a movable inline preview. Mainly useful for app-level player shells. |
370
+
371
+ `features` can enable optional diagnostics with `{ diagnostics: true }`. `onFullscreen` receives `{ isFullscreen }`. All lifecycle callbacks in the table are optional; native event objects differ from browser events.
372
+
373
+ ### Player source
374
+
375
+ ```ts
376
+ type PlayerSource = string | {
377
+ uri?: string;
378
+ url?: string;
379
+ title?: string;
380
+ poster?: string;
381
+ posterUrl?: string;
382
+ id?: string | number;
383
+ streamId?: string | number;
384
+ mediaId?: string | number;
385
+ type?: string; // e.g. 'mpegts', 'hls', or 'youtube' when paired with a YouTube video ID
386
+ mimeType?: string;
387
+ mediaType?: string;
388
+ isLive?: boolean;
389
+ };
390
+ ```
391
+
392
+ ### Inline live preview props
393
+
394
+ `InlineLivePlayer` is exported from `@cinecrew/cinecrew-player/native` and `@cinecrew/cinecrew-player/web`. It renders a compact channel preview/poster and can promote playback to the host app's full player.
395
+
396
+ | Prop | Type | Default | Description |
397
+ | --- | --- | --- | --- |
398
+ | `source`, `url` | `string \| PlayerSource` | — | Direct channel URL and optional channel metadata. |
399
+ | `title` | `string` | `Live TV` | Channel title shown in the preview. |
400
+ | `height` | `number` | `220` | Inline preview height. |
401
+ | `poster`, `posterChannel` | string / object | — | Still image or channel object used when preview is paused/inactive. |
402
+ | `paused`, `isActive` | `boolean` | `false`, `true` | Control whether this preview should render/play its stream. |
403
+ | `onActivate` | `() => void` | — | Called when an inactive preview poster is selected. |
404
+ | `onFullscreen` | `() => void` | — | Called to promote/open the full player. |
405
+ | `controls` | `Pick<PlayerControls, 'playPause' \| 'mute' \| 'fullscreen'>` | all shown | Toggle its compact controls. |
406
+ | `actions` | matching `PlayerActions` subset | built-in | Replace play/pause, mute, or promote behavior. |
407
+ | `initialMuted` | `boolean` | `true` | Initial preview mute state. |
408
+ | `theme`, `icons`, `style` | `PlayerTheme`, `PlayerIcons`, platform style | defaults | Customize preview colors, controls, and layout. |
409
+ | `onError`, `onPlaying` | callbacks | — | Playback lifecycle callbacks. |
410
+
411
+ ## Control visibility
412
+
413
+ Every control can be hidden with `false`. Defaults are designed to be useful out of the box; adapter-backed controls appear when their adapter or corresponding action callback is supplied.
414
+
415
+ ```tsx
416
+ <CineCrewPlayer
417
+ source={source}
418
+ controls={{
419
+ back: true,
420
+ playPause: true,
421
+ restart: true,
422
+ lock: true,
423
+ mute: true,
424
+ aspectRatio: true,
425
+ videoOnly: false,
426
+ audioOnly: true,
427
+ audioTracks: true,
428
+ playbackRate: true,
429
+ minimize: false,
430
+ fullscreen: true,
431
+ recording: false,
432
+ liveChat: false,
433
+ epg: false,
434
+ seek: true,
435
+ }}
436
+ />
437
+ ```
438
+
439
+ | Control key | Description |
440
+ | --- | --- |
441
+ | `back` | Back/close button. Native hardware back remains available. |
442
+ | `playPause` | Center play/pause control. |
443
+ | `restart` | Restart on-demand media. |
444
+ | `lock` | Lock/unlock touch controls. |
445
+ | `mute` | Mute/unmute. |
446
+ | `aspectRatio` | Fit/fill/stretch and available aspect choices. |
447
+ | `videoOnly` | Mute audio while keeping video visible. |
448
+ | `audioOnly` | Show the audio-only card while playback continues. |
449
+ | `audioTracks` | Audio-track picker when tracks are exposed. |
450
+ | `playbackRate` | On-demand playback speed. |
451
+ | `minimize` | Minimize callback button; hidden unless enabled. |
452
+ | `fullscreen` | Fullscreen button on web and inline previews. Native player opens full-screen. |
453
+ | `recording` | Recording controls; requires `integrations.recording` or an action override. |
454
+ | `liveChat` | Chat drawer/panel; requires a chat adapter, render slot, or action override. |
455
+ | `epg` | EPG drawer/panel; requires an EPG adapter, render slot, or action override. |
456
+ | `seek` | On-demand seek bar. |
457
+
458
+ ## Actions and callbacks
459
+
460
+ Callbacks passed to `actions` **replace** built-in behavior; this is useful when an app wants to own navigation, playback state, or a control. Each receives an action payload and a context with the imperative `player` API (and the web video element where available).
461
+
462
+ ```tsx
463
+ const playerRef = React.useRef(null);
464
+
465
+ <CineCrewPlayer
466
+ ref={playerRef}
467
+ source={source}
468
+ actions={{
469
+ onRestart: (_payload, { player }) => player?.restart(),
470
+ onMinimize: () => closePlayerSheet(),
471
+ onBack: () => navigation.goBack(),
472
+ onMute: ({ muted }, { player }) => player?.setMuted(muted),
473
+ onAspectRatioChange: ({ aspectRatio }, { player }) => player?.setAspectRatio(aspectRatio),
474
+ }}
475
+ />
476
+ ```
477
+
478
+ Available action keys: `onBack`, `onPlayPause`, `onSeek`, `onRestart`, `onLock`, `onMute`, `onAspectRatioChange`, `onVideoOnlyChange`, `onAudioOnlyChange`, `onAudioTrackChange`, `onMinimize`, `onPlaybackRateChange`, `onFullscreen`, `onRecordingStart`, `onRecordingPause`, `onRecordingResume`, `onRecordingStop`, `onLiveChatOpen`, `onEpgOpen`, and `onDiagnosticsOpen`.
479
+
480
+ The ref exposes `play`, `pause`, `togglePlayPause`, `restart`, `setMuted`, `toggleMute`, `setAspectRatio`, `setAudioTrack`, `setAudioOnly`, `setVideoOnly`, `setPlaybackRate`, `seekTo`, `seekBy`, `back`, `minimize`, `getVideoElement`, `getAudioTracks`, and fullscreen methods where supported.
481
+
482
+ ## Integrations
483
+
484
+ Integrations are optional. The package has no CineCrew account, database, or worker dependency; the consuming app supplies its own functions.
485
+
486
+ ```tsx
487
+ <CineCrewPlayer
488
+ source={source}
489
+ mediaId={channel.id}
490
+ integrations={{
491
+ user: { id: currentUser.id, username: currentUser.name },
492
+ liveChat: {
493
+ pollIntervalMs: 5000,
494
+ loadMessages: ({ channelId, limit }) => api.loadChat(channelId, limit),
495
+ sendMessage: ({ channelId, userId, username, comment }) =>
496
+ api.sendChat({ channelId, userId, username, comment }),
497
+ },
498
+ epg: {
499
+ limit: 48,
500
+ loadListings: ({ channelId, limit }) => api.getEpg(channelId, limit),
501
+ },
502
+ recording: {
503
+ start: ({ getVideoElement, streamUrl, title }) => recorder.start({ getVideoElement, streamUrl, title }),
504
+ pause: () => recorder.pause(),
505
+ resume: () => recorder.resume(),
506
+ stop: () => recorder.stop(),
507
+ isActive: () => recorder.isActive(),
508
+ subscribe: (listener) => recorder.subscribe(listener),
509
+ },
510
+ onEvent: ({ name, payload }) => analytics.track(name, payload),
511
+ onProgress: (progress) => saveProgress(progress),
512
+ onPresence: (presence) => updatePresence(presence),
513
+ onSleepTimerExpired: (close) => sleepTimer.onExpired(close),
514
+ }}
515
+ />
516
+ ```
517
+
518
+ `loadMessages` returns an array of messages with `username` and `comment` (or `message`) fields. `loadListings` returns EPG entries with `startMs` and `endMs` epoch-millisecond timestamps. The native player renders the built-in chat and EPG UI from these adapters. On web, an app can use `renderLiveChat` / `renderEpg`, or provide `integrations.liveChat.render` / `integrations.epg.render`.
519
+
520
+ ## Themes and icons
521
+
522
+ Defaults are used unless the caller supplies an override. Web theme properties include `accentColor`, `backgroundColor`, `controlBackground`, `controlColor`, `surfaceColor`, `errorColor`, and `borderRadius`. Native also accepts a `colors` palette object.
523
+
524
+ ```tsx
525
+ <CineCrewPlayer
526
+ source={source}
527
+ theme={{
528
+ accentColor: '#16c7d9',
529
+ backgroundColor: '#07111e',
530
+ surfaceColor: '#101e30',
531
+ controlColor: '#f8fbff',
532
+ borderRadius: 18,
533
+ }}
534
+ icons={{
535
+ play: <MyPlayIcon />,
536
+ pause: <MyPauseIcon />,
537
+ mute: 'volume-mute',
538
+ fullscreen: ({ color, size }) => <MyFullscreenIcon color={color} size={size} />,
539
+ }}
540
+ />
541
+ ```
542
+
543
+ Icon keys: `play`, `pause`, `restart`, `lock`, `unlock`, `mute`, `unmute`, `aspectRatio`, `videoOnly`, `audio`, `minimize`, `back`, `recording`, `stop`, `liveChat`, `epg`, `fullscreen`, and `close`. A value may be a string/glyph, a React element, or an icon component.
544
+
545
+ ## Sources and link resolution
546
+
547
+ Local file URIs and direct stream URLs are passed to the selected platform player without changing `http`, `https`, `file`, or other schemes. YouTube watch/share URLs are recognized and played with the embedded YouTube player. Other sharing pages (for example, a private Google Drive page) need a consumer-provided resolver because the package cannot access the consumer’s credentials or infer every host’s download rules:
548
+
549
+ ```tsx
550
+ <CineCrewPlayer
551
+ source={{ uri: driveShareUrl, title: 'My video' }}
552
+ resolveSource={async (source, { platform }) => {
553
+ const playableUrl = await myDriveService.getPlayableUrl(source.uri, platform);
554
+ return { ...source, uri: playableUrl };
555
+ }}
556
+ />
557
+ ```
558
+
559
+ The web browser still enforces its own media-format and origin policies. The player reports engine errors through `onError`; the consuming application decides how to resolve or present them.
560
+
561
+ ## License and attribution
562
+
563
+ The player package is MIT-licensed. The native VLC module is an adapted upstream project and includes its license and notices. MPEG-TS playback uses the bundled patched `mpegts.js` distribution, retaining its Apache-2.0 license. See [`NOTICE`](NOTICE) and the included dependency licenses for details.
564
+
565
+ ## Development
566
+
567
+ ```sh
568
+ npm install
569
+ npm run check:types
570
+ npm test
571
+ npm pack --dry-run
572
+ ```
573
+
574
+ The native VLC source and its Android/iOS autolinking configuration are included inside the `@cinecrew/cinecrew-player` package. The repository publishes only this player package; the adapter is not a separate npm package.