🍎

[iOS] 動画からサムネイル取得する方法(async/await)

2023/03/27に公開

概要

WWDC22で発表された「Create a more responsive media app」の動画の中で紹介された新しいasyncAPIを使ったサムネイルの取得方法について紹介します。

デモ


※デモはローカルの動画ファイルを使用しています。

サムネイルの取得方法について

AVAssetImageGeneratorを使用して動画からサムネイル画像を取得していきます。
サムネイル画像を生成するには、AVAssetImageGeneratorが動画ファイルからフレームデータを読み込む必要があります。WWDC22では、AVAssetImageGeneratorのasync/awaitを使用した画像取得のメソッドが発表されました。
以下のようにして、時間を指定して.imageプロパティを使用して直接imageを取得できます。

func thumbnail(time: CMTime) async throws -> UIImage {
  let generator = AVAssetImageGenerator(asset: asset)
  let thumbnail = try await generator.image(at: time).image
  return UIImage(cgImage: thumbnail)
}

※iOS16以上の制限があります。

正確なフレームを取得する

指定した時間の正確なフレームを取得するために、許容値をゼロに設定したくなるかもしれないが、そうするとフレームに依存した画像の取得になるので、ロードが遅延する可能性がある。

func thumbnail(time: CMTime) async throws -> UIImage {
  let generator = AVAssetImageGenerator(asset: asset)
  generator.requestedTimeToleranceBefore = .zero // ←ココ(here) 
  generator.requestedTimeToleranceAfter = .zero  // ←ココ(here)
  let thumbnail = try await generator.image(at: time).image
  return UIImage(cgImage: thumbnail)
}

フレームの許容値を広範囲に設定することで、データの読み込みを最小限に抑えることができます。

func thumbnail(time: CMTime) async throws -> UIImage {
  let generator = AVAssetImageGenerator(asset: asset)
  generator.requestedTimeToleranceBefore = .zero // ←ココ(here) 
  generator.requestedTimeToleranceAfter = CMTime (seconds: 3, preferredTimescale: 600) // ←ココ(here)
  let thumbnail = try await generator.image(at: time).image
  return UIImage(cgImage: thumbnail)
}

まとめ

今回はAVAssetImageGeneratorの追加された新しいasyncメソッドを紹介しました。
ローカルファイルを使って許容値をゼロに設定して、デモを作って動かしてみましたが、あまり遅延がなくスムーズに表示されました。インターネットに置かれたファイルだと許容値の設定は必要そうに感じました。

Discussion