从 swift 中的本地视频创建缩略图

Creating thumbnail from local video in swift

如何从本地视频文件在 swift 中创建缩略图?

例如,如果视频文件路径位于此处:

file:///Users/Dev/Library/Developer/CoreSimulator/Devices/F33222DF-D8F0-448B-A127-C5B03C64D0DC/data/Containers/Data/Application/4BC62DBF-0108-453C-9324-5BC0E356FE24/tmp/trim.059D11E6-F0EF-43DB-9E97-CA4F1F95D6B6.MOV

谢谢。

经过一些编辑翻译自:

First frame of a video using AVFoundation

    var err: NSError? = nil
    let asset = AVURLAsset(URL: NSURL(fileURLWithPath: "/that/long/path"), options: nil)
    let imgGenerator = AVAssetImageGenerator(asset: asset)
    let cgImage = imgGenerator.copyCGImageAtTime(CMTimeMake(0, 1), actualTime: nil, error: &err)
    // !! check the error before proceeding
    let uiImage = UIImage(CGImage: cgImage)
    let imageView = UIImageView(image: uiImage)
    // lay out this image view, or if it already exists, set its image property to uiImage

BaseZen 的答案翻译成 Swift 2:

import UIKit
import AVFoundation

do {
    let asset = AVURLAsset(URL: NSURL(fileURLWithPath: "/that/long/path"), options: nil)
    let imgGenerator = AVAssetImageGenerator(asset: asset)
    imgGenerator.appliesPreferredTrackTransform = true
    let cgImage = try imgGenerator.copyCGImageAtTime(CMTimeMake(0, 1), actualTime: nil)
    let uiImage = UIImage(CGImage: cgImage)
    let imageView = UIImageView(image: uiImage)
    // lay out this image view, or if it already exists, set its image property to uiImage
} catch let error as NSError {
    print("Error generating thumbnail: \(error)")
}

BaseZen 的回答翻译 Swift 3 / Swift 4

您需要将要制作缩略图的视频位置设置为url资产路径,例如:

别忘了import AVFoundation

func generateThumbnail(path: URL) -> UIImage? {
    do {
        let asset = AVURLAsset(url: path, options: nil)
        let imgGenerator = AVAssetImageGenerator(asset: asset)
        imgGenerator.appliesPreferredTrackTransform = true
        let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
        let thumbnail = UIImage(cgImage: cgImage)
        return thumbnail
    } catch let error {
        print("*** Error generating thumbnail: \(error.localizedDescription)")
        return nil
    }
}

对于对此有疑问的每个人,我在 Github

上创建了以下托管示例

为了理解,还是少写点简单的代码比较好。 这就是我在 Swift (3.1 ... 5.2)

中转换的解决方案
import AVFoundation

func imagePreview(from moviePath: URL, in seconds: Double) -> UIImage? {
    let timestamp = CMTime(seconds: seconds, preferredTimescale: 60)
    let asset = AVURLAsset(url: moviePath)
    let generator = AVAssetImageGenerator(asset: asset)
    generator.appliesPreferredTrackTransform = true

    guard let imageRef = try? generator.copyCGImage(at: timestamp, actualTime: nil) else {
        return nil
    }
    return UIImage(cgImage: imageRef)
}

希望对大家有所帮助。

这是 David 答案的清理版本,并针对 iOS 11 / Swift 4.x 进行了测试。

请注意根据您使用的 Swift 版本处理初始时间的不同调用。

func generateThumbnail(url: URL) -> UIImage? {
    do {
        let asset = AVURLAsset(url: url)
        let imageGenerator = AVAssetImageGenerator(asset: asset)
        imageGenerator.appliesPreferredTrackTransform = true
        // Select the right one based on which version you are using
        // Swift 4.2
        let cgImage = try imageGenerator.copyCGImage(at: .zero,
                                                     actualTime: nil)
        // Swift 4.0
        let cgImage = try imageGenerator.copyCGImage(at: kCMTimeZero,
                                                     actualTime: nil)


        return UIImage(cgImage: cgImage)
    } catch {
        print(error.localizedDescription)

        return nil
    }
}
  1. 根据提供的 URL
  2. 创建一个 AVURLAsset
  3. 使用新创建的AVURLAsset创建一个AVAssetImageGenerator,负责制作缩略图
  4. appliesPreferredTrackTransform 通知生成器将矩阵应用于缩略图生成。默认值为 false。
  5. 尝试在视频轨道的第一帧创建CGImage
  6. 使用新创建的 CGImage 创建一个 UIImage & returns 它
  7. 如果图像生成步骤失败,则会捕获错误并将其与 nil UIImage 一起呈现给控制台
func saveImageDocumentDirectoryWithDate(tempImage:UIImage, block : @escaping (_ url: URL?) -> Void ){

    let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

    let random : String =  randomString(length: 5)

    let fileURL = documentsDirectoryURL.appendingPathComponent(String(format:"CPImage%@.png",random))
    do { try tempImage.pngData()?.write(to: fileURL) }
    catch { block(nil) }
    block(fileURL)}

Swift 5.3

作为其他答案的替代方案,稍作修改后,我决定进行 URL 扩展。

import AVFoundation

extension URL {
    func generateThumbnail() -> UIImage? {
        do {
            let asset = AVURLAsset(url: self)
            let imageGenerator = AVAssetImageGenerator(asset: asset)
            imageGenerator.appliesPreferredTrackTransform = true
            
            // Swift 5.3
            let cgImage = try imageGenerator.copyCGImage(at: .zero,
                                                         actualTime: nil)

            return UIImage(cgImage: cgImage)
        } catch {
            print(error.localizedDescription)

            return nil
        }
    }
}

用法:

let image = someURL.generateThumbnail()

以下是如何在 swift 5 中生成视频的缩略图(第一帧):

import UIKit
import AVFoundation

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let video = AVURLAsset(url: URL(fileURLWithPath: Bundle.main.path(forResource: "sampleVideo", ofType: "mov")!))
        let thumbnailGenerator = AVAssetImageGenerator(asset: video)
    
        do
        {
            let cgImage = try thumbnailGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
            let UiImage = UIImage(cgImage: cgImage)
            imageView.image = UiImage
        }
        catch
        { print(error) }
    
    }

}

在此示例中,视频名称为 sampleVideo.mov(将文件 url 更改为您的视频文件的名称),确保将视频导入本地 Xcode 项目并将其添加到您应用的目标中。

我制作了一个 youtube 来解释这个 here