Ios 如何使用AVAssetExportSession导出AVPlayer音频mp3文件?

Ios 如何使用AVAssetExportSession导出AVPlayer音频mp3文件?,ios,audio,mp3,avplayer,avassetexportsession,Ios,Audio,Mp3,Avplayer,Avassetexportsession,我现在正在尝试导出一个mp3文件,该文件已使用AVPlayer(使用url)播放,因此不必下载两次 这是我的示例代码: 我尝试了每种outputFileType self.exporter = [[AVAssetExportSession alloc] initWithAsset:self.asset presetName:AVAssetExportPresetPassthrough]; } NSError *error; NSLog(

我现在正在尝试导出一个mp3文件,该文件已使用AVPlayer(使用url)播放,因此不必下载两次

这是我的示例代码:

我尝试了每种outputFileType

    self.exporter = [[AVAssetExportSession alloc] initWithAsset:self.asset presetName:AVAssetExportPresetPassthrough];
        }

        NSError *error;

        NSLog(@"export.supportedFileTypes : %@",self.exporter.supportedFileTypes);
       //        "com.apple.quicktime-movie",
//        "com.apple.m4a-audio",
//        "public.mpeg-4",
//        "com.apple.m4v-video",
//        "public.3gpp",
//        "org.3gpp.adaptive-multi-rate-audio",
//        "com.microsoft.waveform-audio",
//        "public.aiff-audio",
//        "public.aifc-audio",
//        "com.apple.coreaudio-format"

        self.exporter.outputFileType = @"public.aiff-audio";
        self.exporter.shouldOptimizeForNetworkUse = YES;

        NSURL *a = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&error];

        NSURL *url = [a URLByAppendingPathComponent:@"filename.mp3"];

        NSString *filePath = [url absoluteString];

        self.exporter.outputURL = url;

        if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]){
            [self.exporter exportAsynchronouslyWithCompletionHandler:^{

                if (self.exporter.status == AVAssetExportSessionStatusCompleted)
                {

                    if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]){
                        NSLog(@"File doesn't exist at path");
                    }else {
                        NSLog@"File saved!");
}                    
                }
                else if(self.exporter.status == AVAssetExportSessionStatusFailed){
                    NSLog(@"Failed");
                }else if(self.exporter.status == AVAssetExportSessionStatusUnknown){
                    NSLog(@"Unknown");
                }else if(self.exporter.status == AVAssetExportSessionStatusCancelled){
                    NSLog(@"Cancelled");
                }else if(self.exporter.status == AVAssetExportSessionStatusWaiting){
                    NSLog(@"Waiting");
                }else if(self.exporter.status == AVAssetExportSessionStatusExporting){
                    NSLog(@"Exporting");
                }

                NSLog(@"Exporter error! : %@",self.exporter.error);

              }];

        }}else{
            NSLog(@"File already exists at path");
        }
如果这是不可能完成的,有没有解决办法


另外,因为我可以更改音频文件的格式。使用AVAudioPlayer的理想类型是什么?

似乎
AVAssetExportSession
仅支持使用
AVAssetExportPresetPassthrough
预设对com.apple.quicktime-movie(.mov)和com.apple.coreaudio-format(.caf)进行mp3转码的文件类型。在编写输出文件时,还必须确保使用这些文件扩展名之一,否则将无法保存

mp3输入文件支持的输出文件类型和扩展名以粗体显示(在OS X 10.11.6上测试):

  • com.apple.quicktime-mov(.mov)
  • com.apple.m4a-audio(.m4a)
  • public.mpeg-4(.mp4)
  • com.apple.m4v-video(.m4v)
  • org.3gpp.adaptive-multi-rate-audio(.amr)
  • com.microsoft.wave-audio(.wav)
  • public.aiff-audio(.aiff)
  • public.aifc-audio(.aifc)
  • com.apple.coreaudio-format(.caf)
如果您不介意将音频数据正确转码为其他格式,则不必使用
AVAssetExportPresetPassthrough
预设。还有
AVAssetExportPresetLowQuality
AVAssetExportPresetMediumQuality
,以及
AVAssetExportPresetHighestQuality
。在下面的示例代码中,输出URL的扩展名为.m4a,生成的转码在iTunes和其他媒体播放器中播放:

AVAsset * asset = [AVAsset assetWithURL:inputURL];
AVAssetExportSession * exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.outputURL = outputURL;
exportSession.metadata = asset.metadata;       
[exportSession exportAsynchronouslyWithCompletionHandler:^{

    if (exportSession.status == AVAssetExportSessionStatusCompleted)
    {
            NSLog(@"AV export succeeded.");
    }
    else if (exportSession.status == AVAssetExportSessionStatusCancelled)
    {
        NSLog(@"AV export cancelled.");
    }
    else
    {
        NSLog(@"AV export failed with error: %@ (%ld)", exportSession.error.localizedDescription, (long)exportSession.error.code);
    }
}];

我试图从ipod库导出mp3格式的音频文件。下面是我的解决方案

extension DirectoryListViewController: MPMediaPickerControllerDelegate {
public func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
    guard let mediaItem = mediaItemCollection.items.first else { ImportExternalFileService.shared.alertImportError(); return  }
    guard let url = mediaItem.assetURL else { ImportExternalFileService.shared.alertImportError(); return }
    guard let songTitle = mediaItem.title else { ImportExternalFileService.shared.alertImportError(); return }
    guard let exportSession = AVAssetExportSession(asset: AVURLAsset(url: url), presetName: AVAssetExportPresetAppleM4A) else {
        ImportExternalFileService.shared.alertImportError(); return
    }
    exportSession.outputFileType = .m4a
    exportSession.metadata = AVURLAsset(url: url).metadata
    exportSession.shouldOptimizeForNetworkUse = true
    guard let fileExtension = UTTypeCopyPreferredTagWithClass(exportSession.outputFileType!.rawValue as CFString, kUTTagClassFilenameExtension) else {
        ImportExternalFileService.shared.alertImportError(); return
    }
    let documentURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    let outputURL = documentURL.appendingPathComponent("\(songTitle).\(fileExtension.takeUnretainedValue())")
    /* Dont't forget to remove the existing url, or exportSession will throw error: can't save file */
    do {
        try FileManager.default.removeItem(at: outputURL)
    } catch let error as NSError {
        print(error.debugDescription)
    }
    exportSession.outputURL = outputURL
    exportSession.exportAsynchronously(completionHandler: {
        if exportSession.status == .completed {
            DispatchQueue.main.async {
                ImportExternalFileService.shared.importRecordFile(url: exportSession.outputURL!)
            }
        } else {
            print("AV export failed with error:- ", exportSession.error!.localizedDescription)
        }
    })
}

public func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController) {
    dismiss(animated: true, completion: nil)
}

}您不能,但可以导出m4a

AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:audioAsset presetName:AVAssetExportPresetAppleM4A];
exportSession.outputURL = [NSURL fileURLWithPath:exportPath];
exportSession.outputFileType = AVFileTypeAppleM4A;
[exportSession exportAsynchronouslyWithCompletionHandler:^{

}];

是的,即使是苹果自己的AVFoundationExporter示例项目似乎也无法处理mp3文件和AVAssetExportPresetPassthrough预设。请参阅此处的答案,可能会对您有所帮助:尝试您的方法。我收到一个mp3文件,可以在QuickTime中播放,但无法在iTunes和其他一些播放器中播放。您知道如何解决此问题吗?看起来您无法使用
AVAssetExportPresetPassthrough
来解决此问题。我正在将代码转换为.m4a,但我使用的是
AVAssetExportPresetLowQuality
preset,它实际上是将音频数据转换为不同的格式,并且工作正常。您可以尝试其他一些预设,包括
AVAssetExportPresetMediumQuality
AVAssetExportPresetHighestQuality
。让我用一些附加信息更新我的答案。@Dalmazio根据您的经验,将视频转换为mp3的正确方法是什么?