Save Live Photos from mov & jpeg on iOS App

f.yuki
2 min readAug 3, 2021

--

You can save mov and jpeg as LivePhotos.
Both mov and jpeg need to be configured with metadata.
You can use AVAssetWriter and CoreImage to set the metadata for each.

Example

https://github.com/fuziki/VideoCreator

AVAssetWriter for mov

Set the content identifier for the file 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 is ”com.apple.quicktime.content.identifier”.

Create and add a metadata track.

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)

Write metadata for start time, end time, and still image time.
Must be written after recording starts.

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

Creating jpeg data with CoreImage

jpeg will set the content identifier to the key of “17”.
Use CIImage.settingProperties to set the properties.
Use CIContext.jpegRepresentation to get the jpeg data from CIImage.

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: [:])!

Save as Live Photos

Use PHPhotoLibrary to save as Live Photos.
Save mov as .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)
}

--

--

f.yuki

Hello! I’m yuki! ios, swift, golang, unity etc…