Right now I get a url from a AVMixComposition using AVExportSession. HighestQuality looks great but the file size is too big, a 15 sec video is 27 mb. MediumQuality looks horrible but the file size is only 1 mb. I know I have to use AVAssetWriter and play with the bit rate to find a middle ground.
The problem is I can't figure out a way to get a url from an AVMixComposition without using AVExportSession to pass to the AVAssetWriter.
What I have to do is save the video using exportSession, get the url, pass it to assetWriter, set the bit rate, and then compress it from there. The resulting .mp4 (has to .mp4) assetWriter video doesn't compress the original exportSession videoURL. It's actually bigger which defeats the purpose.
let mixComposition = AVMutableComposition()
// ...
guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else { return }
exporter.outputURL = outputFileURL
exporter.outputFileType = AVFileType.mp4
exporter.shouldOptimizeForNetworkUse = true
exporter.exportAsynchronously {
// ...
let data = try! Data(contentsOf: outputFileURL)
print("compression size: \(Double(data.count / 1048576)) mb") // 27 mb
DispatchQueue.main.async { ...
guard let videoURL = exporter.outputURL else { return }
self.passUrlToAssetWriter(urlToCompress: videoURL)
}
func passUrlToAssetWriter(urlToCompress: URL) {
let asset = AVAsset(url: urlToCompress)
guard let videoTrack = asset.tracks(withMediaType: AVMediaType.video).first else { return }
guard let audioTrack = asset.tracks(withMediaType: AVMediaType.audio).first else return }
// dropping the bit rate made no difference
let videoSettings:[String:Any] = [AVVideoCompressionPropertiesKey: [AVVideoAverageBitRateKey: 250000], AVVideoCodecKey: AVVideoCodecType.h264, AVVideoHeightKey: videoTrack.naturalSize.height, AVVideoWidthKey: videoTrack.naturalSize.width]
let audioSettings: [String:Any] = [AVFormatIDKey : kAudioFormatMPEG4AAC, AVNumberOfChannelsKey : 2, AVSampleRateKey : 44100.0, AVEncoderBitRateKey: 128000]
assetWriter = try! AVAssetWriter(outputURL: myOutputURL, fileType: AVFileType.mp4)
// everything else to configure assetWriter ...
assetWriter?.finishWriting(completionHandler: {
let data = try! Data(contentsOf: self.assetWriter!.outputURL)!)
print("compression size: \(Double(data.count / 1048576)) mb") // 27.5 mb, it's actually bigger than the exporter file size
})
}