Bau- und Bauingenieurwesen
Erstellen eines benutzerdefinierten Video-Thumbnail-Generators in Ios mit Avfoundation
Table of Contents
Video-Miniaturansichten sind ein Eckpfeiler moderner medienreicher Anwendungen und bieten Benutzern eine schnelle visuelle Vorschau, ohne das vollständige Video abspielen zu müssen. In der iOS-Entwicklung bietet AVFoundation die leistungsstärksten und flexibelsten Tools zum Extrahieren von Miniaturansichten. Dieser Artikel geht durch den Aufbau eines benutzerdefinierten Video-Miniaturansichtsgenerators, der reale Szenarien - einschließlich lokaler und Remote-Dateien, Caching, Fehlerbehandlung und Performance-Tuning - mit Swift und AVFoundation verarbeiten kann.
Verständnis der Rolle von AVFoundation in der Thumbnail-Generation
AVFoundation ist Apples primäres Framework für die Arbeit mit audiovisuellen Medien. Für die Erzeugung von Miniaturansichten sind die Schlüsselklassen AVAsset und AVAssetImageGenerator.
- AVAsset: Repräsentiert ein zeitgesteuertes audiovisuelles Asset (ein lokales oder entferntes Video).
- AVAssetImageGenerator: Bietet Methoden, um CGImageRefs aus dem Asset in bestimmten Zeitintervallen zu erhalten. Es respektiert die Videoorientierung, wendet Farbraumanpassungen an und unterstützt asynchrone Massenerzeugung.
Mit diesen Klassen haben Sie die volle Kontrolle über Bildgröße, Zeitgenauigkeit und Transformation, im Gegensatz zu UIKit-Verknüpfungen, die häufig Konfigurationsoptionen verbergen.
Aufbau des Projekts
Beginnen Sie mit dem Importieren von AVFoundation in Ihre Swift-Datei:
import AVFoundation
Sie müssen auch UIKit verwenden, um die erzeugten Bilder anzuzeigen. Erstellen Sie eine aus einer URL. Verwenden Sie für lokale Dateien. Verwenden Sie für entfernte Videos und stellen Sie sicher, dass das Asset initialisiert werden kann:
// Local
let localURL = Bundle.main.url(forResource: "sample", withExtension: "mp4")!
let asset = AVAsset(url: localURL)
// Remote
let remoteURL = URL(string: "https://example.com/video.mp4")!
let remoteAsset = AVAsset(url: remoteURL)
Ein einzelnes Thumbnail erzeugen
Um ein Miniaturbild zu einem bestimmten Zeitpunkt zu erzeugen, erstellen Sie ein und rufen Sie auf. Diese Methode ist synchron und sollte vom Hauptthread ausgeführt werden, um das Blockieren der Benutzeroberfläche zu vermeiden.
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
let time = CMTime(seconds: 2.0, preferredTimescale: 600) // 2 seconds into the video
do {
let cgImage = try imageGenerator.copyCGImage(at: time, actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
// Update UI on main thread
DispatchQueue.main.async {
imageView.image = thumbnail
}
} catch {
print("Thumbnail generation failed: \(error.localizedDescription)")
}
Wichtig:] Das Setzen von auf stellt sicher, dass das resultierende Bild die Rotationsmetadaten des Videos (Porträt vs. Landschaft) respektiert.
Die richtige Zeit wählen
Thumbnails werden oft am Anfang eines Videos gemacht, aber ziehen Sie eine Zeit in Betracht, die den Inhalt darstellt, z. B. 10% in die Dauer.
let duration = asset.duration
let midTime = CMTimeMultiplyByFloat64(duration, multiplier: 0.1)
Umgang mit Fehlern und Edge Cases
Die Erzeugung von Thumbnails kann aus verschiedenen Gründen fehlschlagen.
- Ungültiges Asset: Das Video kann beschädigt oder die URL nicht erreichbar sein.
- Missing video track: Some assets contain only audio; check .
- Zeit außerhalb der Grenzen: Stellen Sie sicher, dass die angeforderte Zeit zwischen und der Laufzeit des Vermögenswerts liegt.
- Netzwerkfehler: Remote-Assets können möglicherweise nicht geladen werden.
Beispiel für Vorladeeigenschaften:
let assetKeys = ["tracks", "duration", "playable"]
asset.loadValuesAsynchronously(forKeys: assetKeys) {
var error: NSError?
let status = asset.statusOfValue(forKey: "tracks", error: &error)
if status == .loaded {
// Safe to generate thumbnails
} else {
// Handle error
}
}
Anpassen Thumbnail Output
AVAssetImageGenerator bietet mehrere Eigenschaften zur Feinabstimmung des Ausgabebildes.
Maximale Größe
Beschränken Sie das erzeugte Bild auf ein bestimmtes Bounding-Box mit , wodurch der Speicher-Overhead reduziert und die Erzeugung für große Videos beschleunigt wird.
imageGenerator.maximumSize = CGSize(width: 640, height: 480)
Das erzeugte Bild wird skaliert, um innerhalb dieser Dimensionen unter Beibehaltung des Seitenverhältnisses zu passen.
Geforderte Zeittoleranz
Standardmäßig gibt den genauen Rahmen zur gewünschten Zeit (oder so nahe wie möglich) zurück. Sie können die Genauigkeit für die Geschwindigkeit tauschen, indem Sie und einstellen.
imageGenerator.requestedTimeToleranceBefore = CMTime(seconds: 0.5, preferredTimescale: 600)
imageGenerator.requestedTimeToleranceAfter = CMTime(seconds: 0.5, preferredTimescale: 600)
Blendenmodus
steuert, wie das erzeugte Bild saubere Blende vs. Produktionsblende behandelt.
imageGenerator.apertureMode = .cleanAperture
Transformationen anwenden
Wenn Sie das Bild drehen oder umdrehen müssen (z. B. für eine bestimmte Ausrichtung), verwenden Sie Core Graphics-Transformationen. Ein Ansatz besteht darin, das Rohbild zu erfassen und dann eine CGAffineTransformation manuell anzuwenden. Alternativ können Sie auf setzen (wie gezeigt) und der natürlichen Ausrichtung des Assets vertrauen.
Mehrere Thumbnails effizient generieren
Für Video-Raster, Timeline-Srubbing oder Storyboard-Vorschau benötigen Sie oft Dutzende von Miniaturansichten. Vermeiden Sie es, in einer Schleife im Hauptthread aufzurufen. Verwenden Sie stattdessen die asynchrone Methode , die mehrere Zeitanforderungen effizient verarbeitet und interne Parallelität nutzt.
var times: [NSValue] = []
for i in 0..<10 {
let time = CMTime(seconds: Double(i) * 2.0, preferredTimescale: 600)
times.append(NSValue(time: time))
}
imageGenerator.generateCGImagesAsynchronously(forTimes: times) { requestedTime, cgImage, actualTime, result, error in
if result == .succeeded, let cgImage = cgImage {
let thumbnail = UIImage(cgImage: cgImage)
DispatchQueue.main.async {
// Append to array or update collection view cell
}
} else {
print("Failed at \(requestedTime): \(error?.localizedDescription ?? "unknown")")
}
}
Diese Methode skaliert sich gut und ermöglicht es Ihnen, die Benutzeroberfläche schrittweise zu aktualisieren.
Arbeiten mit Remote Videos
Wenn die Video-URL auf einen entfernten Server verweist, müssen Sie warten, bis das Asset vollständig geladen ist oder zumindest die Track-Informationen verfügbar sind.
let urlAsset = AVURLAsset(url: remoteURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
urlAsset.loadValuesAsynchronously(forKeys: ["tracks"]) {
// Then create image generator and proceed
}
Betrachten Sie für Produktions-Apps das Caching von Miniaturansichten auf der Festplatte, damit der wiederholte Zugriff auf dasselbe Video das Bild nicht erneut abruft. Verwenden Sie oder einen dateibasierten Cache unter Verwendung der Video-URL als Schlüssel.
Caching Strategie Beispiel
class ThumbnailCache {
static let shared = ThumbnailCache()
private let cache = NSCache<NSString, UIImage>()
func thumbnail(for url: URL) -> UIImage? {
return cache.object(forKey: url.absoluteString as NSString)
}
func setThumbnail(_ image: UIImage, for url: URL) {
cache.setObject(image, forKey: url.absoluteString as NSString)
}
}
Kombinieren Sie dies mit dem Bildgenerator, um redundante Arbeit zu vermeiden.
Leistungsbetrachtungen
Die Erzeugung von Miniaturansichten ist eine CPU-intensive Operation, insbesondere für hochauflösende 4K-Videos.
- Führen Sie immer synchrone Aufrufe in einer Hintergrundwarteschlange aus (z. B. .
- Stellen Sie eine angemessene ein, um die Ausgabeabmessungen zu reduzieren. Eine Größe von 320x240 ist oft ausreichend für Listen-Miniaturansichten.
- Verwenden Sie , damit der Generator den nächstgelegenen Frame überspringen kann, anstatt die genaue Dekodierung zu lösen.
- Stornieren Sie jede in Gang befindliche asynchrone Generation, wenn die Ansicht verschwindet.
- Generieren Sie für die Anzeige in einer Sammelansicht Miniaturansichten mit der genauen Zellengröße und vermeiden Sie eine Größenänderung am Hauptthread.
Integration mit Swift Concurrency (Async/Await)
Wenn Ihre App auf iOS 15+ abzielt, können Sie den Blockieraufruf in eine Fortsetzung für sauberen Async / Wartecode einfügen:
func generateThumbnail(forVideoAt url: URL, at time: CMTime) async throws -> UIImage {
let asset = AVAsset(url: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
imageGenerator.maximumSize = CGSize(width: 640, height: 480)
return try await withCheckedThrowingContinuation { continuation in
let times = [NSValue(time: time)]
imageGenerator.generateCGImagesAsynchronously(forTimes: times) { _, cgImage, _, result, error in
if let cgImage = cgImage, result == .succeeded {
let image = UIImage(cgImage: cgImage)
continuation.resume(returning: image)
} else {
continuation.resume(throwing: error ?? ThumbnailError.generationFailed)
}
}
}
}
Advanced Customizations
Thumbnails mit Video-Zusammensetzung
Wenn Ihr Video ein verwendet (z. B. Wasserzeichen-Overlay, Farbanpassungen), können Sie es an den Bildgenerator weitergeben:
imageGenerator.videoComposition = myVideoComposition
Das generierte Thumbnail spiegelt die zusammengesetzte Ausgabe wider.
Thumbnails für Live-Fotos generieren
Live-Fotos sind eine Kombination aus einem Video und einem Standbild.Um ein Miniaturbild aus dem zugrunde liegenden Video zu extrahieren, verwenden Sie die und fordern Sie eine Video-URL an, bevor Sie es in AVFoundation einspeisen.
Zugänglichkeit und User Experience
Thumbnails verbessern das visuelle Scannen, bieten aber immer eine Textalternative für VoiceOver-Benutzer.
imageView.isAccessibilityElement = true
imageView.accessibilityLabel = "Thumbnail of video: \(videoTitle)"
Externe Ressourcen
Für ein tieferes Verständnis konsultieren Sie Folgendes:
- AVAssetImageGenerator Offizielle Dokumentation
- AVAsset Reference
- WWDC 2019: AVFoundation Performance Tips
Schlussfolgerung
Durch die Nutzung von sowohl synchron als auch asynchron, durch die Handhabung von Fehlern und Caching-Ergebnissen können Sie eine nahtlose Benutzererfahrung in Ihrer iOS-App bereitstellen. Ob Sie lokale Dateien oder Remote-Videos verarbeiten, die hier behandelten Techniken helfen Ihnen, scharfe, kontextbewusste Miniaturansichten schnell und effizient zu erstellen.