From 417bd7a586aaf8729e79e7f6ae4ab2fa60118eba Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Wed, 3 Apr 2024 22:19:22 +0200 Subject: [PATCH 1/5] 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/5] 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 25a5438d7dab70e0575b240f4f408acf43c80f8b Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Thu, 2 May 2024 14:45:20 +0200 Subject: [PATCH 3/5] fix(ios): text tracks selection by index. regression due to codegen rework --- .../DataStructures/SelectedTrackCriteria.swift | 4 ++-- ios/Video/Features/RCTPlayerOperations.swift | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ios/Video/DataStructures/SelectedTrackCriteria.swift b/ios/Video/DataStructures/SelectedTrackCriteria.swift index 41d68affc4..b4217817af 100644 --- a/ios/Video/DataStructures/SelectedTrackCriteria.swift +++ b/ios/Video/DataStructures/SelectedTrackCriteria.swift @@ -1,6 +1,6 @@ struct SelectedTrackCriteria { let type: String - let value: Any? + let value: String? let json: NSDictionary? @@ -13,6 +13,6 @@ struct SelectedTrackCriteria { } self.json = json self.type = json["type"] as? String ?? "" - self.value = json["value"] + self.value = json["value"] as? String } } diff --git a/ios/Video/Features/RCTPlayerOperations.swift b/ios/Video/Features/RCTPlayerOperations.swift index 3f25515923..b09896dcd5 100644 --- a/ios/Video/Features/RCTPlayerOperations.swift +++ b/ios/Video/Features/RCTPlayerOperations.swift @@ -45,9 +45,11 @@ enum RCTPlayerOperations { } } } else if type == "index" { - if let value = criteria?.value, let index = value as? Int { - if textTracks.count > index { - selectedTrackIndex = index + if let value = criteria?.value { // check value is provided + if let indexValue: Int = Int(value as String) { // ensure value is an integer an String to Snt + if textTracks.count > indexValue { // ensure value is in group range + selectedTrackIndex = indexValue + } } } } @@ -106,9 +108,11 @@ enum RCTPlayerOperations { // } 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] + if let value = criteria?.value { // check value is provided + if let indexValue: Int = Int(value as String) { // ensure value is an integer an String to Snt + if group.options.count > indexValue { // ensure value is in group range + mediaOption = group.options[indexValue] + } } } } else { // default. invalid type or "system" From 2d181466ae31a7c38f6f88ef283941afaa95189c Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Thu, 2 May 2024 14:56:23 +0200 Subject: [PATCH 4/5] chore: make selection by index testable (need a small manual patch) --- examples/basic/src/VideoPlayer.tsx | 32 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/examples/basic/src/VideoPlayer.tsx b/examples/basic/src/VideoPlayer.tsx index 7b858627b0..c44ee37253 100644 --- a/examples/basic/src/VideoPlayer.tsx +++ b/examples/basic/src/VideoPlayer.tsx @@ -104,6 +104,9 @@ class VideoPlayer extends Component { seekerWidth = 0; + // internal usage change to index if you want to select tracks by index instead of lang + textTracksSelectionBy = 'lang'; + srcAllPlatformList = [ { description: 'local file landscape', @@ -300,7 +303,10 @@ class VideoPlayer extends Component { if (selectedTrack?.language) { this.setState({ textTracks: data.textTracks, - selectedTextTrack: { + selectedTextTrack: this.textTracksSelectionBy === 'index' ? { + type: 'index', + value: selectedTrack?.index, + }: { type: 'language', value: selectedTrack?.language, }, @@ -804,7 +810,7 @@ class VideoPlayer extends Component { console.log('on value change ' + itemValue); this.setState({ selectedTextTrack: { - type: 'language', + type: this.textTracksSelectionBy === 'index' ? 'index': 'language', value: itemValue, }, }); @@ -814,13 +820,21 @@ class VideoPlayer extends Component { if (!track) { return; } - return ( - - ); + if (this.textTracksSelectionBy === 'index') { + return ( + ); + } else { + return ( + ); + } })} )} From 62a3420798f9a7bc2da796ac844e48870d7d1ab0 Mon Sep 17 00:00:00 2001 From: Olivier Bouillet Date: Thu, 2 May 2024 15:01:34 +0200 Subject: [PATCH 5/5] chore(ios): fix linter warning --- ios/Video/Features/RCTPlayerOperations.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Video/Features/RCTPlayerOperations.swift b/ios/Video/Features/RCTPlayerOperations.swift index b09896dcd5..9c80c85f3e 100644 --- a/ios/Video/Features/RCTPlayerOperations.swift +++ b/ios/Video/Features/RCTPlayerOperations.swift @@ -46,7 +46,7 @@ enum RCTPlayerOperations { } } else if type == "index" { if let value = criteria?.value { // check value is provided - if let indexValue: Int = Int(value as String) { // ensure value is an integer an String to Snt + if let indexValue = Int(value as String) { // ensure value is an integer an String to Snt if textTracks.count > indexValue { // ensure value is in group range selectedTrackIndex = indexValue } @@ -109,7 +109,7 @@ enum RCTPlayerOperations { // option = group.defaultOption; */ } else if type == "index" { if let value = criteria?.value { // check value is provided - if let indexValue: Int = Int(value as String) { // ensure value is an integer an String to Snt + if let indexValue = Int(value as String) { // ensure value is an integer an String to Snt if group.options.count > indexValue { // ensure value is in group range mediaOption = group.options[indexValue] }