2017-05-17 1 views
1

Ich versuche, jedes Audio-Format zu AAC-Format mit 44100Hz Abtastrate zu kodieren.ios - Konvertiere Video-Audio in AAC

Also im Grunde: Eingang (? Mp3, aac usw., jede mögliche Abtastrate) -> AAC (44100 Hz)

Die Quelle Audio stammt aus einem Video (mp4), aber ich kann es zu m4a extrahieren (AAC) . Die Sache ist, ich möchte auch die Abtastrate auf 44100Hz ändern.

Ich versuche, dies mit AVAssetReader und AVAssetWriter zu erreichen, aber nicht sicher, ob es möglich ist oder ob es die beste Lösung ist. Jede andere Lösung würde sehr geschätzt werden!

Hier ist mein Code so weit:

// Input video audio (.mp4) 
    AVAsset *videoAsset = <mp4 video asset>; 
    NSArray<AVAssetTrack *> *videoAudioTracks = [videoAsset tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *videoAudioTrack = [videoAudioTracks objectAtIndex:0]; 

    // Output audio (.m4a AAC) 
    NSURL *exportUrl = <m4a, aac output file URL>; 

    // ASSET READER 
    NSError *error; 
    AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:videoAsset 
                   error:&error]; 
    if(error) { 
     NSLog(@"error:%@",error); 
     return; 
    } 

    // Asset reader output 
    AVAssetReaderOutput *assetReaderOutput =[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoAudioTrack 
                         outputSettings:nil]; 
    if(![assetReader canAddOutput:assetReaderOutput]) { 
     NSLog(@"Can't add output!"); 
     return; 
    } 

    [assetReader addOutput:assetReaderOutput]; 

    // ASSET WRITER 
    AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportUrl 
                  fileType:AVFileTypeAppleM4A 
                  error:&error]; 
    if(error) { 
     NSLog(@"error:%@",error); 
     return; 
    } 

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

    NSDictionary *outputSettings = @{AVFormatIDKey: @(kAudioFormatMPEG4AAC), 
      AVNumberOfChannelsKey: @2, 
      AVSampleRateKey: @44100.0F, 
      AVChannelLayoutKey: [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], 
      AVEncoderBitRateKey: @64000}; 

    /*NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
            [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, 
            [NSNumber numberWithFloat:44100.f], AVSampleRateKey, 
            [NSNumber numberWithInt:2], AVNumberOfChannelsKey, 
            [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey, 
            [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey, 
            [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, 
            [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey, 
            [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey, 
            nil];*/ 

    // Asset writer input 
    AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio 
                       outputSettings:outputSettings]; 
    if ([assetWriter canAddInput:assetWriterInput]) 
     [assetWriter addInput:assetWriterInput]; 
    else { 
     NSLog(@"can't add asset writer input... die!"); 
     return; 
    } 

    assetWriterInput.expectsMediaDataInRealTime = NO; 

    [assetWriter startWriting]; 
    [assetReader startReading]; 

    CMTime startTime = CMTimeMake (0, videoAudioTrack.naturalTimeScale); 
    [assetWriter startSessionAtSourceTime: startTime]; 

    __block UInt64 convertedByteCount = 0; 
    dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL); 

    [assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue 
              usingBlock:^
              { 
               while (assetWriterInput.readyForMoreMediaData) 
               { 
                CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer]; 
                if (nextBuffer) 
                { 
                 // append buffer 
                 [assetWriterInput appendSampleBuffer: nextBuffer]; 
                 convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer); 

                 CMSampleBufferInvalidate(nextBuffer); 
                 CFRelease(nextBuffer); 
                 nextBuffer = NULL; 
                } 
                else 
                { 
                 [assetWriterInput markAsFinished]; 
                 //    [assetWriter finishWriting]; 
                 [assetReader cancelReading]; 

                 break; 
                } 
               } 
              }]; 

Und hier ist der Fehler, den ich mit einem Video erhalten, die eine MP3-Audiospur enthält:

Terminating app due to uncaught exception 
'NSInvalidArgumentException', reason: '*** -[AVAssetWriterInput 
appendSampleBuffer:] Cannot append sample buffer: Input buffer must 
be in an uncompressed format when outputSettings is not nil' 

Jede Hilfe wäre sehr willkommen, danke!

+0

PCM ist rohe Audio - unkomprimiert - es ist eine Reihe von Punkten auf der Audio-Kurve ist ... zuerst die Eingangsaudiodatei konvertieren zu PCM dann von PCM zum gewählten Ausgabeformat (aac) umwandeln ... dieses Muster vereinfacht Konverterlogik –

Antwort

1

Sie sollten in der Lage sein, dies zu erreichen, indem Sie Ihre AVAssetReaderOutput Ausgabeeinstellungen zu konfigurieren:

NSDictionary *readerOutputSettings = @{ AVSampleRateKey: @44100, AVFormatIDKey: @(kAudioFormatLinearPCM) }; 

AVAssetReaderOutput *assetReaderOutput =[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoAudioTrack 
                        outputSettings:readerOutputSettings];