1

我有一个应用程序,我需要将音频文件合并到 AVCapture 会话录制的视频中,以便可以听到录制电影的音频和合并的音频。

我能够使用 avcomposition 将音频合并到视频中,并且效果很好。但问题是无法听到原始音频文件。这是我的代码。

NSString *resourceAudioName = [NSString stringWithFormat:@"%@_audio",getTitle];
NSURL    *audio_inputFileUrl = [[NSBundle mainBundle] URLForResource:resourceAudioName withExtension:@"mp3"];

NSString  *    video_inputFilePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
video_inputFilePath = [video_inputFilePath stringByAppendingPathComponent:@"movie1.mp4"];

self.outputFilePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"/Documents/OutPutMovie-%@.mp4",[NSDate date]]];
NSURL     *   outputFileUrl = [NSURL fileURLWithPath:self.outputFilePath];
if (audio_inputFileUrl) {

    AVMutableComposition* mixComposition = [AVMutableComposition composition];
    NSURL    *    video_inputFileUrl = [NSURL fileURLWithPath:video_inputFilePath];
    CMTime nextClipStartTime = kCMTimeZero;
    AVURLAsset      *    videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil];
    NSArray         *   videoAssetTracks2 = [videoAsset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetTrack     *   videoAssetTrack2 = ([videoAssetTracks2 count] > 0 ? [videoAssetTracks2 objectAtIndex:0] : nil);
    CMTimeRange        video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
    AVMutableCompositionTrack   *    a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    [a_compositionVideoTrack     insertTimeRange:video_timeRange ofTrack:videoAssetTrack2 atTime:nextClipStartTime error:nil];

    AVURLAsset      *     audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil];
    NSArray         *    videoAssetTracks = [audioAsset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack     *    videoAssetTrack = ([videoAssetTracks count] > 0 ? [videoAssetTracks objectAtIndex:0] : nil);
    CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);
    AVMutableCompositionTrack     *    b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [b_compositionAudioTrack        insertTimeRange:audio_timeRange ofTrack:videoAssetTrack atTime:nextClipStartTime error:nil];


    AVAssetExportSession      * _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
    _assetExport.outputFileType = @"com.apple.quicktime-movie";
    _assetExport.outputURL = outputFileUrl;
        [_assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void ) {


         if (AVAssetExportSessionStatusCompleted == _assetExport.status) {
            [videoAsset release];
             [audioAsset release];
             [_assetExport release];
             [self performSelectorOnMainThread:@selector(moveNextView) withObject:nil waitUntilDone:YES];
         }
         }
     ];
4

2 回答 2

1
 -(void)mergeAndSave
  {
//Create AVMutableComposition Object which will hold our multiple       AVMutableCompositionTrack or we can say it will hold our video and audio files.
AVMutableComposition* mixComposition = [AVMutableComposition composition];

//Now first load your audio file using AVURLAsset. Make sure you give the correct path of your videos.
NSURL *audio_url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"kick" ofType:@"mp3"]];
self.audioAsset = [[AVURLAsset alloc]initWithURL:audio_url options:nil];
CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, self.audioAsset.duration);

//Now we are creating the first AVMutableCompositionTrack containing our audio and add it to our AVMutableComposition object.
AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[self.audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

//Now we will load video file.
NSURL *video_url = mediaUrl;
self.videoAsset = [[AVURLAsset alloc]initWithURL:video_url options:nil];
CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,self.audioAsset.duration);


//Now we are creating the second AVMutableCompositionTrack containing our video and add it to our AVMutableComposition object.
AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];

//decide the path where you want to store the final video created with audio and video merge.
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSString *outputFilePath = [docsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"video.mov"]];
NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
    [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];

//Now create an AVAssetExportSession object that will save your final video at specified path.
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.outputFileType = @"com.apple.quicktime-movie";
_assetExport.outputURL = outputFileUrl;

[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) {
     dispatch_async(dispatch_get_main_queue(), ^{
         [self exportDidFinish:_assetExport];
     });
 }
 ];

}

   - (void)exportDidFinish:(AVAssetExportSession*)session
   {
if(session.status == AVAssetExportSessionStatusCompleted){
    NSURL *outputURL = session.outputURL;
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {
        [library writeVideoAtPathToSavedPhotosAlbum:outputURL
                                    completionBlock:^(NSURL *assetURL, NSError *error){
                                        dispatch_async(dispatch_get_main_queue(), ^{
                                            if (error) {
                                                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Video Saving Failed"  delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil, nil];
                                                [alert show];
                                            }else{
                                                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"Saved To Photo Album"  delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
                                                [alert show];
                                                //[self loadMoviePlayer:outputURL];
                                            }
                                        });
                                    }];
    }
}
 self.audioAsset = nil;
 self.videoAsset = nil;
//[activityView stopAnimating];
//[activityView setHidden:YES];

}

尝试这个

于 2015-09-08T14:32:42.283 回答
0

我相信您必须使用AVMutableAudioMix才能混合多个音频。使用您的方法,只会将其audioAsset添加到组合中。WWDC 2010中有一个关于此的视频,其中解释了如何执行此操作。我试图在这里实施但没有成功。希望有人能帮助我们修复它。

于 2013-08-07T18:27:07.203 回答