Невозможно создать видео при использовании AVAssetExportPresetHighestQuality - PullRequest
0 голосов
/ 30 августа 2018

Я пытаюсь создать приложение, которое объединит несколько видео. Кажется, проблема в том, что когда я объединяю инструкции с AVAssetExportPresetHighestQuality, я получаю сообщение об ошибке, что

Не удалось выполнить экспорт -> Причина. Невозможно создать видео. Информация о пользователе: { NSLocalizedDescription = "Операция остановлена"; NSLocalizedFailureReason = "Невозможно создать видео."; NSUnderlyingError = "Ошибка домена = NSOSStatusErrorDomain Code = -17390 \" (null) \ ""; }

Если я изменю его на AVAssetExportPresetPassthrough, он будет работать нормально, но инструкции игнорируются. Кто-нибудь знает, что проблема может быть с помощью следующего кода. Я почти на месте, но эта проблема держит меня.

AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];

    AVMutableCompositionTrack *track = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                   preferredTrackID:kCMPersistentTrackID_Invalid];

    AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];

    CMTime insertTime = kCMTimeZero;

    NSMutableArray *arrayInstructions = [[NSMutableArray alloc] init];

    int i = 0;

    for (NSMutableDictionary * dict in self.arraySelectedAssets) {

            AVAsset *asset = [dict objectForKey:@"avasset"];

            //[self orientationForTrack:asset];

            AVAssetTrack* videoAssetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
            AVAssetTrack* audioAssetTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

            [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:videoAssetTrack atTime:insertTime error:nil];

            [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:audioAssetTrack atTime:insertTime error:nil];

            AVMutableVideoCompositionInstruction *firstVideoCompositionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
            // Set the time range of the first instruction to span the duration of the first video track.
            firstVideoCompositionInstruction.timeRange = CMTimeRangeMake(insertTime, videoAssetTrack.timeRange.duration);


            AVMutableVideoCompositionLayerInstruction* firstVideoLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]];
            CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation( 0,-1334);
            CGAffineTransform rotateBy90Degrees = CGAffineTransformMakeRotation( M_PI_2);
            CGAffineTransform shrinkWidth = CGAffineTransformMakeScale(0.1, 0.1); // needed because Apple does a "stretch" by default - really, we should find and undo apple's stretch - I suspect it'll be a CALayer defaultTransform, or UIView property causing this
            CGAffineTransform finalTransform = CGAffineTransformConcat( shrinkWidth, CGAffineTransformConcat(translateToCenter, rotateBy90Degrees) );
            [firstVideoLayerInstruction setTransform:finalTransform atTime:kCMTimeZero];

            firstVideoCompositionInstruction.layerInstructions = @[firstVideoLayerInstruction];

            [arrayInstructions addObject:firstVideoCompositionInstruction];

        insertTime = CMTimeAdd(insertTime, videoAssetTrack.timeRange.duration);

        i = i + 1;

    }

    AVMutableVideoComposition *mutableVideoComposition = [AVMutableVideoComposition videoComposition];
    mutableVideoComposition.instructions = arrayInstructions;
    mutableVideoComposition.renderSize = CGSizeMake(1334, 750);
    mutableVideoComposition.frameDuration = CMTimeMake(1, 30);


    // 4 - Get path
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
                             [NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];
    self.combinedVideoURL = [NSURL fileURLWithPath:myPathDocs];

    // 5 - Create exporter

    self.timerExporter = [NSTimer scheduledTimerWithTimeInterval:0.01f
                                             target:self
                                           selector:@selector(exporterProgress)
                                           userInfo:nil
                                            repeats:YES];

    // 5 - Create exporter
    self.exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                      presetName:AVAssetExportPresetHighestQuality];
    self.exporter .outputURL=self.combinedVideoURL;
    self.exporter .outputFileType = AVFileTypeQuickTimeMovie;
    self.exporter .shouldOptimizeForNetworkUse = YES;
    self.exporter.videoComposition = mutableVideoComposition;
    [self.exporter  exportAsynchronouslyWithCompletionHandler:^{

        [self.timerExporter invalidate];

        switch (self.exporter.status) {
            case AVAssetExportSessionStatusFailed:
                NSLog(@"Export failed -> Reason: %@, User Info: %@",
                      self.exporter.error.localizedFailureReason,
                      self.exporter.error.userInfo.description);
                [self showError:self.exporter.error.localizedFailureReason];
                break;
            case AVAssetExportSessionStatusCancelled:
                NSLog(@"Export cancelled");
                break;

            case AVAssetExportSessionStatusCompleted:
                NSLog(@"Export finished");

                dispatch_async(dispatch_get_main_queue(), ^{
                    self.labelProgressText.text = [NSString stringWithFormat:@"%@ (100%%)", NSLocalizedString(@"Combining The Videos", nil)];
                    [self applyTheFilter];
                });

                break;

        }

    }];

1 Ответ

0 голосов
/ 30 августа 2018

Боюсь, это не тот ответ, который вы ищете. У меня была та же проблема с преобразованием и экспортом одного видео - AVAssetExportPresetHighestQuality будет работать для одних активов, а не для других.

В то время я предполагал, что неработающие активы имели недостаточно высокий размер / частоту кадров / качество для рендеринга с использованием AVAssetExportPresetHighestQuality.

Как и вы, я использовал AVAssetExportPresetPassthrough. В вашем случае конечный результат, вероятно, будет состоять в том, что все активы, которые вы объединяете, будут отображаться в их первоначальном формате.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...