[英]Need help exporting audio with AVAssetExportSession
I am having trouble exporting an AVAsset to a local directory.我无法将 AVAsset 导出到本地目录。 I am getting the following error message:
我收到以下错误消息:
failed Error Domain=AVFoundationErrorDomain Code=-11838 "Operation Stopped" UserInfo={NSLocalizedFailureReason=The operation is not supported for this media., NSLocalizedDescription=Operation Stopped, NSUnderlyingError=0x2806d1740 {Error Domain=NSOSStatusErrorDomain Code=-12109 "(null)"}}
This is my code to upload the file:这是我上传文件的代码:
Here is an image of my debugger, where you can see that the file
variable references an actual AVAsset
这是我的调试器的图像,您可以在其中看到
file
变量引用了实际的AVAsset
Here is a description of an AVAssetExportSession that is failing这是失败的 AVAssetExportSession 的描述
Optional<AVAssetExportSession>
- some : <AVAssetExportSession: 0x280791270, asset = <AVURLAsset: 0x2805ef600, URL = https://firebasestorage.googleapis.com/v0/b/camouflage-43fe0.appspot.com/o/eCg9SNmLVlRUacfUBO1CTWNQizO2%2F31983848-C493-469B-A7CD-F7B215C37526%2Fproject_audio%2F1308EB6E-0FB3-4538-AEEC-DF59945C4CF9%2F3826F259-1B18-4381-B893-E69ACC8D6DEE?alt=media&token=8a0725e0-f34c-4b90-b564-3a3ca52e58cd>, presetName = AVAssetExportPresetAppleM4A, outputFileType = com.apple.m4a-audio
Thanks in advance for your help.在此先感谢您的帮助。
EDIT: I tried wrapping the AVURLAsset inside a AVMutableComposition, but now I get this error instead编辑:我尝试将 AVURLAsset 包装在 AVMutableComposition 中,但现在我得到了这个错误
failed Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-17508), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x283ae5c50 {Error Domain=NSOSStatusErrorDomain Code=-17508 "(null)"}}
I think you got an error because of file extension mismatch with 'presetName', 'outputFileType', 'fileURL'.我认为由于文件扩展名与“presetName”、“outputFileType”、“fileURL”不匹配而出现错误。
I try to solve with AVMutableComposition and export audio in m4a format.我尝试使用 AVMutableComposition 解决并以 m4a 格式导出音频。 Audio is on remote server.
音频在远程服务器上。
let url = URL(string: "https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3")
let asset = AVAsset(url: url!)
let playerItem = AVPlayerItem(asset: asset)
let remoteFilePath = url
func downloadLocalCopyOfTrack(_ playerItem: AVPlayerItem, finished:@escaping (URL?) -> ()) {
guard playerItem.asset.isExportable else {
finished(nil)
return
}
let composition = AVMutableComposition()
let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let sourceAudioTrack = playerItem.asset.tracks(withMediaType: AVMediaType.audio).first!
do {
let durationInSec = playerItem.asset.duration.seconds
let duration = CMTime(seconds: durationInSec, preferredTimescale: 1)
try compositionAudioTrack?.insertTimeRange(CMTimeRange(start: CMTime.zero, duration: duration), of: sourceAudioTrack, at: CMTime.zero)
} catch {
print(error.localizedDescription)
finished(nil)
return
}
remoteFilePath.deletePathExtension()
let fileName = remoteFilePath.lastPathComponent
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let outputFilePath = documentDirectory.appendingPathComponent("\(fileName).m4a")
try? FileManager.default.removeItem(at: outputFilePath)
let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
exportSession!.outputURL = outputFilePath
exportSession!.outputFileType = AVFileType.m4a
exportSession!.timeRange = CMTimeRange(start: CMTime.zero, duration: playerItem.duration)
//Timer for Progress of Export Session
var exportProgressBarTimer = Timer() // initialize timer
if #available(iOS 10.0, *) {
exportProgressBarTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
// Get Progress
let progress = Float((exportSession!.progress));
if (progress < 0.99) {
print("progress", progress * 100)
}
}
}
exportSession!.exportAsynchronously(completionHandler: {
switch exportSession!.status {
case .failed:
print("Export failed: \(exportSession!.error!)")
exportProgressBarTimer.invalidate()
case .cancelled:
print("Export canceled")
exportProgressBarTimer.invalidate()
default:
print("Successfully trimmed audio")
DispatchQueue.main.async(execute: {
finished(outputFilePath)
exportProgressBarTimer.invalidate()
})
}
})
}
Usage:用法:
downloadLocalCopyOfTrack(playerItem, finished: { (url) in
if url != nil {
//use url or play here
}else {
print("URL is nil")
}
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.