为啥 imagePickerController.mediaTypes = [kUTTypeMovie as String] 包括实时照片作为反弹或循环效果作为视频?

Posted

技术标签:

【中文标题】为啥 imagePickerController.mediaTypes = [kUTTypeMovie as String] 包括实时照片作为反弹或循环效果作为视频?【英文标题】:Why is imagePickerController.mediaTypes = [kUTTypeMovie as String] including Live Photos as Bounce or Loop Effect as Video?为什么 imagePickerController.mediaTypes = [kUTTypeMovie as String] 包括实时照片作为反弹或循环效果作为视频? 【发布时间】:2018-03-21 18:06:13 【问题描述】:

我正在使用 UIImagePicker 仅从我的库中挑选视频,并将媒体类型设置为:

imagePicker.mediaTypes = [kUTTypeMovie as String]

我注意到,当显示库时,即使我只希望看到视频,如果库中有 BounceLoop 效果的实时照片,它也会显示出来。如果我拍摄同一张照片并将其效果切换为LiveLong Exposure,它将不再出现在图书馆中。如果我将其切换回BounceLoop,它会重新出现。

.photoLibrary.savedPhotosAlbum 我都试过了,结果还是一样。

我问的原因是因为我想把它们排除在图书馆之外,我只想挑选 xxx 秒或更长的视频。

    即使我只选择视频,为什么这些效果类型会显示在图像选择器库中? 为什么只出现LoopBounceLong ExposureLive 没有出现? 如何让它们远离?

也许这将是一个单独的问题,但由于它与 LiveBounce 相同的照片问题我添加了它。我注意到,如果我将源自LiveBounce 照片的 url 放入 AVPlayer 中,如果我转到后台并返回,当应用程序返回前台时会出现短暂的冻结,并且仅发生在这 2 种效果(不应该可用)中。当应用程序进入后台时,我使用此方法Remove AVPlayerLayer 正确删除了 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)
    



【问题讨论】:

@matt 嗨,这里有 2 个问题。 1. 如果这些实际上是照片,并且我只为视频选择 [kUTTypeMovie as String],为什么它们会出现在库中? 2. 如果我选择反弹或循环效果,它们会显示为视频,但如果我选择实时或长时间曝光,它们不会显示为视频。似乎即使它们是照片,Live and Bounce 效果也会将它们转换为视频 一如既往地感谢您的帮助! 【参考方案1】:

如果您要求显示视频,则无法阻止循环/反弹实时照片视频出现在选择器中,因为它们视频。但是,如果用户选择一个,您可以在委托方法中检测到一个。为此,UIImagePickerControllerMediaType 的粒度不够细。相反,获取照片库授权并获取由UIImagePickerControllerPHAsset 键返回的 PHAsset,并检查其playbackStyle。这将得出您想要的区别。

https://developer.apple.com/documentation/photos/phasset.playbackstyle

.videoLooping 是反弹或缩放实时照片。

【讨论】:

谢谢,我认为 [kUTTypeMovie as String] 可以防止任何不是视频的内容。如果使用这两种类型初始化,您能否回答有关 AVPlayer 从后台返回时冻结的问题? 如果我理解正确,如果 AVPlayer 的 url 是 Live 或 Bounce 类型的照片,那么我应该使用 AVQueuePlayer 而不是使用 AVPlayer? 我有你的 ios 10 书,我还没有升级到 11。看来我必须这样做。谢谢你的一切:) 我已经听从了您的建议,并且能够阻止用户在 didFinishPickingMediaWithInfo 中选择实时照片。令我困惑的是,当我打开 YouTube 的 iOS 应用程序时,当我按下视频图标进行录制时,我只看到库中的电影,没有显示任何实时照片。他们是如何阻止图书馆展示除电影之外的任何东西的?除非他们使用不同于 [kUTTypeMovie as String] 的东西? 你的意思是自定义的东西还是其他的 api?

以上是关于为啥 imagePickerController.mediaTypes = [kUTTypeMovie as String] 包括实时照片作为反弹或循环效果作为视频?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3 - 无法覆盖'imagePickerController'

如何使用 ImagePickerController 直接显示“相机胶卷”

无法获取 UIImage 以匹配自定义 ImagePickerController 预览

imagePickerController 选择照片时出错

imagePickerController 获取图片的拍照时间等信息

imagePickerController 返回 0 字节的图像