react-native-alpha-video 0.0.0-stage → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +908 -2
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/android/av1/build.gradle +67 -0
- package/android/av1/consumer-rules.pro +4 -0
- package/android/av1/src/main/cpp/Av1Codec_jni.cpp +8 -0
- package/android/av1/src/main/cpp/CMakeLists.txt +34 -0
- package/android/av1/src/main/java/dev/mediacache/alphavideo/av1/Av1Codec.java +21 -0
- package/android/build.gradle +90 -0
- package/android/consumer-rules.pro +2 -0
- package/android/gradle.properties +1 -0
- package/android/publish.gradle +82 -0
- package/android/settings.gradle +5 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/CMakeLists.txt +59 -0
- package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoCodecs.java +73 -0
- package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoView.java +1982 -0
- package/android/src/main/java/dev/mediacache/alphavideo/BufferedDualStreamPlayer.java +978 -0
- package/android/src/main/java/dev/mediacache/alphavideo/Fetcher.java +37 -0
- package/android/src/main/java/dev/mediacache/alphavideo/HttpFetcher.java +156 -0
- package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecColor.java +47 -0
- package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecDecoders.java +135 -0
- package/android/src/main/java/dev/mediacache/alphavideo/RangeSourceLink.java +54 -0
- package/android/src/main/java/dev/mediacache/alphavideo/SourceReader.java +174 -0
- package/android/src/main/java/dev/mediacache/alphavideo/SurfaceTextureVideoDecoder.java +802 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMAlphaPlayerNative.java +95 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMFrame.java +54 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMSource.java +160 -0
- package/android/src/rangesource/java/dev/mediacache/alphavideo/AppDataSource.java +50 -0
- package/android/vpx/build.gradle +67 -0
- package/android/vpx/consumer-rules.pro +4 -0
- package/android/vpx/src/main/cpp/CMakeLists.txt +34 -0
- package/android/vpx/src/main/cpp/VpxCodec_jni.cpp +8 -0
- package/android/vpx/src/main/java/dev/mediacache/alphavideo/vpx/VpxCodec.java +21 -0
- package/codecs/av1/Dav1dDecoderPlugin.cpp +157 -0
- package/codecs/av1/Dav1dDecoderPlugin.h +17 -0
- package/codecs/vpx/VpxDecoderPlugin.cpp +103 -0
- package/codecs/vpx/VpxDecoderPlugin.h +17 -0
- package/cpp/AlphaDemuxer.cpp +984 -0
- package/cpp/AlphaDemuxer.h +123 -0
- package/cpp/AlphaVideoDecoderPlugin.h +84 -0
- package/cpp/Av1SequenceHeader.cpp +175 -0
- package/cpp/Av1SequenceHeader.h +25 -0
- package/cpp/ByteSource.cpp +116 -0
- package/cpp/ByteSource.h +59 -0
- package/cpp/RangeSourceClient.h +40 -0
- package/cpp/VideoDecoder.cpp +157 -0
- package/cpp/VideoDecoder.h +83 -0
- package/cpp/WebMAlphaPlayer.cpp +1666 -0
- package/cpp/WebMAlphaPlayer.h +389 -0
- package/cpp/WebMAlphaPlayer_jni.cpp +1380 -0
- package/cpp/YuvToRgb.cpp +39 -0
- package/cpp/YuvToRgb.h +40 -0
- package/ios/Sources/AlphaVideo/AlphaVideoCodecs.mm +63 -0
- package/ios/Sources/AlphaVideo/AlphaVideoInternal.h +70 -0
- package/ios/Sources/AlphaVideo/AlphaVideoPlayer.mm +994 -0
- package/ios/Sources/AlphaVideo/AlphaVideoSource.mm +476 -0
- package/ios/Sources/AlphaVideo/AlphaVideoView.mm +374 -0
- package/ios/Sources/AlphaVideo/include/AlphaVideo.h +303 -0
- package/ios/Sources/AlphaVideoAV1/AlphaVideoAV1Codec.mm +16 -0
- package/ios/Sources/AlphaVideoAV1/include/AlphaVideoAV1.h +18 -0
- package/ios/Sources/AlphaVideoVPX/AlphaVideoVPXCodec.mm +16 -0
- package/ios/Sources/AlphaVideoVPX/include/AlphaVideoVPX.h +17 -0
- package/lib/commonjs/AlphaVideoView.js +187 -0
- package/lib/commonjs/AlphaVideoView.js.map +1 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.js +47 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.js.map +1 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.web.js +11 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.web.js.map +1 -0
- package/lib/commonjs/NativeAlphaVideoModule.js +10 -0
- package/lib/commonjs/NativeAlphaVideoModule.js.map +1 -0
- package/lib/commonjs/NativeAlphaVideoModule.web.js +9 -0
- package/lib/commonjs/NativeAlphaVideoModule.web.js.map +1 -0
- package/lib/commonjs/WebPlayer.js +12 -0
- package/lib/commonjs/WebPlayer.js.map +1 -0
- package/lib/commonjs/WebPlayer.web.js +115 -0
- package/lib/commonjs/WebPlayer.web.js.map +1 -0
- package/lib/commonjs/index.js +124 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/AlphaVideoView.js +187 -0
- package/lib/module/AlphaVideoView.js.map +1 -0
- package/lib/module/AlphaVideoViewNativeComponent.js +47 -0
- package/lib/module/AlphaVideoViewNativeComponent.js.map +1 -0
- package/lib/module/AlphaVideoViewNativeComponent.web.js +11 -0
- package/lib/module/AlphaVideoViewNativeComponent.web.js.map +1 -0
- package/lib/module/NativeAlphaVideoModule.js +10 -0
- package/lib/module/NativeAlphaVideoModule.js.map +1 -0
- package/lib/module/NativeAlphaVideoModule.web.js +9 -0
- package/lib/module/NativeAlphaVideoModule.web.js.map +1 -0
- package/lib/module/WebPlayer.js +12 -0
- package/lib/module/WebPlayer.js.map +1 -0
- package/lib/module/WebPlayer.web.js +115 -0
- package/lib/module/WebPlayer.web.js.map +1 -0
- package/lib/module/index.js +124 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoView.d.ts +189 -0
- package/lib/typescript/react-native/src/AlphaVideoView.d.ts.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts +109 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts +5 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts +21 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts.map +1 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts +3 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/WebPlayer.d.ts +3 -0
- package/lib/typescript/react-native/src/WebPlayer.d.ts.map +1 -0
- package/lib/typescript/react-native/src/WebPlayer.web.d.ts +9 -0
- package/lib/typescript/react-native/src/WebPlayer.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/index.d.ts +77 -0
- package/lib/typescript/react-native/src/index.d.ts.map +1 -0
- package/licenses/dav1d-COPYING.txt +23 -0
- package/licenses/libvpx-LICENSE.txt +31 -0
- package/licenses/libvpx-PATENTS.txt +23 -0
- package/licenses/libwebm-LICENSE.txt +30 -0
- package/licenses/libwebm-PATENTS.txt +23 -0
- package/package.json +152 -4
- package/prebuilt/android/arm64-v8a/lib/libdav1d.a +0 -0
- package/prebuilt/android/arm64-v8a/lib/libvpx.a +0 -0
- package/prebuilt/android/armeabi-v7a/lib/libdav1d.a +0 -0
- package/prebuilt/android/armeabi-v7a/lib/libvpx.a +0 -0
- package/prebuilt/android/x86_64/lib/libdav1d.a +0 -0
- package/prebuilt/android/x86_64/lib/libvpx.a +0 -0
- package/prebuilt/include/dav1d/common.h +94 -0
- package/prebuilt/include/dav1d/data.h +117 -0
- package/prebuilt/include/dav1d/dav1d.h +329 -0
- package/prebuilt/include/dav1d/headers.h +440 -0
- package/prebuilt/include/dav1d/picture.h +157 -0
- package/prebuilt/include/dav1d/version.h +50 -0
- package/prebuilt/include/vpx/vp8.h +136 -0
- package/prebuilt/include/vpx/vp8dx.h +228 -0
- package/prebuilt/include/vpx/vpx_codec.h +475 -0
- package/prebuilt/include/vpx/vpx_decoder.h +365 -0
- package/prebuilt/include/vpx/vpx_frame_buffer.h +83 -0
- package/prebuilt/include/vpx/vpx_image.h +209 -0
- package/prebuilt/include/vpx/vpx_integer.h +40 -0
- package/prebuilt/ios/lib/libdav1d.a +0 -0
- package/prebuilt/ios/lib/libvpx.a +0 -0
- package/prebuilt/ios-simulator/include/dav1d/common.h +94 -0
- package/prebuilt/ios-simulator/include/dav1d/data.h +117 -0
- package/prebuilt/ios-simulator/include/dav1d/dav1d.h +329 -0
- package/prebuilt/ios-simulator/include/dav1d/headers.h +440 -0
- package/prebuilt/ios-simulator/include/dav1d/picture.h +157 -0
- package/prebuilt/ios-simulator/include/dav1d/version.h +50 -0
- package/prebuilt/ios-simulator/include/vpx/vp8.h +136 -0
- package/prebuilt/ios-simulator/include/vpx/vp8dx.h +228 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_codec.h +475 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_decoder.h +365 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_frame_buffer.h +83 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_image.h +209 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_integer.h +40 -0
- package/prebuilt/ios-simulator/lib/libdav1d.a +0 -0
- package/prebuilt/ios-simulator/lib/libvpx.a +0 -0
- package/react-native/android/CMakeLists.txt +14 -0
- package/react-native/android/build.gradle +113 -0
- package/react-native/android/src/main/AndroidManifest.xml +1 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModule.java +102 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoPackage.java +50 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManager.java +317 -0
- package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +10 -0
- package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +23 -0
- package/react-native/android/src/norangesource/java/dev/mediacache/alphavideo/AppDataSource.java +15 -0
- package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +30 -0
- package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +61 -0
- package/react-native/ios/RNAlphaVideoViewComponentView.mm +173 -0
- package/react-native/ios/RNAlphaVideoViewManager.mm +147 -0
- package/react-native/src/AlphaVideoView.tsx +329 -0
- package/react-native/src/AlphaVideoViewNativeComponent.ts +132 -0
- package/react-native/src/AlphaVideoViewNativeComponent.web.ts +5 -0
- package/react-native/src/NativeAlphaVideoModule.ts +22 -0
- package/react-native/src/NativeAlphaVideoModule.web.ts +2 -0
- package/react-native/src/WebPlayer.tsx +7 -0
- package/react-native/src/WebPlayer.web.tsx +87 -0
- package/react-native/src/index.tsx +144 -0
- package/react-native-alpha-video.podspec +99 -0
- package/react-native.config.js +12 -0
- package/scripts/build_codecs_android.sh +246 -0
- package/scripts/build_codecs_ios.sh +31 -0
- package/scripts/build_codecs_ios_device.sh +210 -0
- package/scripts/build_codecs_ios_simulator.sh +256 -0
- package/scripts/build_wasm.sh +230 -0
- package/scripts/build_xcframework.sh +49 -0
- package/scripts/fetch-prebuilt.sh +48 -0
- package/scripts/package_release.sh +107 -0
- package/scripts/publish-android.sh +85 -0
- package/scripts/vendor_range_source.sh +47 -0
- package/third_party/libwebm/AUTHORS.TXT +5 -0
- package/third_party/libwebm/LICENSE.TXT +30 -0
- package/third_party/libwebm/PATENTS.TXT +23 -0
- package/third_party/libwebm/README.md +7 -0
- package/third_party/libwebm/webm_parser/include/webm/buffer_reader.h +138 -0
- package/third_party/libwebm/webm_parser/include/webm/callback.h +363 -0
- package/third_party/libwebm/webm_parser/include/webm/dom_types.h +1781 -0
- package/third_party/libwebm/webm_parser/include/webm/element.h +208 -0
- package/third_party/libwebm/webm_parser/include/webm/file_reader.h +103 -0
- package/third_party/libwebm/webm_parser/include/webm/id.h +1085 -0
- package/third_party/libwebm/webm_parser/include/webm/istream_reader.h +99 -0
- package/third_party/libwebm/webm_parser/include/webm/reader.h +94 -0
- package/third_party/libwebm/webm_parser/include/webm/status.h +166 -0
- package/third_party/libwebm/webm_parser/include/webm/webm_parser.h +133 -0
- package/third_party/libwebm/webm_parser/src/ancestory.cc +334 -0
- package/third_party/libwebm/webm_parser/src/ancestory.h +83 -0
- package/third_party/libwebm/webm_parser/src/audio_parser.h +84 -0
- package/third_party/libwebm/webm_parser/src/bit_utils.cc +26 -0
- package/third_party/libwebm/webm_parser/src/bit_utils.h +24 -0
- package/third_party/libwebm/webm_parser/src/block_additions_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/block_group_parser.h +71 -0
- package/third_party/libwebm/webm_parser/src/block_header_parser.cc +76 -0
- package/third_party/libwebm/webm_parser/src/block_header_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/block_more_parser.h +32 -0
- package/third_party/libwebm/webm_parser/src/block_parser.cc +285 -0
- package/third_party/libwebm/webm_parser/src/block_parser.h +126 -0
- package/third_party/libwebm/webm_parser/src/bool_parser.h +95 -0
- package/third_party/libwebm/webm_parser/src/buffer_reader.cc +110 -0
- package/third_party/libwebm/webm_parser/src/byte_parser.h +144 -0
- package/third_party/libwebm/webm_parser/src/callback.cc +155 -0
- package/third_party/libwebm/webm_parser/src/chapter_atom_parser.h +42 -0
- package/third_party/libwebm/webm_parser/src/chapter_display_parser.h +34 -0
- package/third_party/libwebm/webm_parser/src/chapters_parser.h +28 -0
- package/third_party/libwebm/webm_parser/src/cluster_parser.h +48 -0
- package/third_party/libwebm/webm_parser/src/colour_parser.h +55 -0
- package/third_party/libwebm/webm_parser/src/content_enc_aes_settings_parser.h +32 -0
- package/third_party/libwebm/webm_parser/src/content_encoding_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/content_encodings_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/content_encryption_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/cue_point_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/cue_track_positions_parser.h +39 -0
- package/third_party/libwebm/webm_parser/src/cues_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/date_parser.cc +72 -0
- package/third_party/libwebm/webm_parser/src/date_parser.h +64 -0
- package/third_party/libwebm/webm_parser/src/ebml_parser.h +48 -0
- package/third_party/libwebm/webm_parser/src/edition_entry_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/element_parser.h +102 -0
- package/third_party/libwebm/webm_parser/src/file_reader.cc +142 -0
- package/third_party/libwebm/webm_parser/src/float_parser.cc +77 -0
- package/third_party/libwebm/webm_parser/src/float_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/id_element_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/id_element_parser.h +56 -0
- package/third_party/libwebm/webm_parser/src/id_parser.cc +75 -0
- package/third_party/libwebm/webm_parser/src/id_parser.h +45 -0
- package/third_party/libwebm/webm_parser/src/info_parser.h +44 -0
- package/third_party/libwebm/webm_parser/src/int_parser.h +121 -0
- package/third_party/libwebm/webm_parser/src/istream_reader.cc +133 -0
- package/third_party/libwebm/webm_parser/src/master_parser.cc +298 -0
- package/third_party/libwebm/webm_parser/src/master_parser.h +230 -0
- package/third_party/libwebm/webm_parser/src/master_value_parser.h +533 -0
- package/third_party/libwebm/webm_parser/src/mastering_metadata_parser.h +57 -0
- package/third_party/libwebm/webm_parser/src/parser.h +34 -0
- package/third_party/libwebm/webm_parser/src/parser_utils.cc +34 -0
- package/third_party/libwebm/webm_parser/src/parser_utils.h +64 -0
- package/third_party/libwebm/webm_parser/src/projection_parser.h +40 -0
- package/third_party/libwebm/webm_parser/src/recursive_parser.h +93 -0
- package/third_party/libwebm/webm_parser/src/seek_head_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/seek_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/segment_parser.cc +86 -0
- package/third_party/libwebm/webm_parser/src/segment_parser.h +53 -0
- package/third_party/libwebm/webm_parser/src/simple_tag_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/size_parser.cc +56 -0
- package/third_party/libwebm/webm_parser/src/size_parser.h +43 -0
- package/third_party/libwebm/webm_parser/src/skip_callback.h +63 -0
- package/third_party/libwebm/webm_parser/src/skip_parser.cc +59 -0
- package/third_party/libwebm/webm_parser/src/skip_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/slices_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/tag_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/tags_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/targets_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/time_slice_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/track_entry_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/tracks_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/unknown_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/unknown_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/var_int_parser.cc +71 -0
- package/third_party/libwebm/webm_parser/src/var_int_parser.h +56 -0
- package/third_party/libwebm/webm_parser/src/video_parser.h +122 -0
- package/third_party/libwebm/webm_parser/src/virtual_block_parser.cc +72 -0
- package/third_party/libwebm/webm_parser/src/virtual_block_parser.h +69 -0
- package/third_party/libwebm/webm_parser/src/void_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/void_parser.h +41 -0
- package/third_party/libwebm/webm_parser/src/webm_parser.cc +282 -0
- package/third_party/range-source/LICENSE +21 -0
- package/third_party/range-source/README.md +8 -0
- package/third_party/range-source/include/range_source.h +395 -0
- package/third_party/range-source/include/range_source_download.h +309 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The player view, split out from the package barrel.
|
|
3
|
+
*
|
|
4
|
+
* Separate from `index.tsx` so that anything built ON the player can import it without the barrel
|
|
5
|
+
* importing that code back. A cycle through the entry point happens to work while every reference
|
|
6
|
+
* is inside a render, which makes it a trap rather than a design.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { useRef, forwardRef, useImperativeHandle, useMemo, useEffect } from 'react';
|
|
10
|
+
import {
|
|
11
|
+
Platform,
|
|
12
|
+
ViewProps,
|
|
13
|
+
StyleProp,
|
|
14
|
+
ViewStyle,
|
|
15
|
+
} from 'react-native';
|
|
16
|
+
import NativeAlphaVideoView, { Commands, type Decoder } from './AlphaVideoViewNativeComponent';
|
|
17
|
+
import { WebPlayer } from './WebPlayer';
|
|
18
|
+
import type { ByteSource } from 'alpha-video-web';
|
|
19
|
+
|
|
20
|
+
export type { Decoder, ByteSource };
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The web engine (default `'auto'`): `'browser'` (`<video>`), `'webcodecs'`, `'webcodecs-hw'`,
|
|
24
|
+
* `'webcodecs-sw'` or `'software'` (WebAssembly). `'auto'` tries them in that order and uses the
|
|
25
|
+
* first that shows the alpha; a forced engine never falls back.
|
|
26
|
+
*/
|
|
27
|
+
export type WebDecoder = 'auto' | 'browser' | 'webcodecs' | 'webcodecs-hw' | 'webcodecs-sw' | 'software';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Source types for WebM video
|
|
31
|
+
*/
|
|
32
|
+
export interface AlphaVideoSource {
|
|
33
|
+
/**
|
|
34
|
+
* https:// (read by range as it plays), file://, an absolute path, asset://relative/path
|
|
35
|
+
* (app bundle / APK assets; the site root on web), content:// (Android), or
|
|
36
|
+
* Image.resolveAssetSource(require(...)).uri. With `dataSource`, any URI that source reads.
|
|
37
|
+
*/
|
|
38
|
+
uri: string;
|
|
39
|
+
/** Names the stored copy, for URLs that change while the file doesn't (presigned URLs); same as the `cacheKey` prop */
|
|
40
|
+
cacheKey?: string;
|
|
41
|
+
/** Sent with every request for the URL, e.g. Authorization; given to a `dataSource` too */
|
|
42
|
+
headers?: Record<string, string>;
|
|
43
|
+
/**
|
|
44
|
+
* Read the file through the data source registered under this name instead of the built-in
|
|
45
|
+
* fetcher: range-source's `RangeDataSources` on Android and iOS, and range-source-web's on the
|
|
46
|
+
* web. MediaCache registers as `'mediacache'` with `cache.registerRangeDataSource()`.
|
|
47
|
+
*/
|
|
48
|
+
dataSource?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Web only: the file itself (a Blob or File), or a byte source that reads it by offset
|
|
53
|
+
* (`{ size, read(offset, length, signal) }`, the app's own fetcher or decryption). Keep the same
|
|
54
|
+
* object between renders: a new one loads again. On iOS and Android use `source.dataSource`.
|
|
55
|
+
*/
|
|
56
|
+
export type AlphaVideoWebSource = Blob | ByteSource;
|
|
57
|
+
|
|
58
|
+
/** True for `{ uri, ... }`, false for a web-only Blob or byte source. */
|
|
59
|
+
export function isUriSource(source: AlphaVideoSource | AlphaVideoWebSource | null | undefined): source is AlphaVideoSource {
|
|
60
|
+
return source != null && typeof (source as AlphaVideoSource).uri === 'string';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Where a URL's bytes are kept between plays, read back by range: `'disk'` (the cache folder;
|
|
65
|
+
* OPFS, else IndexedDB, on the web), `'memory'` (for the app's lifetime) or `'none'`. `'auto'`,
|
|
66
|
+
* the default, is `'disk'` for URLs and `'none'` for a `dataSource` and local files.
|
|
67
|
+
*/
|
|
68
|
+
export type AlphaVideoStorage = 'auto' | 'disk' | 'memory' | 'none';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Props for the AlphaVideoView component
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* Playback mode for the WebM player.
|
|
75
|
+
*/
|
|
76
|
+
export type PlaybackMode = 'preload' | 'stream' | 'streamAndPreload';
|
|
77
|
+
|
|
78
|
+
export interface AlphaVideoLoadEvent {
|
|
79
|
+
totalFrames: number;
|
|
80
|
+
width: number;
|
|
81
|
+
height: number;
|
|
82
|
+
/**
|
|
83
|
+
* The engine and decoders playing the file: `'software (libvpx)'`, `'software (dav1d)'` (AV1),
|
|
84
|
+
* `'mediacodec-hw (c2.qti.vp9.decoder)'`, `'mediacodec-sw (...)'`, `'mediacodec (hardware, software)'`
|
|
85
|
+
* for one of each. On the web: `'browser'`, `'webcodecs (vp09.00.41.08)'` (with the alpha track's
|
|
86
|
+
* codec when it differs), `'software (vp9)'`, `'software (vp9, 4+2 threads)'` or `'software (dav1d)'`.
|
|
87
|
+
*/
|
|
88
|
+
decoder: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface AlphaVideoViewProps extends ViewProps {
|
|
92
|
+
/** Video source URL or path; on the web also a Blob or byte source ({@link AlphaVideoWebSource}) */
|
|
93
|
+
source: AlphaVideoSource | AlphaVideoWebSource;
|
|
94
|
+
/** Auto-play video when loaded (default: true) */
|
|
95
|
+
autoPlay?: boolean;
|
|
96
|
+
/** Loop video playback (default: true) */
|
|
97
|
+
loop?: boolean;
|
|
98
|
+
/** Pause video playback (default: false) */
|
|
99
|
+
paused?: boolean;
|
|
100
|
+
/** Playback speed multiplier (default: 1.0) */
|
|
101
|
+
playbackSpeed?: number;
|
|
102
|
+
/**
|
|
103
|
+
* Names the stored copy instead of the URL, for URLs that change while the file doesn't
|
|
104
|
+
* (presigned URLs). `source.cacheKey` wins over it.
|
|
105
|
+
*/
|
|
106
|
+
cacheKey?: string;
|
|
107
|
+
|
|
108
|
+
/** See {@link AlphaVideoStorage}. */
|
|
109
|
+
storage?: AlphaVideoStorage;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Cap on the bytes this player stores across every clip, evicting the least recently played
|
|
113
|
+
* (default 512 MB).
|
|
114
|
+
*/
|
|
115
|
+
maxStorageBytes?: number;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Playback mode for the player.
|
|
119
|
+
* - 'stream' (default): Decode frames on-demand with a sliding window cache.
|
|
120
|
+
* - 'preload': Decode all frames upfront before playback starts.
|
|
121
|
+
* - 'streamAndPreload': Start playing immediately while decoding in background.
|
|
122
|
+
*
|
|
123
|
+
* Applies to the software decoders only: a file MediaCodec plays on Android (see `decoder`) decodes as it is read.
|
|
124
|
+
*/
|
|
125
|
+
mode?: PlaybackMode;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Android: the decoder for files with colour and alpha as separate VP8/VP9/AV1 bitstreams
|
|
129
|
+
* (default `'auto'`; see {@link Decoder}). `onLoad` reports the one used. iOS always uses
|
|
130
|
+
* the C++ core; the web has `webDecoder`.
|
|
131
|
+
*/
|
|
132
|
+
decoder?: Decoder;
|
|
133
|
+
|
|
134
|
+
/** Web: the engine (default `'auto'`; see {@link WebDecoder}). `onLoad` reports the one used. */
|
|
135
|
+
webDecoder?: WebDecoder;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @deprecated Use `mode` instead.
|
|
139
|
+
* Enable streaming mode for low RAM usage.
|
|
140
|
+
* When true: decode on-demand with sliding window cache (good for long videos like YouTube)
|
|
141
|
+
* When false: preload all frames to RAM (good for short loops like glow effects)
|
|
142
|
+
* When omitted, `mode` (default 'stream') applies.
|
|
143
|
+
*/
|
|
144
|
+
stream?: boolean;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Number of frames decoded ahead of the shown one when streaming. Stream mode keeps only
|
|
148
|
+
* these, so this is also its memory: more absorbs slow decodes, fewer uses less memory.
|
|
149
|
+
* Default: 8 frames (about 0.27 seconds at 30fps)
|
|
150
|
+
* Only used when mode='stream'
|
|
151
|
+
*/
|
|
152
|
+
streamPrefetchAhead?: number;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Enable global decode queue for non-stream mode.
|
|
156
|
+
* When true (default): decoding is serialized across all players, preventing CPU saturation
|
|
157
|
+
* When false: each player decodes independently (can freeze with many)
|
|
158
|
+
* Has no effect when mode='stream'.
|
|
159
|
+
*/
|
|
160
|
+
useDecodeQueue?: boolean;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Enable verbose per-frame logging for debugging.
|
|
164
|
+
* When true: logs every frame queue, release, and render event.
|
|
165
|
+
* When false (default): only logs lifecycle events and periodic performance stats.
|
|
166
|
+
*/
|
|
167
|
+
verbose?: boolean;
|
|
168
|
+
|
|
169
|
+
/** Container style */
|
|
170
|
+
style?: StyleProp<ViewStyle>;
|
|
171
|
+
/** Callback when video loads */
|
|
172
|
+
onLoad?: (event: AlphaVideoLoadEvent) => void;
|
|
173
|
+
/**
|
|
174
|
+
* Callback when error occurs. On the web, `code` tells the errors apart: `'LOAD_FAILED'`,
|
|
175
|
+
* `'UNSUPPORTED_FILE'`, `'NO_ALPHA_PATH'`, `'DECODER_UNSUPPORTED'`, `'DECODE_FAILED'`, `'WEBGL_UNSUPPORTED'`
|
|
176
|
+
* or `'NEEDS_SERVICE_WORKER'`.
|
|
177
|
+
* On iOS and Android, `'NO_DECODER'` is a file needing a codec left out of the build (see the
|
|
178
|
+
* app's `package.json` `"react-native-alpha-video": { "codecs": [...] }`); other errors have none.
|
|
179
|
+
*/
|
|
180
|
+
onError?: (event: { error: string; code?: string }) => void;
|
|
181
|
+
/** Callback when video ends */
|
|
182
|
+
onEnd?: (event: {}) => void;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Methods exposed by the AlphaVideoView ref
|
|
187
|
+
*/
|
|
188
|
+
export interface AlphaVideoViewRef {
|
|
189
|
+
play: () => void;
|
|
190
|
+
pause: () => void;
|
|
191
|
+
stop: () => void;
|
|
192
|
+
/** Shows that frame (clamped to the clip) and keeps playing or stays paused. */
|
|
193
|
+
seekToFrame: (frame: number) => void;
|
|
194
|
+
/** Seeks to the frame showing at that time, in seconds. */
|
|
195
|
+
seekToTime: (seconds: number) => void;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Native component for iOS and Android, from the codegen spec: a Fabric component on the new
|
|
199
|
+
// architecture, a view manager on the old one.
|
|
200
|
+
const NativeAlphaVideoViewOrNull = Platform.OS !== 'web' ? NativeAlphaVideoView : null;
|
|
201
|
+
|
|
202
|
+
/** `mode` wins over the deprecated `stream`. */
|
|
203
|
+
function resolveMode(mode: PlaybackMode | undefined, stream: boolean | undefined): PlaybackMode | undefined {
|
|
204
|
+
if (mode) return mode;
|
|
205
|
+
if (stream == null) return undefined;
|
|
206
|
+
return stream ? 'stream' : 'preload';
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Native implementation for iOS and Android
|
|
211
|
+
*/
|
|
212
|
+
const NativePlayer = forwardRef<AlphaVideoViewRef, AlphaVideoViewProps>(
|
|
213
|
+
(props, ref) => {
|
|
214
|
+
const nativeRef = useRef<React.ElementRef<typeof NativeAlphaVideoView>>(null);
|
|
215
|
+
|
|
216
|
+
const withView = (command: (view: React.ElementRef<typeof NativeAlphaVideoView>) => void) => {
|
|
217
|
+
if (nativeRef.current) command(nativeRef.current);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
useImperativeHandle(ref, () => ({
|
|
221
|
+
play: () => withView(view => Commands.play(view)),
|
|
222
|
+
pause: () => withView(view => Commands.pause(view)),
|
|
223
|
+
stop: () => withView(view => Commands.stop(view)),
|
|
224
|
+
seekToFrame: (frame: number) => withView(view => Commands.seekToFrame(view, frame)),
|
|
225
|
+
seekToTime: (seconds: number) => withView(view => Commands.seekToTime(view, seconds)),
|
|
226
|
+
}));
|
|
227
|
+
|
|
228
|
+
const uriSource = isUriSource(props.source) ? props.source : undefined;
|
|
229
|
+
const { uri, headers, dataSource } = uriSource ?? {};
|
|
230
|
+
const headersKey = headers ? JSON.stringify(headers) : '';
|
|
231
|
+
// Rebuilt only when a value changes, so a new source object each render doesn't reload
|
|
232
|
+
const nativeSource = useMemo(
|
|
233
|
+
() => ({
|
|
234
|
+
uri,
|
|
235
|
+
headers: headers ? ([] as string[]).concat(...Object.entries(headers)) : undefined,
|
|
236
|
+
dataSource,
|
|
237
|
+
}),
|
|
238
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
239
|
+
[uri, headersKey, dataSource],
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const webOnlySource = props.source != null && !uriSource;
|
|
243
|
+
useEffect(() => {
|
|
244
|
+
if (webOnlySource) {
|
|
245
|
+
props.onError?.({ error: 'A Blob or byte source plays only on the web; on iOS and Android, use source.dataSource' });
|
|
246
|
+
}
|
|
247
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
248
|
+
}, [webOnlySource, props.source]);
|
|
249
|
+
|
|
250
|
+
if (!NativeAlphaVideoViewOrNull) {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Wrap native event handlers to extract nativeEvent data
|
|
255
|
+
const handleNativeLoad = props.onLoad
|
|
256
|
+
? (event: { nativeEvent: AlphaVideoLoadEvent }) => {
|
|
257
|
+
props.onLoad?.(event.nativeEvent);
|
|
258
|
+
}
|
|
259
|
+
: undefined;
|
|
260
|
+
|
|
261
|
+
const handleNativeError = props.onError
|
|
262
|
+
? (event: { nativeEvent: { error: string; code?: string } }) => {
|
|
263
|
+
// The new architecture's event struct sends an absent code as ''
|
|
264
|
+
const { error, code } = event.nativeEvent;
|
|
265
|
+
props.onError?.(code ? { error, code } : { error });
|
|
266
|
+
}
|
|
267
|
+
: undefined;
|
|
268
|
+
|
|
269
|
+
const handleNativeEnd = props.onEnd
|
|
270
|
+
? (event: { nativeEvent: {} }) => {
|
|
271
|
+
props.onEnd?.(event.nativeEvent);
|
|
272
|
+
}
|
|
273
|
+
: undefined;
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<NativeAlphaVideoViewOrNull
|
|
277
|
+
ref={nativeRef}
|
|
278
|
+
source={nativeSource}
|
|
279
|
+
autoPlay={props.autoPlay}
|
|
280
|
+
loop={props.loop}
|
|
281
|
+
paused={props.paused}
|
|
282
|
+
playbackSpeed={props.playbackSpeed}
|
|
283
|
+
cacheKey={uriSource?.cacheKey || props.cacheKey}
|
|
284
|
+
storage={props.storage}
|
|
285
|
+
maxStorageBytes={props.maxStorageBytes}
|
|
286
|
+
mode={resolveMode(props.mode, props.stream)}
|
|
287
|
+
decoder={props.decoder}
|
|
288
|
+
streamPrefetchAhead={props.streamPrefetchAhead}
|
|
289
|
+
useDecodeQueue={props.useDecodeQueue}
|
|
290
|
+
verbose={props.verbose}
|
|
291
|
+
style={props.style}
|
|
292
|
+
onLoad={handleNativeLoad}
|
|
293
|
+
onError={handleNativeError}
|
|
294
|
+
onEnd={handleNativeEnd}
|
|
295
|
+
/>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
NativePlayer.displayName = 'NativePlayer';
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* AlphaVideoView - Cross-platform WebM VP8/VP9/AV1 video player with alpha transparency support
|
|
304
|
+
*
|
|
305
|
+
* Uses native C++ implementation with Metal (iOS) and OpenGL ES (Android) for optimal performance.
|
|
306
|
+
* On the web, alpha-video-web: `<video>` where the browser keeps the alpha, otherwise WebCodecs or
|
|
307
|
+
* WebAssembly decoding drawn in WebGL2.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```tsx
|
|
311
|
+
* <AlphaVideoView
|
|
312
|
+
* source={{ uri: 'https://example.com/video.webm' }}
|
|
313
|
+
* autoPlay={true}
|
|
314
|
+
* loop={true}
|
|
315
|
+
* style={{ width: 300, height: 300 }}
|
|
316
|
+
* />
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
export const AlphaVideoView = forwardRef<AlphaVideoViewRef, AlphaVideoViewProps>(
|
|
320
|
+
(props, ref) => {
|
|
321
|
+
if (Platform.OS === 'web') {
|
|
322
|
+
return <WebPlayer ref={ref} {...props} />;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return <NativePlayer ref={ref} {...props} />;
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
AlphaVideoView.displayName = 'AlphaVideoView';
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type { HostComponent, ViewProps } from 'react-native';
|
|
3
|
+
import type {
|
|
4
|
+
DirectEventHandler,
|
|
5
|
+
Double,
|
|
6
|
+
Int32,
|
|
7
|
+
WithDefault,
|
|
8
|
+
} from 'react-native/Libraries/Types/CodegenTypes';
|
|
9
|
+
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
|
|
10
|
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Playback mode for the WebM player.
|
|
14
|
+
*
|
|
15
|
+
* - `'stream'` (default): Decode frames on-demand with a sliding window cache.
|
|
16
|
+
* Best for long videos or memory-constrained devices. Frames are evicted
|
|
17
|
+
* from cache, so looping requires re-decoding.
|
|
18
|
+
*
|
|
19
|
+
* - `'preload'`: Decode all frames upfront before playback starts.
|
|
20
|
+
* Best for short loops. Zero CPU during playback, instant looping.
|
|
21
|
+
*
|
|
22
|
+
* - `'streamAndPreload'`: Start playing immediately while decoding in background.
|
|
23
|
+
* After first pass completes, all frames are cached for instant looping.
|
|
24
|
+
* Best of both worlds: fast start + smooth loops.
|
|
25
|
+
*/
|
|
26
|
+
export type PlaybackMode = 'preload' | 'stream' | 'streamAndPreload';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Decoder for files with colour and alpha as separate VP8/VP9/AV1 bitstreams (two tracks, or a
|
|
30
|
+
* standard alpha WebM's BlockAdditional). Android only; iOS always uses the C++ core and web the browser.
|
|
31
|
+
*
|
|
32
|
+
* - `'auto'` (default): MediaCodec hardware decoders that list every track's profile, else
|
|
33
|
+
* MediaCodec's software decoders, else the C++ core.
|
|
34
|
+
* - `'mediacodec'`: per track, a hardware decoder if one lists the profile and has an instance
|
|
35
|
+
* free, else a software one.
|
|
36
|
+
* - `'mediacodec-hw'` / `'mediacodec-sw'`: hardware / software decoders only, for both tracks.
|
|
37
|
+
* - `'software'`: the C++ core, with the codecs built in (libvpx for VP8 and 8-bit VP9, dav1d for 8- to
|
|
38
|
+
* 12-bit AV1).
|
|
39
|
+
*
|
|
40
|
+
* A forced engine never falls back: a file it can't play calls `onError`. One that needs a codec
|
|
41
|
+
* left out of the build reports the code `'NO_DECODER'`.
|
|
42
|
+
*/
|
|
43
|
+
export type Decoder = 'auto' | 'mediacodec' | 'mediacodec-hw' | 'mediacodec-sw' | 'software';
|
|
44
|
+
|
|
45
|
+
type LoadEvent = Readonly<{
|
|
46
|
+
totalFrames: Int32;
|
|
47
|
+
width: Int32;
|
|
48
|
+
height: Int32;
|
|
49
|
+
/** The engine and decoders playing the file, e.g. `'mediacodec-hw (c2.qti.vp9.decoder)'`. */
|
|
50
|
+
decoder: string;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
53
|
+
type ErrorEvent = Readonly<{
|
|
54
|
+
error: string;
|
|
55
|
+
/** `'NO_DECODER'` when the file needs a software decoder that isn't built in */
|
|
56
|
+
code?: string;
|
|
57
|
+
}>;
|
|
58
|
+
|
|
59
|
+
/** Android only: every frame is decoded (preload and streamAndPreload modes). */
|
|
60
|
+
type PreloadCompleteEvent = Readonly<{
|
|
61
|
+
totalFrames: Int32;
|
|
62
|
+
timeMs: Double;
|
|
63
|
+
}>;
|
|
64
|
+
|
|
65
|
+
export interface NativeProps extends ViewProps {
|
|
66
|
+
source?: Readonly<{
|
|
67
|
+
uri?: string;
|
|
68
|
+
/** Request headers as name, value, name, value... (codegen has no string maps) */
|
|
69
|
+
headers?: ReadonlyArray<string>;
|
|
70
|
+
/** A data source registered in native code under this name */
|
|
71
|
+
dataSource?: string;
|
|
72
|
+
}>;
|
|
73
|
+
autoPlay?: WithDefault<boolean, true>;
|
|
74
|
+
loop?: WithDefault<boolean, true>;
|
|
75
|
+
paused?: WithDefault<boolean, false>;
|
|
76
|
+
playbackSpeed?: WithDefault<Double, 1.0>;
|
|
77
|
+
/** What the store keeps the source under, instead of its URL */
|
|
78
|
+
cacheKey?: string;
|
|
79
|
+
/** Where a URL's or data source's bytes are kept between plays */
|
|
80
|
+
storage?: WithDefault<'auto' | 'disk' | 'memory' | 'none', 'auto'>;
|
|
81
|
+
/** The store's cap in bytes; 0 for the default (512 MB) */
|
|
82
|
+
maxStorageBytes?: WithDefault<Double, 0>;
|
|
83
|
+
|
|
84
|
+
/** See {@link PlaybackMode}. */
|
|
85
|
+
mode?: WithDefault<'preload' | 'stream' | 'streamAndPreload', 'stream'>;
|
|
86
|
+
|
|
87
|
+
/** See {@link Decoder}. */
|
|
88
|
+
decoder?: WithDefault<'auto' | 'mediacodec' | 'mediacodec-hw' | 'mediacodec-sw' | 'software', 'auto'>;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Number of frames decoded ahead of the shown one when streaming; stream mode keeps only these.
|
|
92
|
+
* Default: 8 frames (about 0.27 seconds at 30fps)
|
|
93
|
+
* Only used when mode='stream'
|
|
94
|
+
*/
|
|
95
|
+
streamPrefetchAhead?: WithDefault<Int32, 8>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Enable global decode queue for non-stream mode.
|
|
99
|
+
* When true (default): decoding is serialized across all players, preventing CPU saturation
|
|
100
|
+
* When false: each player decodes independently (can freeze with many)
|
|
101
|
+
* Has no effect when mode='stream'.
|
|
102
|
+
*/
|
|
103
|
+
useDecodeQueue?: WithDefault<boolean, true>;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Enable verbose per-frame logging for debugging.
|
|
107
|
+
* When true: logs every frame queue, release, and render event.
|
|
108
|
+
* When false (default): only logs lifecycle events and periodic performance stats.
|
|
109
|
+
*/
|
|
110
|
+
verbose?: WithDefault<boolean, false>;
|
|
111
|
+
|
|
112
|
+
onLoad?: DirectEventHandler<LoadEvent>;
|
|
113
|
+
onError?: DirectEventHandler<ErrorEvent>;
|
|
114
|
+
onEnd?: DirectEventHandler<Readonly<{}>>;
|
|
115
|
+
onPreloadComplete?: DirectEventHandler<PreloadCompleteEvent>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type NativeComponentType = HostComponent<NativeProps>;
|
|
119
|
+
|
|
120
|
+
interface NativeCommands {
|
|
121
|
+
play: (viewRef: React.ElementRef<NativeComponentType>) => void;
|
|
122
|
+
pause: (viewRef: React.ElementRef<NativeComponentType>) => void;
|
|
123
|
+
stop: (viewRef: React.ElementRef<NativeComponentType>) => void;
|
|
124
|
+
seekToFrame: (viewRef: React.ElementRef<NativeComponentType>, frame: Int32) => void;
|
|
125
|
+
seekToTime: (viewRef: React.ElementRef<NativeComponentType>, seconds: Double) => void;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
129
|
+
supportedCommands: ['play', 'pause', 'stop', 'seekToFrame', 'seekToTime'],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
export default codegenNativeComponent<NativeProps>('RNAlphaVideoView') as NativeComponentType;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The web player is a <video> element. This stub keeps the native spec's imports out of web bundles.
|
|
2
|
+
const noCommands = {};
|
|
3
|
+
// React Native's Babel codegen plugin rejects `export const Commands` unless it is codegenNativeCommands.
|
|
4
|
+
export { noCommands as Commands };
|
|
5
|
+
export default null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/** The decoder utilities. Android only: iOS has no native module, so `get` returns null there. */
|
|
5
|
+
export interface Spec extends TurboModule {
|
|
6
|
+
getDecoderInfo(): Promise<string>;
|
|
7
|
+
getMaxDecoderInstances(mimeType: string): Promise<number>;
|
|
8
|
+
getActiveDecoderCount(): Promise<number>;
|
|
9
|
+
getDecoderStatus(): Promise<{
|
|
10
|
+
maxVp9Instances: number;
|
|
11
|
+
maxAv1Instances: number;
|
|
12
|
+
vp9HardwareAvailable: boolean;
|
|
13
|
+
av1HardwareAvailable: boolean;
|
|
14
|
+
activeDecoders: number;
|
|
15
|
+
availableVp9Slots: number;
|
|
16
|
+
maxDualStreamPlayers: number;
|
|
17
|
+
canCreateMore: boolean;
|
|
18
|
+
softwareDecoders: string[];
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default TurboModuleRegistry.get<Spec>('RNAlphaVideo');
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// iOS and Android bundles get this instead of WebPlayer.web.tsx, so they never include alpha-video-web.
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import type { AlphaVideoViewProps, AlphaVideoViewRef } from './AlphaVideoView';
|
|
4
|
+
|
|
5
|
+
export const WebPlayer = forwardRef<AlphaVideoViewRef, AlphaVideoViewProps>(() => null);
|
|
6
|
+
|
|
7
|
+
WebPlayer.displayName = 'WebPlayer';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The web player: alpha-video-web, which shows the alpha in every browser. It plays in `<video>`
|
|
3
|
+
* where the browser keeps WebM alpha, otherwise through WebCodecs or WebAssembly decoding drawn
|
|
4
|
+
* in WebGL2, loading those engines only when a file needs them.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { forwardRef, useEffect, useMemo } from 'react';
|
|
8
|
+
import { View, StyleSheet } from 'react-native';
|
|
9
|
+
import { AlphaVideo } from 'alpha-video-web/react';
|
|
10
|
+
import type { ByteSource } from 'alpha-video-web';
|
|
11
|
+
import { isUriSource, type AlphaVideoViewProps, type AlphaVideoViewRef } from './AlphaVideoView';
|
|
12
|
+
|
|
13
|
+
/** asset://path names the app's bundled media; on the web it is served from the site root. */
|
|
14
|
+
function toWebUrl(uri: string): string {
|
|
15
|
+
return uri.startsWith('asset://') ? '/' + uri.slice('asset://'.length).replace(/^\/+/, '') : uri;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type DataSourceFactory = (uri: string, init?: { headers?: Record<string, string> }) => ByteSource;
|
|
19
|
+
|
|
20
|
+
/** range-source-web's `RangeDataSources`, read from its global symbol so this package needn't depend on it. */
|
|
21
|
+
function registeredDataSource(name: string): DataSourceFactory | undefined {
|
|
22
|
+
const scope = globalThis as { [key: symbol]: Map<string, DataSourceFactory> | undefined };
|
|
23
|
+
return scope[Symbol.for('range-source.dataSources')]?.get(name);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const WebPlayer = forwardRef<AlphaVideoViewRef, AlphaVideoViewProps>((props, ref) => {
|
|
27
|
+
const { source, autoPlay = true, loop = true, paused = false, playbackSpeed = 1, webDecoder = 'auto', cacheKey } = props;
|
|
28
|
+
const { storage, maxStorageBytes } = props;
|
|
29
|
+
const { style, onLoad, onError, onEnd } = props;
|
|
30
|
+
// Streamed by range from http(s) URLs and kept in the browser's storage (OPFS, else IndexedDB)
|
|
31
|
+
// by the canvas engines; <video> uses the HTTP cache. A Blob or byte source plays as it is, and
|
|
32
|
+
// a `dataSource` name plays the byte source registered under it, which keeps the bytes itself.
|
|
33
|
+
const uriSource = isUriSource(source) ? source : undefined;
|
|
34
|
+
const dataSource = uriSource?.dataSource;
|
|
35
|
+
const headersKey = JSON.stringify(uriSource?.headers ?? null);
|
|
36
|
+
const fromDataSource = useMemo(
|
|
37
|
+
() => (dataSource && uriSource?.uri ? registeredDataSource(dataSource)?.(uriSource.uri, { headers: uriSource.headers }) ?? null : null),
|
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39
|
+
[dataSource, uriSource?.uri, headersKey],
|
|
40
|
+
);
|
|
41
|
+
const src = dataSource ? fromDataSource : isUriSource(source) ? (source.uri ? toWebUrl(source.uri) : undefined) : source;
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (dataSource && uriSource?.uri && !fromDataSource) {
|
|
45
|
+
onError?.({ error: `No data source is registered on the web under "${dataSource}"` });
|
|
46
|
+
}
|
|
47
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
|
+
}, [fromDataSource, dataSource, uriSource?.uri]);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View style={[styles.container, style]}>
|
|
52
|
+
{src ? (
|
|
53
|
+
<AlphaVideo
|
|
54
|
+
ref={ref}
|
|
55
|
+
src={src}
|
|
56
|
+
autoPlay={autoPlay}
|
|
57
|
+
loop={loop}
|
|
58
|
+
paused={paused}
|
|
59
|
+
playbackSpeed={playbackSpeed}
|
|
60
|
+
decoder={webDecoder}
|
|
61
|
+
headers={dataSource ? undefined : uriSource?.headers}
|
|
62
|
+
cacheKey={
|
|
63
|
+
// As on Android and iOS, a data source's bytes are stored only when storage is set
|
|
64
|
+
dataSource && storage !== 'disk' && storage !== 'memory' ? undefined : uriSource?.cacheKey || cacheKey || (dataSource ? uriSource?.uri : undefined)
|
|
65
|
+
}
|
|
66
|
+
storage={storage === 'disk' ? 'auto' : storage}
|
|
67
|
+
maxStorageBytes={maxStorageBytes}
|
|
68
|
+
style={fill}
|
|
69
|
+
onLoad={({ totalFrames, width, height, decoder }) => onLoad?.({ totalFrames, width, height, decoder })}
|
|
70
|
+
onError={(error) => onError?.({ error: error.message, code: error.code })}
|
|
71
|
+
onEnd={() => onEnd?.({})}
|
|
72
|
+
/>
|
|
73
|
+
) : null}
|
|
74
|
+
</View>
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
WebPlayer.displayName = 'WebPlayer';
|
|
79
|
+
|
|
80
|
+
const styles = StyleSheet.create({
|
|
81
|
+
container: {
|
|
82
|
+
overflow: 'hidden',
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// A DOM style: AlphaVideo renders a <div>
|
|
87
|
+
const fill: React.CSSProperties = { width: '100%', height: '100%' };
|