LoginSignup
2
0

More than 1 year has passed since last update.

LivePhotosをmovとjpegから作る

Posted at

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 固有の機能なので活用して行きたいです
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0