将 AVAsset 压缩并编码为 mp4
Compressing and encoding an AVAsset to mp4
我正在尝试压缩 AVAsset
以降低质量,然后将其导出为 mp4。输入资产可以是相机胶卷允许的任何类型的视频。
我 运行 遇到的问题是,当我尝试将资产导出到 AVAssetExportPresetMediumQuality
时,当输入最初是 mp4 文件时,它在第一个保护语句处失败。但是,如果我将其更改为 AVAssetExportPresetPassthrough
它可以工作但不会压缩文件。对于 compressing/encoding 最初可能是 .mov 或 .mp4 的资产,是否有单向解决方案?
func encodeVideo(asset: AVAsset, completionHandler: @escaping (URL?, String?) -> ()) {
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else {
completionHandler(nil, nil)
return
}
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("compressed-video.mp4")
if FileManager.default.fileExists(atPath: filePath.path) {
do {
try FileManager.default.removeItem(at: filePath)
} catch {
completionHandler(nil, nil)
}
}
exportSession.outputURL = filePath
exportSession.outputFileType = .mp4
exportSession.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: asset.duration)
exportSession.timeRange = range
exportSession.exportAsynchronously {
switch exportSession.status {
case .failed:
print("Conversion Failed")
completionHandler(nil, exportSession.error?.localizedDescription)
case .cancelled:
print("Conversion Cancelled")
completionHandler(nil, exportSession.error?.localizedDescription)
case .completed:
completionHandler(exportSession.outputURL, nil)
default: break
}
}
}
经过进一步测试和研究,这似乎是模拟器(Xcode 11.1 和 iPhone 11 Pro 模拟器,iOS 13.1)的一个 issue/possible 错误。不确定这是否扩展到其他模拟器,但上面使用 AVAssetExportPresetMediumQuality
的代码在我的设备测试中有效。
我看到你回复你的问题说是模拟器的问题。我的建议是在设备上测试 AVFoundation 进程。模拟器并不总是配备足够的设备来处理这些情况。此外,设备上可能出现的问题可能永远不会出现在模拟器上。在任何情况下,您的代码对于转换为 mp4 格式似乎都是有效的。
祝你好运!
我正在尝试压缩 AVAsset
以降低质量,然后将其导出为 mp4。输入资产可以是相机胶卷允许的任何类型的视频。
我 运行 遇到的问题是,当我尝试将资产导出到 AVAssetExportPresetMediumQuality
时,当输入最初是 mp4 文件时,它在第一个保护语句处失败。但是,如果我将其更改为 AVAssetExportPresetPassthrough
它可以工作但不会压缩文件。对于 compressing/encoding 最初可能是 .mov 或 .mp4 的资产,是否有单向解决方案?
func encodeVideo(asset: AVAsset, completionHandler: @escaping (URL?, String?) -> ()) {
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else {
completionHandler(nil, nil)
return
}
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("compressed-video.mp4")
if FileManager.default.fileExists(atPath: filePath.path) {
do {
try FileManager.default.removeItem(at: filePath)
} catch {
completionHandler(nil, nil)
}
}
exportSession.outputURL = filePath
exportSession.outputFileType = .mp4
exportSession.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: asset.duration)
exportSession.timeRange = range
exportSession.exportAsynchronously {
switch exportSession.status {
case .failed:
print("Conversion Failed")
completionHandler(nil, exportSession.error?.localizedDescription)
case .cancelled:
print("Conversion Cancelled")
completionHandler(nil, exportSession.error?.localizedDescription)
case .completed:
completionHandler(exportSession.outputURL, nil)
default: break
}
}
}
经过进一步测试和研究,这似乎是模拟器(Xcode 11.1 和 iPhone 11 Pro 模拟器,iOS 13.1)的一个 issue/possible 错误。不确定这是否扩展到其他模拟器,但上面使用 AVAssetExportPresetMediumQuality
的代码在我的设备测试中有效。
我看到你回复你的问题说是模拟器的问题。我的建议是在设备上测试 AVFoundation 进程。模拟器并不总是配备足够的设备来处理这些情况。此外,设备上可能出现的问题可能永远不会出现在模拟器上。在任何情况下,您的代码对于转换为 mp4 格式似乎都是有效的。 祝你好运!