Swift 需要使用AVAssetExportSession导出音频的帮助吗

Swift 需要使用AVAssetExportSession导出音频的帮助吗,swift,audio,download,export,avassetexportsession,Swift,Audio,Download,Export,Avassetexportsession,我无法将AVAsset导出到本地目录。我收到以下错误消息: failed Error Domain=AVFoundationErrorDomain Code=-11838 "Operation Stopped" UserInfo={NSLocalizedFailureReason=The operation is not supported for this media., NSLocalizedDescription=Operation Stopped, NSUnderly

我无法将AVAsset导出到本地目录。我收到以下错误消息:

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)"}}
这是我上传文件的代码:

这是我的调试器的图像,您可以看到
文件
变量引用了实际的
AVAsset

以下是失败的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

我认为您出现了一个错误,因为文件扩展名与“presetName”、“outputFileType”、“fileURL”不匹配

我尝试用AVMutableComposition解决问题,并以m4a格式导出音频。音频在远程服务器上

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()
            })
        }
    })
}

我认为您出现了一个错误,因为文件扩展名与“presetName”、“outputFileType”、“fileURL”不匹配

我尝试用AVMutableComposition解决问题,并以m4a格式导出音频。音频在远程服务器上

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()
            })
        }
    })
}

请输入
filePath.absoluteString
的值好吗?请检查资产的文件扩展名好吗?我认为它可能无法将此导出到m4a,您可以通过
exporter.supportedFileTypes
检查此问题。您可能有冲突的设置,因为m4a预设与
文件[0]
setting.HI@PranavKasetti不同。谢谢您的帮助。exporter.supportedFileTypes类似于此可选([\uu C.AVFileType(\u rawValue:com.apple.m4a audio)]),filePath.absoluteString类似于此file:///var/mobile/Containers/Data/Application/41F5A4A8-3F6D-4525-86D1-630FA00F08BC/Documents/3826F259-1B18-4381-B893-E69ACC8D6DEEThanks,到目前为止还可以。什么是
文件[0]
?还有com.apple.m4a-audio您能否包括
文件路径的值。absoluteString
请检查资产的文件扩展名?我认为它可能无法将此导出到m4a,您可以通过
exporter.supportedFileTypes
检查此问题。您可能有冲突的设置,因为m4a预设与
文件[0]
setting.HI@PranavKasetti不同。谢谢您的帮助。exporter.supportedFileTypes类似于此可选([\uu C.AVFileType(\u rawValue:com.apple.m4a audio)]),filePath.absoluteString类似于此file:///var/mobile/Containers/Data/Application/41F5A4A8-3F6D-4525-86D1-630FA00F08BC/Documents/3826F259-1B18-4381-B893-E69ACC8D6DEEThanks,到目前为止还可以。什么是
文件[0]
?也是com.apple.m4a-audio
downloadLocalCopyOfTrack(playerItem, finished: { (url) in
  if url != nil {
    //use url or play here
  }else {
    print("URL is nil")
  }
})