LivePhotos を mov と jpeg から作る
- mov と jpeg を LivePhotos として保存できます
- 動画ファイルの時間や、mov と jepg にそれぞれメタデータの設定が必要です
- AVAssetWriter と CoreImage を使って、それぞれのメタデータを設定する事が可能です
サンプルアプリ
- リポジトリはこちらです
LivePhotos として保存できる条件
- mov と jpeg に共通の content identifier を設定する必要があります
mov を作成する AVAssetWriter の設定
- ファイルのメタデータに content identifier を設定します
- assetWriter.metadata に設定します
let assetWriter = try AVAssetWriter(outputURL: url, fileType: fileType)
let item = AVMutableMetadataItem()
item.key = AVMetadataKey.quickTimeMetadataKeyContentIdentifier as NSString
item.keySpace = AVMetadataKeySpace.quickTimeMetadata
item.value = contentIdentifier as NSString
item.dataType = kCMMetadataBaseDataType_UTF8 as String
assetWriter.metadata = [item]
-
AVMetadataKey.quickTimeMetadataKeyContentIdentifier
は"com.apple.quicktime.content.identifier"
のようです -
メタデータトラックを作成して追加します
let spec : NSDictionary = [
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.apple.quicktime.still-image-time",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_SInt8
]
var desc : CMFormatDescription? = nil
CMMetadataFormatDescriptionCreateWithMetadataSpecifications(allocator: kCFAllocatorDefault,
metadataType: kCMMetadataFormatType_Boxed,
metadataSpecifications: [spec] as CFArray,
formatDescriptionOut: &desc)
let input = AVAssetWriterInput(mediaType: .metadata, outputSettings: nil, sourceFormatHint: desc)
let adaptor = AVAssetWriterInputMetadataAdaptor(assetWriterInput: input)
assetWriter.add(adaptor.assetWriterInput)
- 開始時刻と終了時刻と still image time のメタデータを書き込みます
- 録画中に書き込む必要があるようです
let item = AVMutableMetadataItem()
item.key = "com.apple.quicktime.still-image-time" as NSString
item.keySpace = AVMetadataKeySpace.quickTimeMetadata
item.value = 0 as NSNumber
item.dataType = kCMMetadataBaseDataType_SInt8 as String
let timeRange = CMTimeRange(start: startTime, end: latestTime)
metadataAdaptor.append(AVTimedMetadataGroup(items: [item], timeRange: timeRange))
CoreImage を使った jpeg の Data の作成
- jpeg は "17" のキーに content identifier を設定する必要があるようです
- CIImage.settingProperties を使って、プロパティを設定します
- CIContext.jpegRepresentation を使って、CIImage から jpeg の Data を取得します
let ci: CIImage = ~~~~~
let context = CIContext()
let properties: [CFString : Any] = [kCGImagePropertyMakerAppleDictionary: ["17": contentIdentifier]]
let propertiedCi = ci.settingProperties(properties)
let jpegData = context.jpegRepresentation(of: propertiedCi, colorSpace: CGColorSpace(name: CGColorSpace.sRGB)!, options: [:])!
Live Photos の保存
- PHPhotoLibrary を使って Live Photos として保存します
- mov を .pairedVideo として保存します
try PHPhotoLibrary.shared().performChangesAndWait {
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, data: jpegData, options: nil)
let videoOptions = PHAssetResourceCreationOptions()
videoOptions.shouldMoveFile = true
request.addResource(with: .pairedVideo, fileURL: videoUrl, options: videoOptions)
}
おわりに
- Live Photosはなかなかドキュメントを見つけられず苦心しました
- PHPhotoLibrary のエラーも情報が落ちないので、AVCapturePhotoOutput の出力と見比べたり差し替えたりすることで、コンストラクタのオプションだと jpeg の設定で出来ていないことに気付いたり、など大変でした
- Live Photos は iOS 固有の機能なので活用して行きたいです