From 417bd7a586aaf8729e79e7f6ae4ab2fa60118eba Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Wed, 3 Apr 2024 22:19:22 +0200 Subject: [PATCH 1/3] fix(ts): onPlaybackRateChangeData was not correctly typed --- examples/basic/src/VideoPlayer.tsx | 12 ++++++++++++ src/specs/VideoNativeComponent.ts | 4 ++-- src/types/events.ts | 4 ++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/basic/src/VideoPlayer.tsx b/examples/basic/src/VideoPlayer.tsx index e719279dbe..98e1e17f02 100644 --- a/examples/basic/src/VideoPlayer.tsx +++ b/examples/basic/src/VideoPlayer.tsx @@ -36,6 +36,8 @@ import Video, { OnTextTrackDataChangedData, TextTrackType, ISO639_1, + OnPlaybackStateChangedData, + OnPlaybackRateChangeData, } from 'react-native-video'; import ToggleControl from './ToggleControl'; import MultiValueControl, { @@ -335,6 +337,14 @@ class VideoPlayer extends Component { this.channelUp(); }; + onPlaybackRateChange = (data: OnPlaybackRateChangeData) => { + console.log('onPlaybackRateChange', data); + } + + onPlaybackStateChanged = (data: OnPlaybackStateChangedData) => { + console.log('onPlaybackStateChanged', data); + } + toggleFullscreen() { this.setState({fullscreen: !this.state.fullscreen}); } @@ -805,6 +815,8 @@ class VideoPlayer extends Component { selectedAudioTrack={this.state.selectedAudioTrack} playInBackground={false} preventsDisplaySleepDuringVideoPlayback={true} + onPlaybackRateChange={this.onPlaybackRateChange} + onPlaybackStateChanged={this.onPlaybackStateChanged} /> ); diff --git a/src/specs/VideoNativeComponent.ts b/src/specs/VideoNativeComponent.ts index 11752957c7..8f8d09a12d 100644 --- a/src/specs/VideoNativeComponent.ts +++ b/src/specs/VideoNativeComponent.ts @@ -218,7 +218,7 @@ export type OnVideoTracksData = Readonly<{ }[]; }>; -export type OnPlaybackData = Readonly<{ +export type OnPlaybackRateChangeData = Readonly<{ playbackRate: Float; }>; @@ -328,7 +328,7 @@ export interface VideoNativeProps extends ViewProps { onVideoFullscreenPlayerWillDismiss?: DirectEventHandler<{}>; // ios, android onVideoFullscreenPlayerDidDismiss?: DirectEventHandler<{}>; // ios, android onReadyForDisplay?: DirectEventHandler<{}>; - onPlaybackRateChange?: DirectEventHandler; // all + onPlaybackRateChange?: DirectEventHandler; // all onVolumeChange?: DirectEventHandler; // android, ios onVideoExternalPlaybackChange?: DirectEventHandler; onGetLicense?: DirectEventHandler; diff --git a/src/types/events.ts b/src/types/events.ts index 4f9e92380b..c97cd0862b 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -7,7 +7,7 @@ import type { OnExternalPlaybackChangeData, OnLoadStartData, OnPictureInPictureStatusChangedData, - OnPlaybackData, + OnPlaybackRateChangeData, OnPlaybackStateChangedData, OnProgressData, OnSeekData, @@ -239,7 +239,7 @@ export interface ReactVideoEvents { onPictureInPictureStatusChanged?: ( e: OnPictureInPictureStatusChangedData, ) => void; //iOS - onPlaybackRateChange?: (e: OnPlaybackData) => void; //All + onPlaybackRateChange?: (e: OnPlaybackRateChangeData) => void; //All onVolumeChange?: (e: OnVolumeChangeData) => void; //Android, iOS onProgress?: (e: OnProgressData) => void; //All onReadyForDisplay?: () => void; //Android, iOS From 52b8ec197aa7aeee19fcf846e2cd4418bbd07356 Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Sat, 6 Apr 2024 14:22:01 +0200 Subject: [PATCH 2/3] fix: ensure tracks are well displayed in the sample --- examples/basic/src/VideoPlayer.tsx | 29 +++++++++-- ios/Video/Features/RCTPlayerOperations.swift | 51 -------------------- ios/Video/RCTVideo.swift | 2 +- 3 files changed, 27 insertions(+), 55 deletions(-) diff --git a/examples/basic/src/VideoPlayer.tsx b/examples/basic/src/VideoPlayer.tsx index 98e1e17f02..0d53b10bd6 100644 --- a/examples/basic/src/VideoPlayer.tsx +++ b/examples/basic/src/VideoPlayer.tsx @@ -706,10 +706,11 @@ class VideoPlayer extends Component { AudioTrack {this.state.audioTracks?.length <= 0 ? ( - empty + empty ) : ( { console.log('on audio value change ' + itemValue); @@ -736,10 +737,11 @@ class VideoPlayer extends Component { )} TextTrack {this.state.textTracks?.length <= 0 ? ( - empty + empty ) : ( { console.log('on value change ' + itemValue); @@ -929,6 +931,13 @@ const styles = StyleSheet.create({ paddingRight: 2, lineHeight: 12, }, + pickerContainer: { + width: 100, + alignSelf: 'center', + color: 'white', + borderWidth: 1, + borderColor: 'red', + }, IndicatorStyle: { flex: 1, justifyContent: 'center', @@ -966,10 +975,24 @@ const styles = StyleSheet.create({ width: 12, }, picker: { - color: 'white', flex: 1, flexDirection: 'row', justifyContent: 'center', + width: 100, + height: 40, + }, + pickerItem: { + color: 'white', + width: 100, + height: 40, + }, + emptyPickerItem: { + color: 'white', + marginTop: 20, + marginLeft: 20, + flex: 1, + width: 100, + height: 40, }, }); diff --git a/ios/Video/Features/RCTPlayerOperations.swift b/ios/Video/Features/RCTPlayerOperations.swift index 265ab23529..3f25515923 100644 --- a/ios/Video/Features/RCTPlayerOperations.swift +++ b/ios/Video/Features/RCTPlayerOperations.swift @@ -78,57 +78,6 @@ enum RCTPlayerOperations { } } - // UNUSED - static func setStreamingText(player: AVPlayer?, criteria: SelectedTrackCriteria?) async { - let type = criteria?.type - var mediaOption: AVMediaSelectionOption! - - guard let group = await RCTVideoAssetsUtils.getMediaSelectionGroup(asset: player?.currentItem?.asset, for: .legible) else { - return - } - - if type == "disabled" { - // Do nothing. We want to ensure option is nil - } else if (type == "language") || (type == "title") { - let value = criteria?.value as? String - for i in 0 ..< group.options.count { - let currentOption: AVMediaSelectionOption! = group.options[i] - var optionValue: String! - if type == "language" { - optionValue = currentOption.extendedLanguageTag - } else { - optionValue = currentOption.commonMetadata.map(\.value)[0] as! String - } - if value == optionValue { - mediaOption = currentOption - break - } - } - // } else if ([type isEqualToString:@"default"]) { - // option = group.defaultOption; */ - } else if type == "index" { - if let value = criteria?.value, let index = value as? Int { - if group.options.count > index { - mediaOption = group.options[index] - } - } - } else { // default. invalid type or "system" - #if os(tvOS) - // Do noting. Fix for tvOS native audio menu language selector - #else - await player?.currentItem?.selectMediaOptionAutomatically(in: group) - return - #endif - } - - #if os(tvOS) - // Do noting. Fix for tvOS native audio menu language selector - #else - // If a match isn't found, option will be nil and text tracks will be disabled - await player?.currentItem?.select(mediaOption, in: group) - #endif - } - static func setMediaSelectionTrackForCharacteristic(player: AVPlayer?, characteristic: AVMediaCharacteristic, criteria: SelectedTrackCriteria?) async { let type = criteria?.type var mediaOption: AVMediaSelectionOption! diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index cb22e870f0..daa2bcb8c9 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -1471,7 +1471,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH let audioTracks = await RCTVideoUtils.getAudioTrackInfo(self._player) let textTracks = await RCTVideoUtils.getTextTrackInfo(self._player) - self.onTextTracks?(["textTracks": textTracks]) + self.onTextTracks?(["textTracks": self._textTracks?.compactMap { $0.json } ?? textTracks.compactMap(\.json)]) self.onAudioTracks?(["audioTracks": audioTracks]) } } From 0fefebb36f728aa7d4cbc684afa0af41e6860fb3 Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Mon, 29 Apr 2024 22:23:21 +0200 Subject: [PATCH 3/3] fix: avoid crash when setting invalid selected track or index 0 --- src/Video.tsx | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Video.tsx b/src/Video.tsx index 531d50f73b..cc01733890 100644 --- a/src/Video.tsx +++ b/src/Video.tsx @@ -193,13 +193,14 @@ const Video = forwardRef( if (!selectedTextTrack) { return; } - const value = selectedTextTrack.value - ? `${selectedTextTrack.value}` - : undefined; - + const type = typeof selectedTextTrack.value; + if (type !== 'number' && type !== 'string') { + console.log('invalid type provided to selectedTextTrack'); + return; + } return { type: selectedTextTrack?.type, - value, + value: `${selectedTextTrack.value}`, }; }, [selectedTextTrack]); @@ -207,13 +208,15 @@ const Video = forwardRef( if (!selectedAudioTrack) { return; } - const value = selectedAudioTrack.value - ? `${selectedAudioTrack.value}` - : undefined; + const type = typeof selectedAudioTrack.value; + if (type !== 'number' && type !== 'string') { + console.log('invalid type provided to selectedAudioTrack'); + return; + } return { type: selectedAudioTrack?.type, - value, + value: `${selectedAudioTrack.value}`, }; }, [selectedAudioTrack]);