Unsupported header format during conversation of a file from .mov to .wav format and occurs only in the following iOS 11 devices (for example, iOS 9.10)

Below is my code on what I did for this .mov for .wav chains:

- (void)mp4ForURL:(NSURL *)videoURL{

    // Create the asset url with the video file
    AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil];
    NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];

    // Check if video is supported for conversion or not
    if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality])////************************************////
    {
        //Create Export session
        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];////************************************////

        //Creating temp path to save the converted video
        NSString* documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString* myDocumentPath = [documentsDirectory stringByAppendingPathComponent:@"temp.mp4"];
        NSURL *url = [[NSURL alloc] initFileURLWithPath:myDocumentPath];

        //Check if the file already exists then remove the previous file
        if ([[NSFileManager defaultManager]fileExistsAtPath:myDocumentPath])
        {
            [[NSFileManager defaultManager]removeItemAtPath:myDocumentPath error:nil];
        }

        exportSession.outputURL = url;
        //set the output file format if you want to make it in other file format (ex .3gp)
        exportSession.outputFileType = AVFileTypeMPEG4;
        exportSession.shouldOptimizeForNetworkUse = YES;

        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            switch ([exportSession status])
            {
                case AVAssetExportSessionStatusFailed:
                    NSLog(@"Export session failed");
                    break;
                case AVAssetExportSessionStatusCancelled:
                    NSLog(@"Export canceled");
                    break;
                case AVAssetExportSessionStatusCompleted:
                {
                    //Video conversion finished
                    NSLog(@"Successful!");
                    [self convertMP4toMP3withFile:myDocumentPath];
                }
                    break;
                default:
                    break;
            }
        }];
    }
    else
    {
        NSLog(@"Video file not supported!");
    }
}

-(void)convertMP4toCAFwithFile:(NSString*)dstPath //Converted to Core Audio Format .caf
{
    NSURL *dstURL = [NSURL fileURLWithPath:dstPath];

    AVMutableComposition*   newAudioAsset = [AVMutableComposition composition];

    AVMutableCompositionTrack*  dstCompositionTrack;
    dstCompositionTrack = [newAudioAsset addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    AVAsset*    srcAsset = [AVURLAsset URLAssetWithURL:dstURL options:nil];
    AVAssetTrack*   srcTrack = [[srcAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

    CMTimeRange timeRange = srcTrack.timeRange;

    NSError*    error;

    if(NO == [dstCompositionTrack insertTimeRange:timeRange ofTrack:srcTrack atTime:kCMTimeZero error:&error]) {
        NSLog(@"track insert failed: %@\n", error);
        return;
    }

    AVAssetExportSession*   exportSesh = [[AVAssetExportSession alloc] initWithAsset:newAudioAsset presetName:AVAssetExportPresetPassthrough];
    exportSesh.outputFileType = AVFileTypeCoreAudioFormat;
    exportSesh.outputURL = dstURL;

    [[NSFileManager defaultManager] removeItemAtURL:dstURL error:nil];

    [exportSesh exportAsynchronouslyWithCompletionHandler:^{
        AVAssetExportSessionStatus  status = exportSesh.status;
        NSLog(@"exportAsynchronouslyWithCompletionHandler: %li\n", (long)status);

        if(AVAssetExportSessionStatusFailed == status) {
            NSLog(@"FAILURE: %@\n", exportSesh.error);
        } else if(AVAssetExportSessionStatusCompleted == status) {
            NSLog(@"SUCCESS!\n");

            NSError *error;
            //append the name of the file in jpg form

            //check if the file exists (completely unnecessary).
            NSString *onlyPath = [dstPath stringByDeletingLastPathComponent];
            NSInteger randomNumber = arc4random() % 100000;
            strDateAndTime = [self getCurrentDateAndTime];
            strAudioName = [NSString stringWithFormat:@"%@_%ld_%@.%@", @"Audio", (long)randomNumber, strDateAndTime, @"caf"];
            NSString *toPathString = [NSString stringWithFormat:@"%@/%@", onlyPath, strAudioName];
            [[NSFileManager defaultManager] moveItemAtPath:dstPath toPath:toPathString error:&error];

            //[self uploadAudioOnAWSFromPath:toPathString];

            [self convertToWavForFilePath:toPathString];
        }
    }];
}

- (void)convertToWavForFilePath:(NSString *)cafFilePath
{
    // set up an AVAssetReader to read from the iPod Library

    //    NSString *cafFilePath=[[NSBundle mainBundle]pathForResource:@"test" ofType:@"caf"];

    NSURL *assetURL = [NSURL fileURLWithPath:cafFilePath];
    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];

    NSError *assetError = nil;
    AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset
                                                               error:&assetError];

    if (assetError) {
        NSLog (@"error: %@", assetError);
        return;
    }

    AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput
                                              assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
                                              audioSettings: nil];
    if (! [assetReader canAddOutput: assetReaderOutput]) {
        NSLog (@"can't add reader output... die!");
        return;
    }
    [assetReader addOutput: assetReaderOutput];

    NSInteger randomNumber = arc4random() % 100000;
    _finalAudioName = [NSString stringWithFormat:@"%@_%ld_%@", @"Audio", (long)randomNumber, strDateAndTime];
    //    NSString *title = @"MyRec";
    NSArray *docDirs = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docDir = [docDirs objectAtIndex: 0];
    __block NSString *wavFilePath = [[docDir stringByAppendingPathComponent :_finalAudioName]
                                     stringByAppendingPathExtension:@"wav"];

    _finalAudioName = [wavFilePath lastPathComponent];

    if ([[NSFileManager defaultManager] fileExistsAtPath:wavFilePath])
    {
        [[NSFileManager defaultManager] removeItemAtPath:wavFilePath error:nil];
    }
    NSURL *exportURL = [NSURL fileURLWithPath:wavFilePath];
    AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportURL
                                                          fileType:AVFileTypeWAVE
                                                             error:&assetError];
    if (assetError)
    {
        NSLog (@"error: %@", assetError);
        return;
    }

    AudioChannelLayout channelLayout;
    memset(&channelLayout, 0, sizeof(AudioChannelLayout));
    channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
    NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                    [NSNumber numberWithFloat:44100.0], AVSampleRateKey,                                    
                                    [NSNumber numberWithInt:1], 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];

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

    AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
    CMTime startTime = CMTimeMake (0, soundTrack.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);
                 CMTime progressTime = CMSampleBufferGetPresentationTimeStamp(nextBuffer);

                 CMTime sampleDuration = CMSampleBufferGetDuration(nextBuffer);
                 if (CMTIME_IS_NUMERIC(sampleDuration))
                     progressTime= CMTimeAdd(progressTime, sampleDuration);
                 float dProgress= CMTimeGetSeconds(progressTime) / CMTimeGetSeconds(songAsset.duration);
                 NSLog(@"%f",dProgress);
             }
             else
             {
                 [assetWriterInput markAsFinished];
                 [assetReader cancelReading];

                 [assetWriter finishWritingWithCompletionHandler:^{
                     [self uploadAudioOnAWSFromPath:wavFilePath];
                 }];
             }
         }
     }];
}

In the above code, the converted final file, which is in the .wav format, which I must send to the AWS server to get the text from it. For a text conversation, we used the Google Speech API and whenever I send a file that is converted from the bottom to iOS 11 (for example, iOS 9.10), this shows me this error:   Error: WAV header indicates an unsupported format.

Above the error, the Google Speech API is displayed when converting the audio file format (.wav) to text format.

iOS 11, iOS 11 (, iOS 9,10) .

+4

Source: https://habr.com/ru/post/1689723/


All Articles