Video pikkukuvat ovat kulmakivi nykyaikaisissa media-rikas sovelluksissa, jotka tarjoavat käyttäjille nopean visuaalisen esikatselun tarvitsematta pelata koko videota. iOS-kehityksessä AVFounducation tarjoaa suorimmat ja joustavat työkalut peukalonkuvan poimimiseen. Tämä artikkeli kulkee läpi rakentamalla mukautetun videon peukalon generaattorin, joka pystyy käsittelemään tosimaailman skenaarioita. Mukaan lukien paikalliset ja etätiedostot, välimuisti, virheiden käsittely ja suorituskyky virittämällä.

AVFoundingation ...

AVFounding on Apple. Apple.Sen ensisijainen toimintakehys audiovisuaalisissa muodoissa on . Avainluokat ovat AVAsset ja AVAssetImageGenerator[.

  • AVAsset[: Edustaa ajastettua audiovisuaalista aineistoa (paikallista tai etävideota). Se sisältää kappaletietoja, kestoa ja metatietoja.
  • AVAssetImageGenerator[: Tarjoaa menetelmiä saada CGImageRefit omaisuuserän tiettynä ajan välein. Se kunnioittaa videon suuntautumista, soveltaa väritilan säätöjä, ja tukee asynkroninen irtotavarana generaation.

Käyttämällä näitä luokkia suoraan saat täyden hallinnan kuvan koon, ajan tarkkuuden ja muuntamisen suhteen, toisin kuin Uikit-pikakuvat, jotka usein piilottavat asetusvalinnat.

Projektin käynnistäminen

Aloita tuomalla AVFoundingation Swift-tiedostoosi:

import AVFoundation

Tarvitset myös UIKitin näyttämään luodut kuvat. Luo [ URL-osoitteesta. Paikallistiedostojen osalta käytä . Kaukovideoita varten käytä [ ja varmista, että kohde voidaan alustaa:

// 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)

Yhden peukalon luominen

Luodaksesi yhden pikkukuvan tiettynä aikana, luo [ ja soita . Tämä menetelmä on synkronoitu ja se on poistettava päälangasta, jotta vältetään käyttöliittymän estäminen.

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)")
}

Tärkeintä:[ Asettaen :lle varmistaa, että tuloksena oleva kuva kunnioittaa videon kiertometadataa (kuva vs. maisema). Ilman tätä pystysuora video saattaa näkyä sivuttain.

Oikean ajan valinta

Peukalot otetaan usein videon alussa, mutta harkitse käyttää aikaa, joka edustaa sisältöä. Esimerkiksi 10%:n verran duraatioon. Jotta saataisiin mielekäs aikapiste, kysy omaisuuserän duraatio:

let duration = asset.duration
let midTime = CMTimeMultiplyByFloat64(duration, multiplier: 0.1)

Virheiden ja sivuseikkatapausten käsittely

Peukalokäärme voi epäonnistua useista syistä. Käsittele virheet aina hienovaraisesti ja anna varakäyttöliittymä.

  • Vähän käytetty ominaisuus:[ Video voi olla korruptoitunut tai URL-osoite on tavoittamaton.
  • Kadonnut videoraita:[] Jotkut varat sisältävät vain äänen; tarkista .
  • Aika, joka kuluu rajojen ulkopuolelle:[ Varmista, että pyydetty aika on ja omaisuuserän duraatio.
  • Verkkovirheet:[ Etäistuotteet voivat olla ladattavia. Käytä ennen kuin luot pikkukuvia.

Esimerkki omaisuuden esilastauksesta:

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
 }
}

Muokataan peukalon tulostus

AVASsetImageGenerator tarjoaa useita ominaisuuksia hienosäätää lähtökuvaa.

Enimmäiskoko

Rajoita luotu kuva tiettyyn rajauslaatikkoon käyttäen . Tämä vähentää muistin yläpintoja ja nopeuttaa suurten videoiden sukupolven nopeuttamista.

imageGenerator.maximumSize = CGSize(width: 640, height: 480)

Luotu kuva skaalataan sopimaan näihin mittoihin säilyttäen samalla kuvasuhteen.

Pyydetty aikatoleranssi

Oletuksena palauttaa tarkan kehyksen pyydettyyn aikaan (tai mahdollisimman lähelle). Nopeuden tarkkuutta voidaan vaihtaa asettamalla ja . Pikkukuvien osalta 0,5 sekunnin toleranssi on usein hyväksyttävä ja nopeampi:

imageGenerator.requestedTimeToleranceBefore = CMTime(seconds: 0.5, preferredTimescale: 600)
imageGenerator.requestedTimeToleranceAfter = CMTime(seconds: 0.5, preferredTimescale: 600)

Aukotila

valvoo, miten tuotettu kuva käsittelee puhdasta aukkoa vs. tuotantoaukko. Käytä reunapölyn poistamiseen ja puhtaamman pikkukuvan tuottamiseen:

imageGenerator.apertureMode = .cleanAperture

Muodonmuutosten soveltaminen

Jos haluat kääntää tai kääntää kuvaa (esim. tiettyä suuntaa varten), käytä Core Graphics -ohjelmistoa. Yksi lähestymistapa on ottaa raakakuva talteen ja sitten soveltaa CGAffineTransform -muotoa manuaalisesti. Vaihtoehtoisesti voit asettaa [] ]:een (kuten on esitetty) ja luottaa voimavaraan.

Useiden peukaloiden luominen tehokkaasti

Videoruudukoille, aikajanan pesulle tai tarinan esikatseluille tarvitaan usein kymmeniä pikkukuvia. Vältä soittamasta päälangan silmukaan . Sen sijaan käytä asynkronista menetelmää . Se käsittelee useita aikavaatimuksia tehokkaasti ja sisäistä rinnakkaisuutta tehokkaasti.

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")")
 }
}

Tämä menetelmä asteikot hyvin ja voit päivittää käyttöliittymän asteittain. Muista soittaa , jos käyttäjä jättää näytön ilmaiseksi resursseja.

Työskentely etävideoiden kanssa

Kun videon URL-osoite osoittaa etäpalvelimelle, sinun on odotettava, että omaisuuserä on täysin ladattu tai ainakin sen ratatiedot ovat saatavilla. Käytä asianmukaisia välimuistiopaketteja toistuvien latausten välttämiseksi.

let urlAsset = AVURLAsset(url: remoteURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
urlAsset.loadValuesAsynchronously(forKeys: ["tracks"]) {
 // Then create image generator and proceed
}

Tuotannossa sovellukset, harkita välimuistia levyllä niin, että toistuva pääsy samaan videoon ei uudelleen hakemaan kuvaa. Käytä tai tiedostopohjainen välimuisti käyttäen videon URL avain.

Välimuististrategia esimerkki

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)
 }
}

Yhdistä tämä kuvageneraattori välttää tarpeetonta työtä.

Suorituskyvyn huomioon ottaminen

Pienoiskuvien luominen on CPU-intensiivinen toiminto erityisesti korkean resoluution 4K-videoille.

  • Soita aina synkronoituja puheluita taustajonossa (esim. ).
  • Aseta kohtuullinen , jotta saadaan vähennettyä tulosteen kuvan mittoja. 320x240 koko riittää usein listan pikkukuviin.
  • Käytä , jotta generaattori voi ohittaa lähimmän kehyksen eikä ratkaista tarkkaa koodinpurkua.
  • Peru kaikki keskeneräiset analogiset sukupolvet, kun näkymä katoaa.
  • Näyttöä varten kokoelmanäkymässä, luoda pikkukuvia tarkka solun koko ja välttää uudelleenkokoa päälangan.

Integrointi Swift Concurrency (Async/Await)

Jos sovelluksesi on iOS 15+, voit kääriä estopuhelun jatkoksi puhtaalle async/await-koodille:

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)
 }
 }
 }
}

Kehittyneet muokkaukset

Esikatseluja videokoostumus

Jos videossasi käytetään (esim. vesileiman päällystys, värinsäätö), voit siirtää sen kuvageneraattorille:

imageGenerator.videoComposition = myVideoComposition

Luotu pikkukuva heijastaa yhdistettyä tulosta.

Luodaan peukalonnäkymiä live-kuville

Live-kuvia ovat videon ja kuvan yhdistelmä. Voit poimia peukalon videon taustasta, käyttää ja pyytää videon URL-osoitetta ennen sen syöttämistä AVFounducationiin.

Esteettömyys ja käyttäjäkokemus

Peukalot parantavat visuaalista skannausta, mutta tarjoavat aina tekstin vaihtoehdon VoiceOver-käyttäjille. Käytä kuvanäkymässä , jossa kuvataan videosisältöä, jos mahdollista.

imageView.isAccessibilityElement = true
imageView.accessibilityLabel = "Thumbnail of video: \(videoTitle)"

Ulkoiset resurssit

Syvemmät tiedot:

Päätelmät

Kun rakennat videon videon pienkuvageneraattorin AVFounducation-sovelluksella, saat täydellisen vapauden kuvan laadun, ajoituksen ja suorituskyvyn yli. Käyttämällä :a sekä synkronisesti että synkronoidusti, käsittelemällä virheitä ja välimuistin avulla voit tarjota saumattoman käyttäjäkokemuksen iOS-sovelluksessasi. Olitpa tekemisissä paikallisten tiedostojen tai etävideoiden kanssa, tässä käsitellyt tekniikat auttavat sinua tuottamaan teräviä, konteksti-ware-pikkukuvia nopeasti ja tehokkaasti.