Table of Contents
비디오 엄지나일은 현대 미디어 풍부한 응용 분야의 코너스톤으로, 사용자가 전체 비디오를 재생할 필요없는 빠른 시각 미리보기를 제공합니다. iOS 개발에서 AVFoundation은 엄지나일 이미지를 추출하기위한 가장 수행 및 유연한 도구를 제공합니다. 이 문서는 로컬 및 원격 파일, 캐싱, 오류 처리 및 성능 조정을 포함하여 실제 시나리오를 처리 할 수있는 사용자 정의 비디오 엄지나일 발전기를 구축하여 걸어 걷습니다. Swift 및 AVFoundation.
Thumbnail Generation의 AVFoundation 역할 이해
AVFoundation은 시청각 미디어와 함께 일하는 Apple의 기본 프레임 워크입니다. 썸네일 세대의 경우, 주요 클래스는 ]AVAsset과 ]AVAssetImageGenerator입니다.
- AVAsset: 시간된 오디오 자산(국적 또는 원격 비디오)를 나타냅니다. 이 트랙 정보, 기간 및 메타데이터가 포함되어 있습니다.
- AVAssetImageGenerator: 특정 시간 간격에 자산에서 CGImageRefs를 얻는 방법을 제공합니다. 그것은 비디오 방향을 존중하고, 색 공간 조정을 적용하고, 비동기 대량 생성을 지원합니다.
이 클래스를 사용하여 이미지 크기, 시간 정확도, 변환을 통해 전체 제어를 제공합니다. UIKit Shortcuts와는 달리 구성 옵션을 숨깁니다.
프로젝트 설정
Swift 파일로 AVFoundation을 가져 오기로 시작:
import AVFoundation
생성된 이미지를 표시하려면 UIKit가 필요합니다. URL에서 을 만듭니다. 로컬 파일에 대해서는 를 사용하십시오. 리모트 동영상의 경우 를 사용하며, 자산을 초기화할 수 있습니다.
// 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)
단일 Thumbnail 생성
지정된 시간에 하나의 엄밀을 생성하려면 ]을 만들고 ]를 호출합니다. 이 방법은 동기이며 UI를 차단하는 데 메인 스레드를 차단하기 위해 실행되어야합니다.
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: ] ]]]는 영상의 교체 메타데이터 (초상 vs. 풍경)를 존중합니다. 이 없이, 밝은 영상은 보도될 수 있습니다.
오른쪽 시간 선택
Thumbnails는 종종 비디오의 시작 부분에 촬영되지만, 콘텐츠를 나타내는 시간을 고려합니다. 예를 들어, 10 %는 지속 시간입니다. 의미있는 시간을 얻으려면 자산의 지속 시간을 쿼리하십시오.
let duration = asset.duration
let midTime = CMTimeMultiplyByFloat64(duration, multiplier: 0.1)
처리 오류 및 Edge 케이스
Thumbnail 세대는 여러 가지 이유로 실패 할 수 있습니다. 항상 과실을 처리하고 fallback UI를 제공합니다.
- 무효 자산:비디오는 손상되거나 URL이 제한될 수 있습니다.
- Misssing video track:] 일부 자산은 오디오만 포함; ].
- ]시간의 경계: 요청된 시간을 보장하는 것은 과 자산의 지속 시간입니다.
- Network error: Remote Assets는 로드에 실패할 수 있습니다. 썸네일 생성하기 전에 를 사용하십시오.
preloading 자산의 예:
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
}
}
사용자 정의 Thumbnail 출력
AVAssetImageGenerator는 출력 이미지가 잘 쓰일 수 있는 몇몇 특성을 제안합니다.
최대 크기
생성된 이미지는 ]를 사용하여 특정한 경계 상자로 제한합니다. 이것은 큰 영상을 위한 기억 머리 위와 속도를 감소시킵니다.
imageGenerator.maximumSize = CGSize(width: 640, height: 480)
생성된 이미지는 이 차원 안에 적합하기 위하여 종횡비를 보존하는 동안 확장될 것입니다.
위탁된 시간 포용력
기본적으로 ]는 요청된 시간에 정확한 프레임을 반환합니다 (또는 가능한 한 가까이). 과 ]]을 설정하여 속도를 위해 정확도를 거래 할 수 있습니다. thumbnails의 경우 0.5 초의 허용 오차는 종종 허용되고 빠릅니다.
imageGenerator.requestedTimeToleranceBefore = CMTime(seconds: 0.5, preferredTimescale: 600)
imageGenerator.requestedTimeToleranceAfter = CMTime(seconds: 0.5, preferredTimescale: 600)
가늠구멍 형태
] 생성 된 이미지가 깨끗한 조리대를 처리하는 방법을 제어합니다. 생산 노출. 가장자리 먼지를 제거하고 깨끗한 엄밀을 생산하기 위해 를 사용합니다.
imageGenerator.apertureMode = .cleanAperture
Transformations 적용
이미지를 회전하거나 플립 할 필요가 있다면 (예 : 특정 방향), 코어 그래픽 변환을 사용합니다. 한 가지 접근법은 원시 이미지를 캡처하고 수동으로 CGAffineTransform을 적용합니다. 또는 [[FLT : 24]]]를 [[FLT : 25]]]로 설정하고 자산의 자연 방향을 신뢰합니다.
여러 가지 Thumbnails를 효율적으로 생성
비디오 그리드, 타임 라인 스크레이빙, 또는 스토리 보드 미리보기를 위해, 당신은 종종 엄지손의 수십 가지가 필요합니다. ]]를 호출하는 피하십시오. 대신, 비동기적인 방법을 사용합니다 . 그것은 여러 시간 요청을 효율적으로 처리하고 내부 병렬을 활용합니다.
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")")
}
}
이 방법은 잘 스케일하고 UI를 incrementally 업데이트 할 수 있습니다. 사용자가 스크린을 무료 리소스로 나타낸 경우 ]를 호출하는 것을 기억하십시오.
원격 동영상 작업
원격 서버에 비디오 URL 포인트가 있을 때, 완전히 로드되거나 적어도 트랙 정보를 사용할 수 있도록 자산을 기다릴 필요가 있습니다. 반복 다운로드를 방지하기 위해 적절한 캐싱 헤더를 사용하여 ]를 사용하십시오.
let urlAsset = AVURLAsset(url: remoteURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
urlAsset.loadValuesAsynchronously(forKeys: ["tracks"]) {
// Then create image generator and proceed
}
생산 앱의 경우 디스크에 캐싱 엄밀을 고려하여 동일한 비디오에 대한 액세스를 반복하는 것은 이미지를 재 ‐fetch하지 않습니다. 또는 비디오 URL을 키로 사용하여 파일 기반 캐시를 사용하십시오.
캐싱 전략 예제
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)
}
}
이 이미지를 결합하여 중복 작업을 피하기 위해 생성기.
성능 고려
thumbnails 생성은 CPU ‐ 집중적인 가동, 특히 고해상도 4K 비디오를 위해입니다. 이 모범 사례를 따르십시오:
- 항상 배경 큐에 비동기 통화를 수행 (예를 들어, ).
- 출력 이미지 크기를 줄이기 위해 합리적인 를 설정합니다. 320x240의 크기는 종종 목록 썸네일에 충분합니다.
- ]를 사용하여 발전기를 사용하여 정확한 디코드를 해결하는 대신 가장 가까운 프레임을 건너 뛸 수 있습니다.
- 보기가 사라질 때 비동기 발생을 방지하십시오.
- 수집보기에 표시를 위해 정확한 셀 크기에 엄밀하게 생성하고 주요 스레드에 재조정을 방지합니다.
Swift Concurrency (Async/Await)와 통합
앱이 iOS 15+를 대상으로 하는 경우, 깨끗한 async/await 코드를 위한 continuation에 있는 차단 통화를 감싸는 수 있습니다:
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)
}
}
}
}
고급 사용자 정의
Thumbnails 와 비디오 구성
비디오가 (예 : 워터 마크 오버레이, 색상 조정)을 사용한다면 이미지 생성기로 전달할 수 있습니다.
imageGenerator.videoComposition = myVideoComposition
생성 된 썸네일은 복합 출력을 반영합니다.
라이브 사진에 대한 Thumbnails 생성
라이브 사진은 비디오와 여전히 이미지의 조합입니다. 언더리 비디오에서 엄밀을 추출하려면 ]을 사용하며 AVFoundation로 먹이기 전에 비디오 URL을 요청하십시오.
접근성 및 사용자 경험
Thumbnails는 시각적 인 스캐닝을 향상하지만 항상 VoiceOver 사용자를위한 텍스트 대안을 제공합니다. 이미지보기에 ]를 사용하여 비디오 콘텐츠를 설명 할 수 있습니다.
imageView.isAccessibilityElement = true
imageView.accessibilityLabel = "Thumbnail of video: \(videoTitle)"
외부 자료
더 깊은 이해를 위해, 뒤에 오는 상담:
관련 기사
AVFoundation을 가진 사용자 정의 비디오 엄밀 발전기를 구축하면 이미지 품질, 타이밍 및 성능에 대한 완벽한 자유를 제공합니다. 를 레버리지로 활용하면 동시 및 비동기적으로 처리 오류 및 캐싱 결과가 가능하며 iOS 앱에서 원활한 사용자 경험을 제공할 수 있습니다. 로컬 파일이나 원격 비디오를 처리하는 경우, 이 기술을 통해 crisp, context-aware thumbnails를 신속하고 효율적으로 생산할 수 있습니다.