- 이번에는 애플 생태계(iOS, iPadOS, macOS)에서는 유용하게 사용되는 Live Photo에 대해 알아보겠다.
- Live Photo는 기본적으로 사진인데, 촬영 순간의 앞뒤 장면도 담겨있다는 특징이 있다.
- Live Photo를 저장하고 불러오는 방법, 그리고 Video 포맷으로 변환하는 방법을 알아보겠다.
Live Photo 저장하기
- Live Photo의 구조를 들여다보면, 하나의 Live Photo는 하나의 사진과 하나의 영상으로 이뤄져있다.
- 그래서 Live Photo를 저장한다고 하면, 한 쌍의 사진과 영상을 저장하는 것과 같다.
- 이 부분에서는 Live Photo를 사용자의 사진보관함에 저장하는 방법을 알아보겠다.
var livePhotoResource: (pairedImage: URL, pairedVideo: URL)?
self.saveToLibrary(livePhotoResource) { (success) in
if success {
print("라이브포토가 사진에 저장되었습니다")
} else {
print("에러가 발생했습니다")
}
}
- livePhotoResource는 한 쌍의 사진과 영상을 묶은 tuple 타입이다.
- 다음과 같이 saveToLibrary function에 임의의 livePhotoResource를 넣어 저장하면 된다.
func saveToLibrary(_ resources: LivePhotoResources, completion: @escaping (Bool) -> Void) {
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetCreationRequest.forAsset()
let options = PHAssetResourceCreationOptions()
creationRequest.addResource(with: PHAssetResourceType.pairedVideo, fileURL: resources.pairedVideo, options: options)
creationRequest.addResource(with: PHAssetResourceType.photo, fileURL: resources.pairedImage, options: options)
}, completionHandler: { (success, error) in
if error != nil {
print(error as Any)
}
completion(success)
})
}
- saveToLibrary는 이렇게 생겼는데, 결국 한 쌍의 사진과 영상을 사진보관함에 추가하는 방식이다.
Live Photo 불러오기
- 이번에는 Live Photo를 사진보관함으로부터 불러오는 방법에 대해 알아보겠다.
let livePhotoVideoURL: URL?
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? NSString {
if mediaType == kUTTypeLivePhoto {
guard let livePhoto = info[UIImagePickerController.InfoKey.livePhoto] as? PHLivePhoto else { return }
self.extractResources(from: livePhoto, to: someURL, completion: { resources in
self.livePhotoVideoURL = resources?.pairedVideo
})
}
}
}
- 우선, 사진보관함의 내용물을 불러오기 위해 Image Picker를 사용해야 한다.
- Image Picker는 사용할줄 안다고 가정하고 넘어가겠다.
- Image Picker의 info를 통해 불러온 미디어가 Live Photo이면, 이를 PHLivePhoto로 캐스팅한다.
- 캐스팅해서 얻은 값을 extractResources에 넣고, 나온 값이 해당 Live Photo의 URL이다.
func extractResources(from livePhoto: PHLivePhoto, to directoryURL: URL, completion: @escaping (LivePhotoResources?) -> Void) {
let assetResources = PHAssetResource.assetResources(for: livePhoto)
var keyPhotoURL: URL?
var videoURL: URL?
for resource in assetResources {
let buffer = NSMutableData()
let options = PHAssetResourceRequestOptions()
PHAssetResourceManager.default().requestData(for: resource, options: options, dataReceivedHandler: { (data) in
buffer.append(data)
}) { (error) in
if error == nil {
if resource.type == .pairedVideo {
videoURL = self.saveAssetResource(resource, to: directoryURL, resourceData: buffer as Data)
} else {
keyPhotoURL = self.saveAssetResource(resource, to: directoryURL, resourceData: buffer as Data)
}
} else {
print(error as Any)
}
}
}
completion((keyPhotoURL!, videoURL!))
}
- extractResources는 이렇게 생겼다.
- PHAssetResourceManager의 default()의 requestData 이 부분이 핵심이다.
- videoURL과 keyPhotoURL을 받아, completion을 통해 튜플 값으로 넘겨주는 것이다.
Live Photo를 Video로
- 위 내용들을 잘 이해했다면, Live Photo를 Video를 변환하는 것은 의외로 간단하다.
if FileManager.default.fileExists(atPath: livePhotoVideoURL.path) {
PHPhotoLibrary.shared().performChanges({
let videoURL = Foundation.URL(fileURLWithPath: livePhotoVideoURL.path)
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
}) { (success, error) -> Void in
if success {
print("비디오가 사진에 저장되었습니다")
} else {
print(error.debugDescription)
}
}
}
- 앞서, 사진보관함으로부터 Live Photo의 Paired Video URL을 불러왔었다.
- 해당 URL을 PHPhotoLibrary에 저장하면 끝이다.