iOS
Swift

UIImagePicker から動画を取得する際、使用するキーによって画質に差が出る

UIImagePickerでカメラロール内のメディアを使うとき delegateで渡ってきたinfoから情報を取得しますが、URLのキーによって動画の画質に差が出てきます。

動画のURLは以下2種類のキーで取得できます。

UIImagePickerControllerReferenceURL の方が画質がよく、
UIImagePickerControllerMediaURL はわずかですが画質が悪いです。
iPad やスクショを Mac で引き取ってみるなどすると違いがわかります。

ただ、単純に UIImagePickerControllerReferenceURL を使えばいいかと言うとそうでもなく、
UIImagePickerControllerReferenceURL は iOS11 で deprecated になっています。
代わりに UIImagePickerControllerPHAsset を使えとあるので使うしかないのですが、 PHAsset から AVPlayerItem を生成してやる必要があるので、一手間必要になってきてしまいます。

最後に、 ImagePicker から動画を取得して再生するサンプルコードを添付します。
プロジェクト全体のリンクはコチラです。 https://github.com/taketomato/movieTest

Swift
import UIKit
import AVKit
import Photos
import AVFoundation

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    let imagePickerController = UIImagePickerController()
    var videoURL: URL?

    @IBOutlet var assetURLswitch: UISwitch!
    @IBOutlet weak var fileUrlLabel: UILabel!
    @IBOutlet weak var assetUrlLabel: UILabel!

    // MARK: - Life Cycle

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        updateLabel()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        PHPhotoLibrary.requestAuthorization { (_) in } // for iOS11
    }

    // MARK: - UIImagePickerControllerDelegate

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        if assetURLswitch.isOn {
            videoURL = info["UIImagePickerControllerReferenceURL"] as? URL // 画質良い iOS11 で deprecated
        } else {
            videoURL = info["UIImagePickerControllerMediaURL"] as? URL // 画質悪い
        }

        let completion: () -> () = { [weak self] in
            guard let url = self?.videoURL else { return }
            print(url)
            self?.playMovie(url)
        }

        imagePickerController.dismiss(animated: true, completion: completion)
    }

    // MARK: - Private

    fileprivate func playMovie(_ url: URL) {
        let player = AVPlayer(url: url)
        let playerViewController = AVPlayerViewController()
        playerViewController.player = player

        present(playerViewController, animated: true){
            playerViewController.player?.play()
        }
    }

    fileprivate func updateLabel() {
        fileUrlLabel.isHidden = assetURLswitch.isOn
        assetUrlLabel.isHidden = !assetURLswitch.isOn
    }

    // MARK: - IB Action

    // カメラロールから動画を選択
    @IBAction func selectImage(_ sender: Any) {
        imagePickerController.sourceType = .photoLibrary
        imagePickerController.delegate = self
        imagePickerController.mediaTypes = ["public.movie"] // 動画のみ表示
        present(imagePickerController, animated: true, completion: nil)
    }

    @IBAction func switched(_ sender: Any) {
        updateLabel()
    }
}