2012-10-24 26 views
8

Tôi đang cố gắng lấy tệp m4a hoặc mp3 cục bộ và nén/xuống mẫu tệp này (với mục đích tạo tệp nhỏ hơn).AVAssetWriter Cách ghi các tệp m4a/mp3 nén xuống/lấy mẫu

Ban đầu, tôi đang sử dụng AVAssetExportSession để xuất AVAsset sang thư mục tạm thời, nhưng tôi không có quyền kiểm soát nén/lấy mẫu xuống (bạn chỉ có thể sử dụng các giá trị đặt sẵn, chỉ có định dạng tệp .wav hỗ trợ giảm chất lượng).

Sau đó, sau một vài ví dụ ở đây trên SO, tôi đã thử sử dụng AVAssetReader/AVAssetWriter để tạo biểu mẫu này 'xuất'.

tôi tạo độc giả của tôi/nhà văn như vậy:

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]; 

Và sau đó tôi bắt đầu viết ...

[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; 
     } 
    } 
}]; 

Khi tôi thực hiện bằng văn bản, dữ liệu tôi đã được cho là ghi vào exportURL là null và người viết báo cáo thành công. Bất kỳ ý tưởng gì có thể sẽ sai?

Cập nhật Trạng thái của người viết sau khi gọi appendSampleBuffer: là AVAssetWriterStatusFailed, mặc dù trạng thái người đọc thành công và dường như đọc toàn bộ tệp.

+0

Nó có bao giờ cố gắng viết gì không? Trạng thái của người đọc lần đầu tiên nó cố gắng gắn thêm bộ lọc mẫu là gì? – BlueVoodoo

+0

Ah ha, nó xuất hiện ở mọi bước khi '[writerInput appendSampleBuffer:]' được gọi, trạng thái ghi là 3, bằng cách nhìn vào enum, trông giống như AVAssetWriterStatusFailed. Dường như người đọc đang sao chép tất cả các bộ đệm mẫu từ nội dung của tôi mặc dù - appendSampleBuffer được gọi là * nhiều lần * – Dfowj

Trả lời

5

tôi đi qua các giải pháp:

Sử dụng NSHomeDirectory() trong NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"] đã gây ra tác giả không có khả năng để tạo ra các tập tin. Không chắc chắn lý do tại sao, hoặc những gì tôi sẽ cần phải làm để cho phép điều này để làm việc, nhưng thay đổi NSHomeDirectiory() đến NSTemporaryDirectory() đã giải quyết vấn đề của tôi trong khi chờ đợi.

+1

Bạn không thể ghi vào thư mục chính trong iOS. Thư mục tạm thời là ok, cũng như thư mục Documents –