[我开始说我花了很多时间搜索文档,在此处和其他地方发布的内容,但是我无法找到解决该问题的方法。
我正在使用AVAssetExportSession
导出存储在.mp4
实例中的AVAsset
文件。我要做的是:
isExportable
的AVAsset
属性exportPresets
实例兼容的AVAsset
数组AVAssetExportPreset1920x1080
,或者,如果不存在,我尝试使用AVAssetExportPresetPassthrough
导出媒体(仅供参考,100%的次数,我需要的预设始终包含在列表中,但是我也尝试了直通选项而且还是不行)outputFileType
是AVFileTypeMPEG4
,我也尝试通过将.mp4
扩展名分配给该文件,但没有任何使其起作用。我总是收到此错误
错误域= AVFoundationErrorDomain代码= -11838“操作已停止”UserInfo = {NSUnderlyingError = 0x600000658c30 {ErrorDomain = NSOSStatusErrorDomain Code = -12109“(null)”},NSLocalizedFailureReason =此操作不受支持媒体。,NSLocalizedDescription =操作已停止}
下面是我正在使用的代码
func _getDataFor(_ item: AVPlayerItem, completion: @escaping (Data?) -> ()) {
guard item.asset.isExportable else {
completion(nil)
return
}
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: item.asset)
var preset: String = AVAssetExportPresetPassthrough
if compatiblePresets.contains(AVAssetExportPreset1920x1080) { preset = AVAssetExportPreset1920x1080 }
guard
let exportSession = AVAssetExportSession(asset: item.asset, presetName: preset),
exportSession.supportedFileTypes.contains(AVFileTypeMPEG4) else {
completion(nil)
return
}
var tempFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp_video_data.mp4", isDirectory: false)
tempFileUrl = URL(fileURLWithPath: tempFileUrl.path)
exportSession.outputURL = tempFileUrl
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTimeMake(0, 1)
let timeRange = CMTimeRangeMake(startTime, item.duration)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
print("\(exportSession.error)")
let data = try? Data(contentsOf: tempFileUrl)
_ = try? FileManager.default.removeItem(at: tempFileUrl)
completion(data)
}
}
好像是在AVAsset
中转换AVMutableComposition
实例一样有效。如果有任何人知道,请告诉我。
这是新的_getDataFor(_:completion:)
方法实现
func _getDataFor(_ item: AVPlayerItem, completion: @escaping (Data?) -> ()) {
guard item.asset.isExportable else {
completion(nil)
return
}
let composition = AVMutableComposition()
let compositionVideoTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let sourceVideoTrack = item.asset.tracks(withMediaType: AVMediaTypeVideo).first!
let sourceAudioTrack = item.asset.tracks(withMediaType: AVMediaTypeAudio).first!
do {
try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, item.duration), of: sourceVideoTrack, at: kCMTimeZero)
try compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, item.duration), of: sourceAudioTrack, at: kCMTimeZero)
} catch(_) {
completion(nil)
return
}
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: composition)
var preset: String = AVAssetExportPresetPassthrough
if compatiblePresets.contains(AVAssetExportPreset1920x1080) { preset = AVAssetExportPreset1920x1080 }
guard
let exportSession = AVAssetExportSession(asset: composition, presetName: preset),
exportSession.supportedFileTypes.contains(AVFileTypeMPEG4) else {
completion(nil)
return
}
var tempFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp_video_data.mp4", isDirectory: false)
tempFileUrl = URL(fileURLWithPath: tempFileUrl.path)
exportSession.outputURL = tempFileUrl
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTimeMake(0, 1)
let timeRange = CMTimeRangeMake(startTime, item.duration)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
print("\(tempFileUrl)")
print("\(exportSession.error)")
let data = try? Data(contentsOf: tempFileUrl)
_ = try? FileManager.default.removeItem(at: tempFileUrl)
completion(data)
}
}
检查是否正确设置了AVURLAsset的委托属性。
[self.playerAsset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
并且符合AVAssetResourceLoaderDelegate协议。这就是您需要做的。
我遇到了这个问题,因为Microphone
权限已关闭/被拒绝。一旦设置好,此错误就消失了。