如何将 AVMutableComposition 传递给 AVAssetWriter
How to pass AVMutableComposition to AVAssetWriter
现在我使用 AVExportSession 从 AVMixComposition 中得到一个 url。 HighestQuality 看起来不错,但文件太大,15 秒的视频是 27 MB。 MediumQuality 看起来很糟糕,但文件大小只有 1 MB。我知道我必须使用 AVAssetWriter 并调整比特率来找到中间立场。
问题是我想不出一种方法来从 AVMixComposition 获取 url 而不使用 使用 AVExportSession 传递给 AVAssetWriter。
我要做的是使用 exportSession 保存视频,获取 url,将其传递给 assetWriter,设置比特率,然后从那里进行压缩。生成的 .mp4(必须为 .mp4)assetWriter 视频不会压缩原始的 exportSession videoURL。它实际上更大,这违背了目的。
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
})
}
不需要使用url,你可以将mixComposition传递给AVPlayerItem
> AVPlayer
> player.currentItem.asset
:
let mixComposition = AVMutableComposition()
// ...
passMixToAssetWriter(mixComposition)
func passMixToAssetWriter(_ mixComposition: AVMutableComposition) {
let item = AVPlayerItem(asset: composition)
let player = AVPlayer()
player.replaceCurrentItem(with: item)
guard let currentItem = player.currentItem else { return }
let asset = currentItem.asset
guard let videoTrack = asset.tracks(withMediaType: AVMediaType.video).first else { return }
guard let audioTrack = asset.tracks(withMediaType: AVMediaType.audio).first else return }
// raise the bit rate to 11000000
let videoSettings:[String:Any] = [AVVideoCompressionPropertiesKey: [AVVideoAverageBitRateKey: 1100000], 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
})
}
现在我使用 AVExportSession 从 AVMixComposition 中得到一个 url。 HighestQuality 看起来不错,但文件太大,15 秒的视频是 27 MB。 MediumQuality 看起来很糟糕,但文件大小只有 1 MB。我知道我必须使用 AVAssetWriter 并调整比特率来找到中间立场。
问题是我想不出一种方法来从 AVMixComposition 获取 url 而不使用 使用 AVExportSession 传递给 AVAssetWriter。
我要做的是使用 exportSession 保存视频,获取 url,将其传递给 assetWriter,设置比特率,然后从那里进行压缩。生成的 .mp4(必须为 .mp4)assetWriter 视频不会压缩原始的 exportSession videoURL。它实际上更大,这违背了目的。
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
})
}
不需要使用url,你可以将mixComposition传递给AVPlayerItem
> AVPlayer
> player.currentItem.asset
:
let mixComposition = AVMutableComposition()
// ...
passMixToAssetWriter(mixComposition)
func passMixToAssetWriter(_ mixComposition: AVMutableComposition) {
let item = AVPlayerItem(asset: composition)
let player = AVPlayer()
player.replaceCurrentItem(with: item)
guard let currentItem = player.currentItem else { return }
let asset = currentItem.asset
guard let videoTrack = asset.tracks(withMediaType: AVMediaType.video).first else { return }
guard let audioTrack = asset.tracks(withMediaType: AVMediaType.audio).first else return }
// raise the bit rate to 11000000
let videoSettings:[String:Any] = [AVVideoCompressionPropertiesKey: [AVVideoAverageBitRateKey: 1100000], 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
})
}