2012-06-26 2 views
1

Я немного уменьшил этот вопрос и надеюсь на помощь.Запись и воспроизведение звука с помощью AVAssetWriter

В основном этот класс имеет два метода: один для начала записи звука (-recordMode), а другой для воспроизведения звука (playMode). В настоящее время у меня есть этот класс в проекте с одним контроллером представления с двумя кнопками, которые вызывают соответствующие методы (rec, play). Других переменных нет, класс самодостаточен.

Однако он не будет воспроизводить/записывать что-либо, и я не могу понять, почему. Когда я пытаюсь воспроизвести файл, я получаю размер файла 0 и ошибку, потому что вы не можете инициализировать AVAudioPlayer с ссылкой nil, конечно. Но я не понимаю, почему файл пуст или почему self.outputPath is nil.

.h файл

#import <AVFoundation/AVFoundation.h> 

@interface MicCommunicator : NSObject<AVCaptureAudioDataOutputSampleBufferDelegate> 

@property(nonatomic,retain) NSURL *outputPath; 
@property(nonatomic,retain) AVCaptureSession * captureSession; 
@property(nonatomic,retain) AVCaptureAudioDataOutput * output; 

-(void)beginStreaming; 
-(void)playMode; 
-(void)recordMode; 

@end 

.m файл:

@implementation MicCommunicator { 
    AVAssetWriter *assetWriter; 
    AVAssetWriterInput *assetWriterInput; 
} 

@synthesize captureSession = _captureSession; 
@synthesize output = _output; 
@synthesize outputPath = _outputPath; 

-(id)init { 
    if ((self = [super init])) { 
     NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     self.outputPath = [NSURL fileURLWithPath:[[searchPaths objectAtIndex:0] stringByAppendingPathComponent:@"micOutput.output"]]; 

     AudioChannelLayout acl; 
     bzero(&acl, sizeof(acl)); 
     acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; //kAudioChannelLayoutTag_Stereo; 
     NSDictionary *audioOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
              [NSNumber numberWithInt: kAudioFormatULaw],AVFormatIDKey,   
              [NSNumber numberWithFloat:8000.0],AVSampleRateKey,//was 44100.0 
              [NSData dataWithBytes: &acl length: sizeof(AudioChannelLayout) ], AVChannelLayoutKey, 
              [NSNumber numberWithInt:1],AVNumberOfChannelsKey, 
              [NSNumber numberWithInt:8000.0],AVEncoderBitRateKey, 
              nil]; 

     assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioOutputSettings]; 
     [assetWriterInput setExpectsMediaDataInRealTime:YES]; 

     assetWriter = [[AVAssetWriter assetWriterWithURL:_outputPath fileType:AVFileTypeWAVE error:nil] retain]; 
     [assetWriter addInput:assetWriterInput]; 
    } 
    return self; 
} 

-(void)dealloc { 
    [assetWriter release]; 
    [super dealloc]; 
} 

//conveniance methods 

-(void)playMode 
{ 
    [self stopRecording]; 

    NSError *error; 
    AVAudioPlayer * audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:self.outputPath error:&error]; 
    audioPlayer.numberOfLoops = -1; 

    if (audioPlayer == nil){ 
     NSLog(@"error: %@",[error description]);   
    }else{ 
     NSLog(@"playing"); 
     [audioPlayer play]; 
    } 
} 

-(void)recordMode 
{ 
     [self beginStreaming];  
} 

-(void)stopRecording 
{ 
    [self.captureSession stopRunning]; 
    [assetWriterInput markAsFinished]; 
    [assetWriter finishWriting]; 

    NSDictionary *outputFileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@",self.outputPath] error:nil]; 
    NSLog (@"done. file size is %llu", [outputFileAttributes fileSize]); 
} 

//starts audio recording 
-(void)beginStreaming { 
    self.captureSession = [[AVCaptureSession alloc] init]; 
    AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 
    NSError *error = nil; 
    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error]; 
    if (audioInput) 
     [self.captureSession addInput:audioInput]; 
    else { 
     NSLog(@"No audio input found."); 
     return; 
    } 

    AVCaptureAudioDataOutput *output = [[AVCaptureAudioDataOutput alloc] init]; 

    dispatch_queue_t outputQueue = dispatch_queue_create("micOutputDispatchQueue", NULL); 
    [output setSampleBufferDelegate:self queue:outputQueue]; 
    dispatch_release(outputQueue); 

    [self.captureSession addOutput:output]; 
    [assetWriter startWriting]; 
    [self.captureSession startRunning]; 
} 

//callback 
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 
    AudioBufferList audioBufferList; 
    NSMutableData *data= [[NSMutableData alloc] init]; 
    CMBlockBufferRef blockBuffer; 
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); 

    //for (int y = 0; y < audioBufferList.mNumberBuffers; y++) { 
    // AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; 
    // Float32 *frame = (Float32*)audioBuffer.mData; 
    //   
    // [data appendBytes:frame length:audioBuffer.mDataByteSize]; 
    //} 

    // append [data bytes] to your NSOutputStream 


    // These two lines write to disk, you may not need this, just providing an example 
    [assetWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)]; 
    [assetWriterInput appendSampleBuffer:sampleBuffer]; 

    CFRelease(blockBuffer); 
    blockBuffer=NULL; 
    [data release]; 
} 

@end 
+0

Перейди через код еще раз и, если вызов возвращает некоторую информацию об ошибке, как в 'состояния BOOL' или' NSError', проверьте или зарегистрировать ее. Это приблизит вас к источнику проблемы. Вызывается ли ваш обратный вызов? – zoul

+0

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

+0

huh, если я ставлю NSLog (@ «количество буферов% d», y); в цикле for внутри обратного вызова всегда равен 0. Значение mNumberBuffers равно 0, а –

ответ

0

Per поддержки Apple:

это, следовательно, ошибка - файл создается, ряд образцов написано успешно, после чего append начинает сбой по неизвестной причине.

Кажется, что AVAssetWriter выходит из строя только с этими настройками.

что звуковое сообщения следует использовать для ULAW аудио

+0

была ли эта ошибка когда-либо исправлена ​​Apple? – TigerCoding

+0

На самом деле не уверен, что я не могу проверить это на поздний срок. если этот материал действительно дает вам проблемы, предложение может заключаться в использовании одного из ваших бесплатных случаев поддержки разработки из apple –