为什么 imagePickerController.mediaTypes = [kUTTypeMovie as String] 将实时照片作为弹跳或循环效果作为视频?
Why is imagePickerController.mediaTypes = [kUTTypeMovie as String] including Live Photos as Bounce or Loop Effect as Video?
我使用 UIImagePicker 仅从我的媒体库中选择视频,并将我的媒体类型设置为:
imagePicker.mediaTypes = [kUTTypeMovie as String]
我注意到,当展示库时,即使我希望只有视频,如果库中有具有 Bounce
或 Loop
效果的实时照片,它也会显示。如果我拍摄同一张照片并将其效果切换为 Live
或 Long Exposure
,它将不再出现在图库中。如果我将其切换回 Bounce
或 Loop
,它会重新出现。
我已经尝试了 .photoLibrary
和 .savedPhotosAlbum
,同样的事情发生了。
我问的原因是因为我不想让他们出库,我只想选择 xxx 秒或更长时间的视频。
- 即使我只选择视频,为什么这些效果类型会出现在图像选择器库中?
- 为什么只有
Loop
和 Bounce
出现而 Long Exposure
和 Live
没有出现?
- 如何将它们拒之门外?
也许这是一个单独的问题,但由于它属于相同的 Live
和 Bounce
照片问题,所以我添加了它。我注意到,如果我在 AVPlayer 中放置从 Live
或 Bounce
照片派生的 url,如果我进入后台并返回,当应用程序出现时会短暂冻结回到前台,它只发生在这 2 个效果(不应该可用)。当应用程序进入后台时,我使用此方法 正确删除了 AVPlayerLayer,但当播放器内部初始化来自那些效果类型的 url 时,它仍然在前台短暂冻结(应用程序无响应) .
代码:
import MobileCoreServices
import AVFoundation
class ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
var playerItem: AVPlayerItem?
var player: AVPlayer?
var playerLayer: AVPlayerLayer?
var currentPlayTime: CMTime?
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imagePickerController.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(appHasEnteredBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)
}
override func viewDidLayoutSubviews() {
// I have a UIView Outlet for the AVPlayerLayer named viewForPlayerLayer.
guard let playerLayer = playerLayer else { return }
playerLayer.videoGravity = .resizeAspectFill
viewForPlayerLayer.layer.insertSublayer(playerLayer, at: 0)
playerLayer.frame = viewForPlayerLayer.bounds
playerLayer.masksToBounds = true
}
@IBAction fileprivate func showLibraryButtonTapped(_ sender: UIButton) {
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary // .savedPhotosAlbum also tried
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.videoMaximumDuration = 60
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let url = info[UIImagePickerControllerMediaURL] as? URL{
let asset = AVAsset(url: url)
playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem!)
playerLayer = AVPlayerLayer(player: player)
player?.play()
}
imagePicker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
imagePicker.dismiss(animated: true, completion: nil)
}
@objc fileprivate func appHasEnteredBackground() {
currentPlayTime = player.currentTime()
if player.isPlaying{
player.pause()
}
playerLayer = nil
}
@objc fileprivate func appWillEnterForeground(){
if let player = player, let currentPlayTime = currentPlayTime{
playerLayer = AVPlayerLayer(player: player)
player.seek(to: currentPlayTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
}
}
}
如果您要求显示视频,则无法阻止 loop/bounce 实时照片视频出现在选择器中,因为它们 是 视频。但是,如果用户 选择 一个,您可以在委托方法中检测到一个。为此,UIImagePickerControllerMediaType
不足以 fine-grained。相反,获取照片库授权并获取由 UIImagePickerControllerPHAsset
键返回的 PHAsset,并检查其 playbackStyle
。这样就能画出你想要的区别了。
https://developer.apple.com/documentation/photos/phasset.playbackstyle
.videoLooping
是反弹或缩放实时照片。
我使用 UIImagePicker 仅从我的媒体库中选择视频,并将我的媒体类型设置为:
imagePicker.mediaTypes = [kUTTypeMovie as String]
我注意到,当展示库时,即使我希望只有视频,如果库中有具有 Bounce
或 Loop
效果的实时照片,它也会显示。如果我拍摄同一张照片并将其效果切换为 Live
或 Long Exposure
,它将不再出现在图库中。如果我将其切换回 Bounce
或 Loop
,它会重新出现。
我已经尝试了 .photoLibrary
和 .savedPhotosAlbum
,同样的事情发生了。
我问的原因是因为我不想让他们出库,我只想选择 xxx 秒或更长时间的视频。
- 即使我只选择视频,为什么这些效果类型会出现在图像选择器库中?
- 为什么只有
Loop
和Bounce
出现而Long Exposure
和Live
没有出现? - 如何将它们拒之门外?
也许这是一个单独的问题,但由于它属于相同的 Live
和 Bounce
照片问题,所以我添加了它。我注意到,如果我在 AVPlayer 中放置从 Live
或 Bounce
照片派生的 url,如果我进入后台并返回,当应用程序出现时会短暂冻结回到前台,它只发生在这 2 个效果(不应该可用)。当应用程序进入后台时,我使用此方法
代码:
import MobileCoreServices
import AVFoundation
class ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
var playerItem: AVPlayerItem?
var player: AVPlayer?
var playerLayer: AVPlayerLayer?
var currentPlayTime: CMTime?
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imagePickerController.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(appHasEnteredBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)
}
override func viewDidLayoutSubviews() {
// I have a UIView Outlet for the AVPlayerLayer named viewForPlayerLayer.
guard let playerLayer = playerLayer else { return }
playerLayer.videoGravity = .resizeAspectFill
viewForPlayerLayer.layer.insertSublayer(playerLayer, at: 0)
playerLayer.frame = viewForPlayerLayer.bounds
playerLayer.masksToBounds = true
}
@IBAction fileprivate func showLibraryButtonTapped(_ sender: UIButton) {
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary // .savedPhotosAlbum also tried
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.videoMaximumDuration = 60
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let url = info[UIImagePickerControllerMediaURL] as? URL{
let asset = AVAsset(url: url)
playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem!)
playerLayer = AVPlayerLayer(player: player)
player?.play()
}
imagePicker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
imagePicker.dismiss(animated: true, completion: nil)
}
@objc fileprivate func appHasEnteredBackground() {
currentPlayTime = player.currentTime()
if player.isPlaying{
player.pause()
}
playerLayer = nil
}
@objc fileprivate func appWillEnterForeground(){
if let player = player, let currentPlayTime = currentPlayTime{
playerLayer = AVPlayerLayer(player: player)
player.seek(to: currentPlayTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
}
}
}
如果您要求显示视频,则无法阻止 loop/bounce 实时照片视频出现在选择器中,因为它们 是 视频。但是,如果用户 选择 一个,您可以在委托方法中检测到一个。为此,UIImagePickerControllerMediaType
不足以 fine-grained。相反,获取照片库授权并获取由 UIImagePickerControllerPHAsset
键返回的 PHAsset,并检查其 playbackStyle
。这样就能画出你想要的区别了。
https://developer.apple.com/documentation/photos/phasset.playbackstyle
.videoLooping
是反弹或缩放实时照片。