feat(tvos): add custom image metadata option for tvos and add missing types for custom metadata properties (#3280)

* fix: add typescript types for custom metadata properties
* chore: add possibility to override image metadata of video playback

---------

Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>
This commit is contained in:
Konstantin 2023-10-07 15:14:10 +02:00 committed by GitHub
parent 067adde124
commit a855284d8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 48 additions and 6 deletions

5
API.md
View File

@ -981,7 +981,7 @@ Platforms: iOS, Android
##### Overriding the metadata of a source
Provide an optional `title`, `subtitle` and/or `description` properties for the video.
Provide an optional `title`, `subtitle`, `customImageUri` and/or `description` properties for the video.
Useful when to adapt the tvOS playback experience.
Example:
@ -991,7 +991,8 @@ source={{
uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8',
title: 'Custom Title',
subtitle: 'Custom Subtitle',
description: 'Custom Description'
description: 'Custom Description',
customImageUri: 'https://pbs.twimg.com/profile_images/1498641868397191170/6qW2XkuI_400x400.png'
}}
```

View File

@ -16,6 +16,8 @@ export default function App() {
title: 'Custom Title',
subtitle: 'Custom Subtitle',
description: 'Custom Description',
customImageUri:
'https://pbs.twimg.com/profile_images/1498641868397191170/6qW2XkuI_400x400.png',
}}
style={[styles.fullScreen, StyleSheet.absoluteFillObject]}
controls

View File

@ -319,10 +319,10 @@ PODS:
- React-jsinspector (0.71.12-0)
- React-logger (0.71.12-0):
- glog
- react-native-video (6.0.0-alpha.7):
- react-native-video (6.0.0-alpha.8):
- React-Core
- react-native-video/Video (= 6.0.0-alpha.7)
- react-native-video/Video (6.0.0-alpha.7):
- react-native-video/Video (= 6.0.0-alpha.8)
- react-native-video/Video (6.0.0-alpha.8):
- PromisesSwift
- React-Core
- React-perflogger (0.71.12-0)
@ -598,7 +598,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 0c8c5e8b2171be52295f59097923babf84d1cf66
React-jsinspector: f8e6919523047a9bd1270ade75b4eca0108963b4
React-logger: 16c56636d4209cc204d06c5ba347cee21b960012
react-native-video: 4c8d6b0f82b32a3f02a9fde0287704f455b7211d
react-native-video: 86950ad481cec184d7c9420ec3bca0c27904bbcd
React-perflogger: 355109dc9d6f34e35bc35dabb32310f8ed2d29a2
React-RCTActionSheet: 9d1be4d43972f2aae4b31d9e53ffb030115fa445
React-RCTAnimation: aab7e1ecd325db67e1f2a947d85a52adf86594b7

View File

@ -12,6 +12,7 @@ struct VideoSource {
let title: String?
let subtitle: String?
let description: String?
let customImageUri: String?
let json: NSDictionary?
@ -29,6 +30,7 @@ struct VideoSource {
self.title = nil
self.subtitle = nil
self.description = nil
self.customImageUri = nil
return
}
self.json = json
@ -43,5 +45,6 @@ struct VideoSource {
self.title = json["title"] as? String
self.subtitle = json["subtitle"] as? String
self.description = json["description"] as? String
self.customImageUri = json["customImageUri"] as? String
}
}

View File

@ -330,4 +330,15 @@ enum RCTVideoUtils {
item.extendedLanguageTag = "und"
return item.copy() as! AVMetadataItem
}
static func createImageMetadataItem(imageUri: String) -> Data? {
if let uri = URL(string: imageUri),
let imgData = try? Data(contentsOf: uri),
let image = UIImage(data: imgData),
let pngData = image.pngData() {
return pngData
}
return nil
}
}

View File

@ -408,6 +408,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
mapping[.commonIdentifierDescription] = description
}
if let customImageUri = _source?.customImageUri,
let imageData = RCTVideoUtils.createImageMetadataItem(imageUri: customImageUri) {
mapping[.commonIdentifierArtwork] = imageData
}
if #available(iOS 12.2, *), !mapping.isEmpty {
playerItem.externalMetadata = RCTVideoUtils.createMetadataItems(for: mapping)
}

View File

@ -143,6 +143,10 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
requestHeaders: resolvedSource?.headers || {},
startTime: resolvedSource.startTime || 0,
endTime: resolvedSource.endTime,
title: resolvedSource.title,
subtitle: resolvedSource.subtitle,
description: resolvedSource.description,
customImageUri: resolvedSource.customImageUri,
};
}, [source]);

View File

@ -22,6 +22,10 @@ type VideoSrc = Readonly<{
requestHeaders?: Headers;
startTime?: number;
endTime?: number;
title?: string;
subtitle?: string;
description?: string;
customImageUri?: string;
}>;
export type Filter =

View File

@ -33,6 +33,10 @@ export type ReactVideoSource = Readonly<{
headers?: Headers;
startTime?: number;
endTime?: number;
title?: string;
subtitle?: string;
description?: string;
customImageUri?: string;
}>;
export type ReactVideoDrm = Readonly<{
@ -86,6 +90,13 @@ type TextTracks = {
uri: string;
}[];
type Chapters = {
title: string;
startTime: number;
endTime: number;
uri?: string;
};
export interface ReactVideoProps extends ReactVideoEvents {
source?: ReactVideoSource;
drm?: ReactVideoDrm;
@ -95,6 +106,7 @@ export interface ReactVideoProps extends ReactVideoEvents {
automaticallyWaitsToMinimizeStalling?: boolean; // iOS
backBufferDurationMs?: number; // Android
bufferConfig?: BufferConfig; // Android
chapters?: Chapters[]; // iOS
contentStartTime?: number; // Android
controls?: boolean;
currentPlaybackTime?: number; // Android