简体   繁体   English

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

[英]How can I export a AVPlayer audio mp3 file using AVAssetExportSession?

I am now trying to export an mp3 file that has been player using AVPlayer (using an url) so it doesn't have to be downloaded twice.我现在正在尝试导出使用 AVPlayer(使用 url)播放的 mp3 文件,因此不必下载两次。

This is my sample code:这是我的示例代码:

I've tried every outputFileType...我已经尝试了每个 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");
        }

If this is not possible to accomplish, is there any work around?如果这无法完成,是否有任何解决方法?

Also, as I can change the format of the audio file.另外,因为我可以更改音频文件的格式。 What's the ideal type to work with AVAudioPlayer?使用 AVAudioPlayer 的理想类型是什么?

It appears AVAssetExportSession only supports filetypes for mp3 transcoding with com.apple.quicktime-movie (.mov) and com.apple.coreaudio-format (.caf) using the AVAssetExportPresetPassthrough preset.看起来AVAssetExportSession只支持使用AVAssetExportPresetPassthrough预设的com.apple.quicktime-movie (.mov) 和com.apple.coreaudio-format (.caf) 的 mp3 转码文件类型。 You must also be sure to use one of these file extensions when writing your output file otherwise it won't save.在编写输出文件时,您还必须确保使用这些文件扩展名之一,否则将无法保存。

Supported output filetype and extensions for an mp3 input file are in bold (tested on OS X 10.11.6): mp3 输入文件支持的输出文件类型和扩展名以粗体显示(在 OS X 10.11.6 上测试):

  • com.apple.quicktime-movie (.mov) com.apple.quicktime-电影 (.mov)
  • com.apple.m4a-audio (.m4a) com.apple.m4a-音频 (.m4a)
  • public.mpeg-4 (.mp4) public.mpeg-4 (.mp4)
  • com.apple.m4v-video (.m4v) com.apple.m4v-视频 (.m4v)
  • org.3gpp.adaptive-multi-rate-audio (.amr) org.3gpp.adaptive-multi-rate-audio (.amr)
  • com.microsoft.waveform-audio (.wav) com.microsoft.waveform-audio (.wav)
  • public.aiff-audio (.aiff) public.aiff-audio (.aiff)
  • public.aifc-audio (.aifc) public.aifc-音频 (.aifc)
  • com.apple.coreaudio-format (.caf) com.apple.coreaudio 格式 (.caf)

If you don't mind performing a proper transcode of the audio data to another format, then you don't have to use the AVAssetExportPresetPassthrough preset.如果您不介意将音频数据正确转码为另一种格式,那么您不必使用AVAssetExportPresetPassthrough预设。 There are also AVAssetExportPresetLowQuality , AVAssetExportPresetMediumQuality , and AVAssetExportPresetHighestQuality .还有AVAssetExportPresetLowQualityAVAssetExportPresetMediumQualityAVAssetExportPresetHighestQuality In the sample code that follows, the output URL has extension .m4a and the resulting transcode plays in iTunes and other media players:在下面的示例代码中,输出 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);
    }
}];

I tried to export audio file with mp3 format from ipod library.我试图从 ipod 库中导出 mp3 格式的音频文件。 and this is my solution below.这是我下面的解决方案。

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

} }

You can't, but you can export m4a.你不能,但你可以导出 m4a。

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

}];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM