2012-05-11 3 views
3

Итак, я столкнулся с очень странной и странной проблемой, и мне было интересно, если кто-нибудь еще столкнется с этой проблемой. Я захватываю необработанные данные из MPMediaItem из музыкальной библиотеки телефонов, а затем отправляю их через HTTP для воспроизведения в другом месте. Там, где возникает моя проблема, когда я захватываю необработанные данные из файла типа .m4a, кажется, что они отсутствуют. Например, если исходный файл, который я проверяю с itunes, равен 7.4 МБ, что плохой из моего кода имеет размер 7,3 МБ. Ive сделал некоторые исследования и обнаружил, что файл .m4a на самом деле является инкапсуляцией, и я думаю, что я не получаю инкапсуляцию файла только необработанные музыкальные данные, поэтому он не распознается. Вот мой код, который дает мне сырые музыкальные данные из MPMediaItem.m4a необработанные данные из библиотеки iPod не играют

    NSError * error = nil; 
        MPMediaQuery *query = [MPMediaQuery albumsQuery]; 
        NSArray * songs = query.items; 
        MPMediaItem * song = [songs objectAtIndex:socket_data_index]; 
        AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:[song valueForProperty:MPMediaItemPropertyAssetURL] options:nil]; 
        AVAssetReader * reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];     
        AVAssetTrack * songTrack = [songAsset.tracks objectAtIndex:0]; 
        AVAssetReaderTrackOutput * output = [[AVAssetReaderTrackOutput alloc] initWithTrack:songTrack outputSettings:nil]; 
        [reader addOutput:output];       
        [output release]; 



        [reader startReading]; 

        while (reader.status == AVAssetReaderStatusReading) 
        {        
         AVAssetReaderTrackOutput * trackOutput = (AVAssetReaderTrackOutput *)[reader.outputs objectAtIndex:0]; 
         CMSampleBufferRef sampleBufferRef = [trackOutput copyNextSampleBuffer];        
         if (sampleBufferRef) 
         { 
          CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBufferRef); 

          size_t length = CMBlockBufferGetDataLength(blockBufferRef); 
          NSMutableData * data = [[NSMutableData alloc] initWithLength:length]; 
          CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, data.mutableBytes); 

          [data_to_return appendData:data]; 
          [data release]; 

          CMSampleBufferInvalidate(sampleBufferRef); 
          CFRelease(sampleBufferRef); 
         } 
        } 

        if (reader.status == AVAssetReaderStatusFailed || reader.status == AVAssetReaderStatusUnknown) 
        { 
         // Something went wrong. Handle it. 
        } 

        if (reader.status == AVAssetReaderStatusCompleted) 
        {       

         return [[[HTTPDataResponse alloc] initWithData:data_to_return] autorelease]; 
        } 

        [reader release]; 

я делаю и получить правильные данные для .mp3 файлов, находящихся в библиотеке телефонов, но когда дело доходит до .M4A это, кажется, отсутствует некоторые части.

Еще раз спасибо, что нашли время, чтобы помочь мне.

ответ

1

Я столкнулся с той же проблемой. AVAssetReader возвращает только исходные аудиоданные. Он работает для .mp3, потому что формат файла - это всего лишь куча фреймов, содержащих все необходимое проигрывателю для воспроизведения файла. Вы можете заметить, что вся информация id3 отсутствует в экспортированном файле.

.m4a аудиофайлы - это контейнеры, которые обертывают аудиоданные aac. Вы получили только аудиоданные без дополнительной информации, то есть сэмплера или таблицы поиска.

Обходной путь для вашей проблемы может заключаться в использовании AVAssetExportSession для экспорта AVAssetTrack в файл на телефоне и потоковой передачи файла оттуда. Я попробовал именно это, и был написан рабочий файл .m4a.

Следующий код основан на Apples example how to export a trimmed audio asset:

// create the export session 
AVAssetExportSession *exportSession = [AVAssetExportSession 
             exportSessionWithAsset: songAsset 
             presetName:AVAssetExportPresetAppleM4A]; 
if (nil == exportSession) 
    NSLog(@"Error"); 

// configure export session output with all our parameters 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; 
NSString *filePath = [NSString stringWithFormat: @"%@/export.m4a", basePath]; 

exportSession.outputURL = [NSURL fileURLWithPath: filePath]; // output path 
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type 

[exportSession exportAsynchronouslyWithCompletionHandler:^{ 
    if (AVAssetExportSessionStatusCompleted == exportSession.status) 
    { 
     NSLog(@"AVAssetExportSessionStatusCompleted"); 
    } 
    else if (AVAssetExportSessionStatusFailed == exportSession.status) 
    { 
     // a failure may happen because of an event out of your control 
     // for example, an interruption like a phone call comming in 
     // make sure and handle this case appropriately 
     NSLog(@"AVAssetExportSessionStatusFailed"); 
    } 
    else 
    { 
     NSLog(@"Export Session Status: %d", exportSession.status); 
    } 
}]; 

Недостатком этого решения является то, что файл в то время как должны были быть записаны на диск. Я все еще ищу лучший способ обработки файлов .m4a.

+0

Это то, что я в конце концов сделал, не уверен, есть ли способ избежать записи на диск. – Krzemienski

+0

@melle, я внедрил ваше решение, и теперь оно включает информацию о заголовке, но когда я перехожу к загрузке на s3 с помощью AmazonS3Client, у меня возникает проблема, когда данные просто не загружаются. Есть идеи? Может ли быть что-то в исходном заголовке, что мешает ему загружать? – user592419

+0

Извините, я понятия не имею, что может быть проблемой для клиента Amazons. Вы должны сравнить файл с сеанса экспорта с исходным файлом, который был синхронизирован с вашим устройством iOS. – melle

 Смежные вопросы

  • Нет связанных вопросов^_^