SwiftUIで動画ファイルのサムネイルを作る

最終更新日

SwiftUIで動画ファイルのサムネイルを作る時に、UIImageを生成してその画像をSwiftUIのImageで表示しようとすると、アスペクト比が崩れてしまい、Image().resizable()でサイズ調整をしようとしてもうまくいかなかったことがありました。

その挙動になる理由はよくわからないのですが、CGImageを使ってImageで表示すると綺麗に出力できましたので。

struct ThumnailView : View{
    
    var thumnailCGImage:CGImage = UIImage(systemName: "exclamationmark.octagon")!.cgImage!
    var imageOrientation:Image.Orientation = Image.Orientation.up
    
    init(filePath:String) {
        guard let url = URL(string: filePath) else {return}
        let asset = AVAsset(url: url)
        let imageGenerator = AVAssetImageGenerator(asset: asset)
        let track = asset.tracks(withMediaType: AVMediaType.video).first!
        let transform = track.preferredTransform
        
        print ("*** \(transform.tx), \(transform.ty), size: \(track.totalSampleDataLength)")
        
        do {
                        
            if transform.tx == 0 && transform.ty == 0 {
                self.imageOrientation = Image.Orientation.up
            } else if (transform.tx > 0 && transform.ty == 0) {
                self.imageOrientation = Image.Orientation.right
            } else if (transform.tx == 0 && transform.ty > 0) {
                self.imageOrientation = Image.Orientation.left
            } else {
                self.imageOrientation = Image.Orientation.down
            }
            
            self.thumnailCGImage = try imageGenerator.copyCGImage(at: CMTimeMake(value: 1,timescale: 60), actualTime: nil)
            
        } catch let error {
            print (error)
        }
    }
    
    var body: some View {
        Image(decorative: self.thumnailCGImage, scale: 1, orientation: self.imageOrientation).resizable()
    }
}

ImageでCGImageを表示する場合、CGImageには向きの情報を保持していないので、表示する際に指定してあげる必要があります。

Image(decorative: self.thumnailCGImage, scale: 1, orientation: self.imageOrientation).resizable()

向きの情報は動画の向き情報から取得します。

guard let url = URL(string: filePath) else {return}
let asset = AVAsset(url: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
let track = asset.tracks(withMediaType: AVMediaType.video).first!
let transform = track.preferredTransform
do {
    if transform.tx == 0 && transform.ty == 0 {
           self.imageOrientation = Image.Orientation.up
        } else if (transform.tx > 0 && transform.ty == 0) {
            self.imageOrientation = Image.Orientation.right
        } else if (transform.tx == 0 && transform.ty > 0) {
            self.imageOrientation = Image.Orientation.left
        } else {
            self.imageOrientation = Image.Orientation.down
        }
}

一応うまく動いているように見えるのですが、うまくいかないなどあれば教えて下さい。

githubは以下です。

https://github.com/ikeda-yusaku/ThumnailView

アスペクト比がうまく調整できな挙動はUIImageを動的に生成した場合の挙動のようです。静的な画像ファイルでは特に問題が発生しませんでしたので、おそらくSwiftUIの不具合だと思います。今後のバージョンアップで使い勝手が良くなるのが楽しみですね。

それでは、今回はこんなところで。

シェアする

Social media & sharing icons powered by UltimatelySocial
Follow by Email