AVFoundation + AssetWriter: Generate Movie With Images and Audio

前端 未结 2 1282
孤独总比滥情好
孤独总比滥情好 2020-12-02 05:04

I have to export a movie from my iPhone application which contains UIImage from an NSArray and add some audio files in .caf format that have to start at pre-specified times.

相关标签:
2条回答
  • 2020-12-02 05:43

    Can you please replace the "for" loop with a single "audioInfo" dictionary which has all the values which need to be set so that it becomes more copy-paste friendly? :)

    If you just want to add a single audio file, the following code should replace the for loop :

    NSString * pathString = [self getAudioFilePath];
    AVURLAsset * urlAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:pathString] options:nil];
    
    AVAssetTrack * audioAssetTrack = [[urlAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio 
                                                        preferredTrackID: kCMPersistentTrackID_Invalid];
    
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,urlAsset.duration) ofTrack:audioAssetTrack atTime:kCMTimeZero error:&error];      
    
    0 讨论(0)
  • 2020-12-02 05:52

    I ended up exporting the video separately using the above code and added the audio files separately using AVComposition & AVExportSession. Here is the code

    -(void) addAudioToFileAtPath:(NSString *) filePath toPath:(NSString *)outFilePath
    {
        NSError * error = nil;
    
        AVMutableComposition * composition = [AVMutableComposition composition];
    
    
        AVURLAsset * videoAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:filePath] options:nil];
    
        AVAssetTrack * videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    
        AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo 
                                                                                    preferredTrackID: kCMPersistentTrackID_Invalid];
    
        [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,videoAsset.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero
                                         error:&error];     
    
        CMTime audioStartTime = kCMTimeZero;
        for (NSDictionary * audioInfo in audioInfoArray)
        {
            NSString * pathString = [audioInfo objectForKey:audioFilePath];
            AVURLAsset * urlAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:pathString] options:nil];
    
            AVAssetTrack * audioAssetTrack = [[urlAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
            AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio 
                                                                                        preferredTrackID: kCMPersistentTrackID_Invalid];
    
            [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,urlAsset.duration) ofTrack:audioAssetTrack atTime:audioStartTime error:&error];      
    
            audioStartTime = CMTimeAdd(audioStartTime, CMTimeMake((int) (([[audioInfo objectForKey:audioDuration] floatValue] * kRecordingFPS) + 0.5), kRecordingFPS));
        }
        AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];  
        assetExport.videoComposition = mutableVideoComposition;
    
        assetExport.outputFileType =AVFileTypeQuickTimeMovie;// @"com.apple.quicktime-movie";
        assetExport.outputURL = [NSURL fileURLWithPath:outFilePath];
    
        [assetExport exportAsynchronouslyWithCompletionHandler:
         ^(void ) {
             switch (assetExport.status) 
             {
                 case AVAssetExportSessionStatusCompleted:
    //                export complete 
                     NSLog(@"Export Complete");
                     break;
                 case AVAssetExportSessionStatusFailed:
                     NSLog(@"Export Failed");
                     NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
    //                export error (see exportSession.error)  
                     break;
                 case AVAssetExportSessionStatusCancelled:
                     NSLog(@"Export Failed");
                     NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
    //                export cancelled  
                     break;
             }
         }];    
    }
    
    0 讨论(0)
提交回复
热议问题