2012-05-11 18 views
3

私は非常に奇妙で奇妙な問題に直面しており、他の誰かがこの問題を抱えているのか疑問に思っていました。私は携帯音楽ライブラリからの生データをMPMediaItemから取得し、HTTP経由で他の場所で再生するために送信しています。私の問題が発生している場所は、タイプ.m4aのファイルから生データを取得しているときに欠けているようです。例えば、私がiTunesからチェックする元のファイルが7.4MBの場合、私のコードから得られるものは、サイズ7.3MBです。私はいくつかの研究を行い、.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]; 

から私に生の音楽データを提供し、携帯電話のライブラリにあるが、それが来るとき、あるように思わ.M4Aする.mp3ファイルの正しいデータを取得する私のコードですいくつかの部分がありません。

もう一度お手伝いしていただき、ありがとうございます。

答えて

1

同じ問題が発生しました。 AVAssetReaderは生のオーディオデータのみを返します。これは、ファイル形式がプレーヤがファイルを再生するために必要なすべてを含むフレームの束であるため、.mp3で機能します。エクスポートされたファイルにすべてのid3情報がないことに気付くかもしれません。

.m4aオーディオファイルは、オーディオデータを囲むコンテナです。これ以上の情報、つまりサンプレートやシークテーブルはなく、オーディオデータのみを受信しました。

あなたの問題を回避するには、携帯電話上のファイルにAVAssetTrackをエクスポートし、そこからファイルをストリーミングするAVAssetExportSessionを使用することができます。私はこれを正確に試し、作業用の.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、あなたのソリューションを実装しました。ヘッダー情報が含まれていますが、AmazonS3Clientを使用してs3にアップロードすると、データがアップロードされない問題が発生します。何か案は?元のヘッダーにアップロードできないようなものがありますか? – user592419

+0

申し訳ありませんが、私はAmazonsクライアントで何が問題になるか分かりません。エクスポートセッションのファイルと、iOSデバイスに同期された元のファイルを比較する必要があります。 – melle

関連する問題