web-dev-qa-db-fra.com

Création d'une miniature à partir d'une vidéo locale en swift

Comment créer une vignette dans Swift à partir d'un fichier vidéo local?

Par exemple, si le chemin du fichier vidéo se trouve ici:

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

Merci.

36
Ralph

Traduit avec quelques modifications de:

Première image d'une vidéo utilisant 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
54
BaseZen

Réponse de BaseZen traduite Swift 3 / Swift 4

Vous devez définir l'emplacement de la vidéo dont vous souhaitez créer une miniature en tant que chemin d'accès de l'URL, comme:

N'oubliez pas de 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
    }
}

Pour tous ceux qui ont des problèmes avec cela, j'ai créé l'exemple de goutte suivant hébergé sur Github

55
David Seek

Il s'agit d'une version nettoyée de la réponse de David et testée contre iOS 11/Swift 4.x.

Veuillez noter les différents appels pour gérer l'heure initiale en fonction de la version de Swift que vous utilisez.

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. Crée un AVURLAsset à partir du URL fourni
  2. Crée un AVAssetImageGenerator en utilisant le AVURLAsset nouvellement créé, est responsable de la création de la vignette
  3. applyPreferredTrackTransform informe le générateur d'appliquer la matrice à la génération de vignettes. La valeur par défaut est false.
  4. Tente de créer un CGImage à la première image de la piste vidéo
  5. Crée un UIImage en utilisant le CGImage nouvellement créé et le renvoie
  6. Si l'étape de génération d'image échoue, une erreur est interceptée et présentée à la console avec un UIImage nul
19
CodeBender

La réponse de BaseZen traduite en 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)")
}
12
Carl Smith

Il vaut mieux écrire moins de code simple pour comprendre. C'est ce que je convertis les solutions en Swift (3.1 ... 4.2)

import AVFoundation

func videoPreviewUIImage(moviePath: URL) -> UIImage? {
    let asset = AVURLAsset(url: moviePath)
    let generator = AVAssetImageGenerator(asset: asset)
    generator.appliesPreferredTrackTransform = true
    let timestamp = CMTime(seconds: 2, preferredTimescale: 60)
    if let imageRef = try? generator.copyCGImage(at: timestamp, actualTime: nil) {
        return UIImage(cgImage: imageRef)
    } else {
        return nil
    }
}

J'espère que cela aidera quelqu'un.

4
Bilal Arslan