Converting MPMediaItem to NSData

2019-06-10 03:48发布

问题:

I'm trying to convert an MPMediaItem to NSData object so I can play it with AVAudioPlayer. The following answer was posted a while back on a similar question, with steps on how to to that:

MPMediaItems raw song data

Of course you can access the data of a MPMediaItem. It's not crystal clear at once but it works. Here's how:

Get the media item's URL from it's MPMediaItemPropertyAssetURL property Initialize an AVURLAsset with this URL Initialize an AVAssetReader with this asset Fetch the AVAssetTrack you want to read from the AVURLAsset Create an AVAssetReaderTrackOutput with this track Add this output to the AVAssetReader created before and -startReading Fetch all data with AVAssetReaderTrackOutput's -copyNextSampleBuffer PROFIT!

After fetching the data with 'copyNextSampleBuffer', I now have an CMSampleBufferRef object. How do I continue from here?

Thanks, Gili

回答1:

Try this:

-(void)mediaItemToData : (MPMediaItem * ) curItem
{
    NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];

    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
                                                                      presetName:AVAssetExportPresetAppleM4A];

    exporter.outputFileType =   @"com.apple.m4a-audio";

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * myDocumentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    [[NSDate date] timeIntervalSince1970];
    NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
    NSString *intervalSeconds = [NSString stringWithFormat:@"%0.0f",seconds];

    NSString * fileName = [NSString stringWithFormat:@"%@.m4a",intervalSeconds];

    NSString *exportFile = [myDocumentsDirectory stringByAppendingPathComponent:fileName];

    NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL;

    // do the export
    // (completion handler block omitted)
    [exporter exportAsynchronouslyWithCompletionHandler:
     ^{
         int exportStatus = exporter.status;

         switch (exportStatus)
         {
             case AVAssetExportSessionStatusFailed:
             {
                 NSError *exportError = exporter.error;
                 NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                 break;
             }
             case AVAssetExportSessionStatusCompleted:
             {
                 NSLog (@"AVAssetExportSessionStatusCompleted");

                 NSData *data = [NSData dataWithContentsOfFile: [myDocumentsDirectory
                                                                 stringByAppendingPathComponent:fileName]];

                 //DLog(@"Data %@",data);
                 data = nil;

                 break;
             }
             case AVAssetExportSessionStatusUnknown:
             {
                 NSLog (@"AVAssetExportSessionStatusUnknown"); break;
             }
             case AVAssetExportSessionStatusExporting:
             {
                 NSLog (@"AVAssetExportSessionStatusExporting"); break;
             }
             case AVAssetExportSessionStatusCancelled:
             {
                 NSLog (@"AVAssetExportSessionStatusCancelled"); break;
             }
             case AVAssetExportSessionStatusWaiting:
             {
                 NSLog (@"AVAssetExportSessionStatusWaiting"); break;
             }
             default:
             {
                 NSLog (@"didn't get export status"); break;
             }
         }
     }];
}


回答2:

Try to use following code

 MPMediaItem *item;
 NSData *dataMedia = [NSData dataWithContentsOfURL:[item valueForProperty:MPMediaItemPropertyAssetURL]];