Blog スタッフブログ

iOS Swift システム開発

[iOS]MPMediaItemの正確な再生時間を取得する

Swift

こんにちは、株式会社MIXシステム開発担当のBloomです。

早速本題のMPMediaItemの正確な再生時間を取得する方法について、

お仕事の中で得た知見を共有させていただきたいと思います。

ミュージックライブラリからMPMediaItemを取得

まずはミュージックライブラリからMPMediaItemを取得しましょう。取得する方法は以前の記事に掲載した方法をそのまま利用できます。

    func mediaPicker(_ mediaPicker: MPMediaPickerController,
                     didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        
        dismiss(animated: true, completion: nil)
        
        let items = mediaItemCollection.items
        if items.isEmpty { return }
        let item = items.first // MPMediaItem
    }

さて、ここから再生時間を取得してみましょう。通常はplaybackDurationプロパティで再生時間へアクセスできます。

    func mediaPicker(_ mediaPicker: MPMediaPickerController,
                     didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        /* 中略 */
        if let item = items.first {
            print(item.playbackDuration)
        }
    }

しかしなんとこの方法で取得した再生時間は数秒の誤差が発生する場合があるようです。今回はこの誤差をできるだけ解消する方法を紹介します。

AVURLAssetから読み込む

先ほどのコードに追記し、MPMediaItemのアセットURLからAVURLAssetを生成しましょう。

    func mediaPicker(_ mediaPicker: MPMediaPickerController,
                     didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        /* 中略 */
        let items = mediaItemCollection.items
        if items.isEmpty { return }
        if let item = items.first, 
            let url = item.assetURL {
            print("MPMediaItem duration:\(item.playbackDuration)")
            printPlaybackDuration(url: url)
        }
    }

    func printPlaybackDuration(url: URL) {
        Task {
            let avUrlAsset = AVURLAsset(url: url, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
            if let time = try? await avUrlAsset.load(.duration) {
                let duration = CMTimeGetSeconds(time)
                print(duration)
            }
        }
    }

このコードを実行することで精度を高めた再生時間が取得できます。良かったですね。

参考文献

AVPlayerのdurationの取得 – zenn.dev