从 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
}
}
- 根据提供的
URL
创建一个 AVURLAsset
- 使用新创建的
AVURLAsset
创建一个AVAssetImageGenerator
,负责制作缩略图
- appliesPreferredTrackTransform 通知生成器将矩阵应用于缩略图生成。默认值为 false。
- 尝试在视频轨道的第一帧创建
CGImage
- 使用新创建的 CGImage 创建一个
UIImage
& returns 它
- 如果图像生成步骤失败,则会捕获错误并将其与 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
如何从本地视频文件在 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
}
}
- 根据提供的
URL
创建一个 - 使用新创建的
AVURLAsset
创建一个AVAssetImageGenerator
,负责制作缩略图 - appliesPreferredTrackTransform 通知生成器将矩阵应用于缩略图生成。默认值为 false。
- 尝试在视频轨道的第一帧创建
CGImage
- 使用新创建的 CGImage 创建一个
UIImage
& returns 它 - 如果图像生成步骤失败,则会捕获错误并将其与 nil UIImage 一起呈现给控制台
AVURLAsset
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