mirror of
https://github.com/zoriya/react-native-video.git
synced 2026-05-31 10:13:43 +00:00
fix(ios): notification controls (#4838)
* fix: update observer thread * fix(ios): fix showNotificationControls not working when set during initialization * fix(ios): set custom metadata on AVPlayerItem for now playing info * refactor: warn when wront artwork url * docs: update file header * chore: warn when failed to load artwork image
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// AVMetadataItem+make.swift
|
||||
// ReactNativeVideo
|
||||
//
|
||||
// Created by Kamil Moskała on 06/02/2026.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
|
||||
extension AVMetadataItem {
|
||||
static func make(identifier: AVMetadataIdentifier, value: NSObjectProtocol & NSCopying) -> AVMutableMetadataItem {
|
||||
let item = AVMutableMetadataItem()
|
||||
item.identifier = identifier
|
||||
item.value = value
|
||||
item.extendedLanguageTag = "und"
|
||||
return item
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ class NowPlayingInfoCenterManager {
|
||||
updateNowPlayingInfo()
|
||||
playbackObserver = player.addPeriodicTimeObserver(
|
||||
forInterval: CMTime(value: 1, timescale: 4),
|
||||
queue: .global(),
|
||||
queue: .main,
|
||||
using: { [weak self] _ in
|
||||
self?.updateNowPlayingInfo()
|
||||
}
|
||||
@@ -218,13 +218,16 @@ class NowPlayingInfoCenterManager {
|
||||
}
|
||||
|
||||
public func updateNowPlayingInfo() {
|
||||
guard let player = currentPlayer, let currentItem = player.currentItem
|
||||
else {
|
||||
guard let player = currentPlayer else {
|
||||
invalidateCommandTargets()
|
||||
MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]
|
||||
return
|
||||
}
|
||||
|
||||
guard let currentItem = player.currentItem else {
|
||||
return
|
||||
}
|
||||
|
||||
// commonMetadata is metadata from asset, externalMetadata is custom metadata set by user
|
||||
// externalMetadata should override commonMetadata to allow override metadata from source
|
||||
// When the metadata has the tag "iTunSMPB" or "iTunNORM" then the metadata is not converted correctly and comes [nil, nil, ...]
|
||||
|
||||
@@ -391,6 +391,44 @@ class HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec {
|
||||
playerItem = AVPlayerItem(asset: asset)
|
||||
}
|
||||
|
||||
if let metadata = source.config.metadata {
|
||||
let title = metadata.title
|
||||
let artist = metadata.artist
|
||||
let imageUri = metadata.imageUri
|
||||
|
||||
DispatchQueue.main.async { [weak playerItem] in
|
||||
guard let playerItem else { return }
|
||||
var items: [AVMetadataItem] = []
|
||||
|
||||
if let title {
|
||||
items.append(.make(identifier: .commonIdentifierTitle, value: title as NSString))
|
||||
}
|
||||
if let artist {
|
||||
items.append(.make(identifier: .commonIdentifierArtist, value: artist as NSString))
|
||||
}
|
||||
if !items.isEmpty {
|
||||
playerItem.externalMetadata = items
|
||||
}
|
||||
}
|
||||
|
||||
// Load artwork in background to not block player initialization
|
||||
if let imageUri, let imageUrl = URL(string: imageUri) {
|
||||
Task { [weak playerItem] in
|
||||
guard let (data, _) = try? await URLSession.shared.data(from: imageUrl) else {
|
||||
print("[RNV] Failed to load artwork from: \(imageUrl)")
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
guard let playerItem else { return }
|
||||
playerItem.externalMetadata = playerItem.externalMetadata + [.make(identifier: .commonIdentifierArtwork, value: data as NSData)]
|
||||
NowPlayingInfoCenterManager.shared.updateNowPlayingInfo()
|
||||
}
|
||||
}
|
||||
} else if let imageUri {
|
||||
print("[RNV] Invalid imageUri for artwork: \(imageUri)")
|
||||
}
|
||||
}
|
||||
|
||||
return playerItem
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user