2012-10-24 22 views
8

私はローカルのm4aまたはmp3ファイルを取得し、このファイルを圧縮/ダウンサンプリングしようとしています(ファイルを小さくするため)。AVAssetWriterダウンサンプリング/圧縮m4a/mp3ファイルを書き込む方法

元々、私はAVAssetをtempディレクトリにエクスポートするためにAVAssetExportSessionを使用していましたが、圧縮/ダウンサンプリングを制御できませんでした(プリセットのみ使用できますが、品質劣化をサポートします)。

次に、ここでいくつかの例をあげて、AVAssetReader/AVAssetWriterを使用してこの「エクスポート」を実行しようとしました。

私のような私のリーダ/ライタを作成:

私は、私はおそらくに書いたデータを書き込む終わりだ
[writer startWriting]; 
[writer startSessionAtSourceTime:kCMTimeZero]; 

[reader startReading]; 
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL); 
[writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{ 

    NSLog(@"Asset Writer ready : %d", writerInput.readyForMoreMediaData); 
    while (writerInput.readyForMoreMediaData) { 
     CMSampleBufferRef nextBuffer; 
     if ([reader status] == AVAssetReaderStatusReading && (nextBuffer = [readerOutput copyNextSampleBuffer])) { 
      if (nextBuffer) { 
       NSLog(@"Adding buffer"); 
       [writerInput appendSampleBuffer:nextBuffer]; 
      } 
     } else { 
      [writerInput markAsFinished]; 

      switch ([reader status]) { 
       case AVAssetReaderStatusReading: 
        break; 
       case AVAssetReaderStatusFailed: 
        [writer cancelWriting]; 
        break; 
       case AVAssetReaderStatusCompleted: 
        NSLog(@"Writer completed"); 
        [writer endSessionAtSourceTime:asset.duration]; 
        [writer finishWriting]; 

        NSData *data = [NSData dataWithContentsOfFile:exportPath]; 
        NSLog(@"Data: %@", data); 
        break; 
      } 
      break; 
     } 
    } 
}]; 

...

NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]; 

NSURL *exportURL = [NSURL fileURLWithPath:outPath]; 

// reader 
NSError *readerError = nil; 
AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset 
                 error:&readerError]; 

AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];  
AVAssetReaderTrackOutput *readerOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track 
                      outputSettings:nil]; 
[reader addOutput:readerOutput]; 

// writer 
NSError *writerError = nil; 
AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:exportURL 
                fileType:AVFileTypeAppleM4A 
                error:&writerError]; 

AudioChannelLayout channelLayout; 
memset(&channelLayout, 0, sizeof(AudioChannelLayout)); 
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; 

// use different values to affect the downsampling/compression 
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey, 
           [NSNumber numberWithFloat:44100.0], AVSampleRateKey, 
           [NSNumber numberWithInt:2], AVNumberOfChannelsKey, 
           [NSNumber numberWithInt:128000], AVEncoderBitRateKey, 
           [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey, 
           nil]; 

AVAssetWriterInput *writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio 
                   outputSettings:outputSettings]; 
[writerInput setExpectsMediaDataInRealTime:NO]; 
[writer addInput:writerInput]; 

そして、私が書き込みを開始しますexportURLはnullであり、ライターは正常終了を報告します。何が間違っている可能性がありますか?

更新appendSampleBuffer:を呼び出した後ライターのステータスは、読者のステータスは成功し、ファイル全体を通読しているようだが、AVAssetWriterStatusFailedされます。

+0

これまでに何か書き込もうとしていますか?初めてサンプルバッファを追加しようとしたときの読者のステータスは? – BlueVoodoo

+0

ああ、 '[writerInput appendSampleBuffer:]'が呼び出されるたびに表示され、ライターのステータスは3で、列挙型を見るとAVAssetWriterStatusFailedのようになります。 * appendSampleBufferは* many * timesと呼ばれています。 – Dfowj

答えて

5

私は解決策に出くわした:NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]でNSHomeDirectory()を使用する

はライターがファイルを作成することはできませんさせました。なぜか、またはこれが動作するようにするために何をする必要があるのか​​正確にはわかりませんが、NSHomeDirectiory()NSTemporaryDirectory()に変更すると、私の問題が解決されました。

+1

iOSのホームディレクトリに書き込むことはできません。一時ディレクトリはOKです。また、Documentsディレクトリ –

関連する問題