Skip to content

Commit

Permalink
feat(tvos): add custom image metadata option for tvos and add missing…
Browse files Browse the repository at this point in the history
… 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 <[email protected]>
  • Loading branch information
Duell10111 and freeboub authored Oct 7, 2023
1 parent 067adde commit a855284
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 6 deletions.
5 changes: 3 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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'
}}
```

Expand Down
2 changes: 2 additions & 0 deletions examples/exampletvOS/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions examples/exampletvOS/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions ios/Video/DataStructures/VideoSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct VideoSource {
let title: String?
let subtitle: String?
let description: String?
let customImageUri: String?

let json: NSDictionary?

Expand All @@ -29,6 +30,7 @@ struct VideoSource {
self.title = nil
self.subtitle = nil
self.description = nil
self.customImageUri = nil
return
}
self.json = json
Expand All @@ -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
}
}
11 changes: 11 additions & 0 deletions ios/Video/Features/RCTVideoUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
5 changes: 5 additions & 0 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
4 changes: 4 additions & 0 deletions src/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

Expand Down
4 changes: 4 additions & 0 deletions src/VideoNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ type VideoSrc = Readonly<{
requestHeaders?: Headers;
startTime?: number;
endTime?: number;
title?: string;
subtitle?: string;
description?: string;
customImageUri?: string;
}>;

export type Filter =
Expand Down
12 changes: 12 additions & 0 deletions src/types/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<{
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit a855284

Please sign in to comment.