वीडियो थंबनेल आधुनिक मीडिया समृद्ध अनुप्रयोगों का एक कोनेस्टोन है, जो उपयोगकर्ताओं को पूर्ण वीडियो खेलने की आवश्यकता के बिना एक त्वरित दृश्य पूर्वावलोकन प्रदान करता है। आईओएस विकास में, एवीफ़ाउंडेशन थंबनेल छवियों को निकालने के लिए सबसे अधिक प्रदर्शनकारी और लचीला उपकरण प्रदान करता है। यह लेख एक कस्टम वीडियो थंबनेल जनरेटर के निर्माण के माध्यम से चलता है जो वास्तविक दुनिया के परिदृश्यों को संभाल सकता है - स्थानीय और दूरस्थ फ़ाइलों, कैशिंग, त्रुटि हैंडलिंग और प्रदर्शन ट्यूनिंग सहित - स्विफ्ट और एवीफ़ाउंडेशन का उपयोग करता है।

The sorry of the sorry of the sorry of the sorry.

AVFoundation is Apple's प्राइमरी फ्रेमवर्क for working with audiovisual media. The most important class is the most important class of the most important class.

  • AVAsset: एक समयबद्ध ऑडियोविज़ुअल परिसंपत्ति (एक स्थानीय या दूरस्थ वीडियो) का प्रतिनिधित्व करता है। इसमें ट्रैक जानकारी, अवधि और मेटाडाटा शामिल है।
  • AVAssetImageGenerator: विशिष्ट समय अंतराल पर परिसंपत्ति से CGImageRefs प्राप्त करने के तरीके प्रदान करता है। यह वीडियो अभिविन्यास का सम्मान करता है, रंग अंतरिक्ष समायोजन लागू करता है, और अतुल्यकालिक थोक पीढ़ी का समर्थन करता है।

इन वर्गों का उपयोग करके सीधे छवि के आकार, समय सटीकता और परिवर्तन पर पूर्ण नियंत्रण देता है, जो यूआईकेआईटी शॉर्टकट के विपरीत अक्सर कॉन्फ़िगरेशन विकल्पों को छिपाता है।

परियोजना की स्थापना

अपने स्विफ्ट फ़ाइल में AVFoundation को आयात करके शुरू करें:

import AVFoundation

आपको उत्पन्न हुई छवियों को प्रदर्शित करने के लिए भी यूआईकेट की आवश्यकता है। एक यूआरएल से बनाएं। स्थानीय फ़ाइलों के लिए, ] का उपयोग करें। दूरस्थ वीडियो के लिए, का उपयोग करें और सुनिश्चित करें कि परिसंपत्ति को शुरू किया जा सकता है:

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

एक एकल थंबनेल उत्पन्न करना

एक निर्दिष्ट समय में एक थंबनेल उत्पन्न करने के लिए, एक और ] का निर्माण करें। यह विधि तुल्यकालिक है और इसे यूआई को अवरुद्ध करने से बचने के लिए मुख्य धागे को बंद करना चाहिए।

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

]Important: Setting to यह सुनिश्चित करता है कि परिणामी छवि वीडियो के घूर्णन मेटाडाटा (पोर्ट्रेट बनाम परिदृश्य) का सम्मान करती है। इसके बिना, एक ईमानदार वीडियो बग़ैर दिखाई दे सकता है।

सही समय का चयन

थंबनेल अक्सर वीडियो की शुरुआत में लिया जाता है, लेकिन उस समय का उपयोग करने पर विचार करें जो उस विषय पर निर्भर करता है-जैसे, 10% अवधि में। एक सार्थक समय बिंदु प्राप्त करने के लिए, परिसंपत्ति की अवधि को क्वेरी करें:

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

हैंडलिंग त्रुटियां और एज मामले

थंबनेल पीढ़ी कई कारणों से विफल हो सकती है। हमेशा त्रुटियों को सुंदर ढंग से संभालती है और गिरने वाली यूआई प्रदान करती है।

  • ]Invalid परिसंपत्ति: वीडियो भ्रष्ट या URL अप्रगम्य हो सकता है।
  • ]Missing video track: कुछ परिसंपत्तियों में केवल ऑडियो होता है; ]]]]] ]]]]]] ]]]]]Mising video track: कुछ संपत्तियों में केवल ऑडियो होते हैं; ]]]]]]] ]]]]]]
  • ]]]]]]]]]]]]]]]]][[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]][[[[[[[[[[[FLT[[[[[[[[[[[FLT:]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
  • ]Network त्रुटियों: दूरस्थ संपत्ति लोड करने में विफल हो सकती है। [[FLT: 13]] का उपयोग थंबनेल पैदा करने से पहले।

संपत्तियों को पूर्वभार देने का उदाहरण:

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

थंबनेल आउटपुट को अनुकूलित करना

AVAssetImageGenerator उत्पादन छवि को ठीक करने के लिए कई गुण प्रदान करता है।

अधिकतम आकार

उत्पन्न छवि को एक विशिष्ट सीमा बॉक्स में प्रतिबंधित करें, जिसका उपयोग किया जाता है। यह स्मृति को कम करता है और बड़े वीडियो के लिए पीढ़ी को गति देता है।

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

उत्पन्न छवि को इन आयामों के भीतर फिट करने के लिए स्केल किया जाएगा जबकि पहलू अनुपात को संरक्षित किया जाएगा।

अनुरोधित समय सहिष्णुता

डिफ़ॉल्ट रूप से, ] अनुरोधित समय (या संभव के रूप में करीब) पर सटीक फ्रेम लौटाता है। आप सेटिंग और द्वारा गति के लिए सटीकता का व्यापार कर सकते हैं। थंबनेल के लिए, 0.5 सेकंड की सहिष्णुता अक्सर स्वीकार्य और तेज़ होती है:

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

एपर्चर मोड

]] नियंत्रित करता है कि कैसे उत्पन्न छवि स्वच्छ एपर्चर बनाम उत्पादन एपर्चर को संभालती है। ] का उपयोग किनारे धूल को हटाने और क्लीनर थंबनेल का उत्पादन करने के लिए करें:

imageGenerator.apertureMode = .cleanAperture

परिवर्तन लागू करना

यदि आपको छवि को घुमाने या फ्लिप करने की आवश्यकता है (उदाहरण के लिए, एक विशिष्ट अभिविन्यास के लिए), कोर ग्राफिक्स का उपयोग बदलता है। एक दृष्टिकोण कच्चे छवि को कैप्चर करना है और फिर मैन्युअल रूप से CGAffineTransform लागू करना है। वैकल्पिक रूप से, आप ] को ] (जैसा कि दिखाया गया है) सेट कर सकते हैं और परिसंपत्ति के प्राकृतिक अभिविन्यास पर भरोसा कर सकते हैं।

कुशलतापूर्वक उत्पन्न करने वाले एकाधिक थंबनेल

वीडियो ग्रिड, टाइमलाइन स्क्रबिंग, या स्टोरीबोर्ड पूर्वावलोकन के लिए, आपको अक्सर दर्जनों थंबनेल की आवश्यकता होती है। मुख्य धागे पर एक लूप में को बुलाने से बचें। इसके बजाय, अतुल्यकालिक विधि का उपयोग करें। यह कई बार अनुरोधों को कुशलतापूर्वक संसाधित करता है, आंतरिक समानांतरवाद का लाभ उठाता है।

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

यह विधि अच्छी तरह से पैमाने पर है और आपको यूआई को वृद्धि से अपडेट करने देता है। [[FLT::29]]] को कॉल करने के लिए याद रखें यदि उपयोगकर्ता स्क्रीन को मुफ्त संसाधनों में छोड़ देता है।

दूरस्थ वीडियो के साथ काम करना

जब वीडियो यूआरएल एक दूरस्थ सर्वर पर इंगित करता है, तो आपको उस परिसंपत्ति को पूरी तरह से लोड करने या कम से कम इसकी ट्रैक जानकारी उपलब्ध होने का इंतजार करना होगा। बार-बार डाउनलोड से बचने के लिए उपयुक्त कैशिंग हेडर के साथ का उपयोग करें।

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

उत्पादन ऐप के लिए, डिस्क पर कैशिंग थंबनेल पर विचार करें ताकि उसी वीडियो तक पहुंच को दोहराया गया छवि को फिर से नहीं बदलता। का उपयोग करें या एक कुंजी के रूप में वीडियो यूआरएल का उपयोग करके फ़ाइल-आधारित कैश।

कैचिंग रणनीति उदाहरण

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

इसे अनावश्यक काम से बचने के लिए छवि जनरेटर के साथ मिलाएं।

प्रदर्शन विचार

उत्पन्न थंबनेल एक सीपीयू-गहन ऑपरेशन है, विशेष रूप से उच्च-रिज़ॉल्यूशन 4K वीडियो के लिए। इन सर्वोत्तम प्रथाओं का पालन करें:

  • हमेशा पृष्ठभूमि कतार (जैसे, ] पर सिंक्रोनस कॉल करें।
  • आउटपुट छवि आयाम को कम करने के लिए एक उचित सेट करें। 320x240 का आकार अक्सर सूची थंबनेल के लिए पर्याप्त होता है।
  • ] का प्रयोग करने के लिए जनरेटर को सटीक डीकोड को हल करने के बजाय निकटतम फ्रेम को छोड़ने की अनुमति देता है।
  • जब दृश्य गायब हो जाता है तो किसी भी घटना को रद्द कर देता है।
  • एक संग्रह दृष्टिकोण में प्रदर्शित करने के लिए, सटीक सेल आकार पर थंबनेल उत्पन्न करें और मुख्य धागे पर आकार देने से बचें।

स्विफ्ट कंसर्रेंसी (Async/Await) के साथ एकीकृत

यदि आपका ऐप iOS 15+ को लक्षित करता है, तो आप स्वच्छ async/await कोड के लिए एक निरंतरता में अवरुद्ध कॉल को लपेट सकते हैं:

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

उन्नत अनुकूलन

वीडियो संरचना के साथ थंबनेल

यदि आपका वीडियो एक ] का उपयोग करता है (उदाहरण के लिए, वॉटरमार्क ओवरले, रंग समायोजन), तो आप इसे छवि जनरेटर में पास कर सकते हैं:

imageGenerator.videoComposition = myVideoComposition

उत्पन्न थंबनेल मिश्रित उत्पादन को प्रतिबिंबित करेगा।

लाइव तस्वीरें के लिए थंबनेल उत्पन्न करना

लाइव तस्वीरें एक वीडियो और एक अभी भी छवि का संयोजन है। अंतर्निहित वीडियो से एक थंबनेल निकालने के लिए, का उपयोग करें और इसे AVFoundation में खिलाने से पहले एक वीडियो URL का अनुरोध करें।

अभिगम्यता और उपयोगकर्ता अनुभव

थंबनेल दृश्य स्कैनिंग को बढ़ाता है, लेकिन हमेशा वॉयसओवर उपयोगकर्ताओं के लिए एक टेक्स्ट विकल्प प्रदान करता है। छवि दृश्य पर का उपयोग करें, यदि संभव हो तो वीडियो सामग्री का वर्णन करें।

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

बाह्य संसाधन

गहरी समझ के लिए, निम्नलिखित सलाह लें:

निष्कर्ष

AVFoundation के साथ एक कस्टम वीडियो थंबनेल जनरेटर का निर्माण आपको छवि की गुणवत्ता, समय और प्रदर्शन पर पूरी स्वतंत्रता देता है। का लाभ उठाकर दोनों तुल्यकालिक और अतुल्यकालिक रूप से, हैंडलिंग त्रुटियों और कैशिंग परिणाम, आप अपने iOS ऐप में एक सहज उपयोगकर्ता अनुभव प्रदान कर सकते हैं। चाहे आप स्थानीय फ़ाइलों या रिमोट वीडियो को संसाधित कर रहे हों, यहां शामिल तकनीकें आपको कुरकुरकुरा, संदर्भ-जाने वाले थंबनेल को जल्दी और कुशलतापूर्वक बनाने में मदद करेगी।