1

您好我正在尝试使用 AVMutableComposition 将视频合并在一起。我遇到的问题是 AVAsset trackingWithMediaTypes 方法返回一个空数组并且应用程序崩溃了。

有人可以指出我做错了什么。谢谢

这是我到目前为止所拥有的:

-(void) mergeVideosAndAudio:(AVAsset *)audioAsset{

    //Load Video Assets

    NSError *error;
    NSArray *dirFiles;
    if ((dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self documentsDirectory] error:&error]) == nil) {
        // handle the error
    };
    // find all the temp files
    NSArray *movFiles = [dirFiles filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self BEGINSWITH 'temp'"]];
    NSLog(@"The are %i temp files",movFiles.count);
    NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:[self documentsDirectory]  error:nil];

        //Create the composition
    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];

    // 1 - Video track
    AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];
    CMTime videoTrackDuration;

    for (int j = 0; j < filePathsArray.count; j++) {
        NSURL *url = [NSURL fileURLWithPath:filePathsArray[j]];
        AVURLAsset *currentAsset = [[AVURLAsset alloc]initWithURL:url options:nil];
        videoTrackDuration = CMTimeAdd(videoTrackDuration, currentAsset.duration);
        CMTime time;
        if (j == 0) {
            time = kCMTimeZero;

        }else{
            NSURL *previousAssetURL = [NSURL fileURLWithPath:filePathsArray[j-1]];
            AVURLAsset *previousAsset = [[AVURLAsset alloc]initWithURL:previousAssetURL options:nil];
            time = previousAsset.duration;
        }

        [firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, currentAsset.duration) ofTrack:[[currentAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:time error:nil];
    }

    // 2 - Audio track
    if (audioAsset!=nil){
        AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                            preferredTrackID:kCMPersistentTrackID_Invalid];
        [AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoTrackDuration)
                            ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
    }

    //3 - Get Path for merge
    NSString *myPathDocs =  [[self documentsDirectory] stringByAppendingPathComponent:
                             [NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];
    self.fileURL = [NSURL URLWithString: myPathDocs];

    // 5 - Create exporter
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                      presetName:AVAssetExportPresetHighestQuality];
    exporter.outputURL=self.fileURL;
    exporter.outputFileType = AVFileTypeQuickTimeMovie;
    exporter.shouldOptimizeForNetworkUse = YES;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self exportDidFinish:exporter];
        });
    }];

}
-(void)exportDidFinish:(AVAssetExportSession*)session {
    if (session.status == AVAssetExportSessionStatusCompleted) {
        self.fileURL = session.outputURL;
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:self.fileURL]) {
            [library writeVideoAtPathToSavedPhotosAlbum:self.fileURL 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];
                        [alert show];
                    } else {
                        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"Saved To Photo Album"
                                                                       delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                        [alert show];
                    }
                });
            }];
        }
    }
    [self removeTempFilesFromDocuments];
}

这是错误的屏幕截图: 在此处输入图像描述

4

4 回答 4

0

好吧,错误就在那里“空数组的索引0超出范围”。这意味着您有空的视频资产数组。因此,通过NSFileManager. 去检查数组filePathsArray,有问题。

于 2014-10-23T07:58:28.147 回答
0

首先检查视频是否存在于特定路径并正常运行。

就我而言,视频存在于路径中,但无法运行。这主要是因为视频无法在该路径上正确写入。希望能帮助到你。

于 2015-02-18T10:28:10.423 回答
0

不确定这是否能解决您的问题。但是在我尝试从 url 加载 AVAsset 但获得没有轨道的资产之前,我遇到了这个问题。为我解决的问题是在创建 NSURL 时添加“isDirectory:NO”:

NSURL *url = [NSURL fileURLWithPath:filePathsArray[j] isDirectory:NO];
于 2016-03-16T11:43:17.167 回答
0

请检查您的文件持续时间不应为零。

于 2016-01-21T13:33:54.180 回答