сохранить видео после обрезки с помощью Zoom uiscrollview swift [dубликат]

Я использую AVCaptureMovieFileOutput для записи некоторого видео. У меня есть слой предварительного просмотра, отображаемый с помощью AVLayerVideoGravityResizeAspectFill, который слегка масштабируется. Проблема заключается в том, что окончательное видео больше, содержащее дополнительное изображение, которое не помещалось на экране во время предварительного просмотра.

Это предварительный просмотр и результирующее видео

Есть ли способ указать CGRect, который я хочу вырезать из видео, используя AVAssetExportSession?

EDIT ----

Когда я применяю CGAffineTransformScale к AVAssetTrack, он масштабируется в видео, а с AVMutableVideoComposition renderSize установлен на view.bounds он обрывает концы. Отлично, осталось всего одну проблему. Ширина видео не растягивается до нужной ширины, она просто заполняется черным.

ИЗМЕНИТЬ 2 ---- Предлагаемый вопрос / ответ неполный ..

Некоторые моего кода:

В моем методе - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error у меня есть это, чтобы обрезать и изменять размер видео.

- (void)flipAndSave:(NSURL *)videoURL withCompletionBlock:(void(^)(NSURL *returnURL))completionBlock
{
    AVURLAsset *firstAsset = [AVURLAsset assetWithURL:videoURL];

    // 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.
    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
    // 2 - Video track
    AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];
    [firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, firstAsset.duration)
                        ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];

    // 2.1 - Create AVMutableVideoCompositionInstruction
    AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    mainInstruction.timeRange = CMTimeRangeMake(CMTimeMakeWithSeconds(0, 600), firstAsset.duration);

    // 2.2 - Create an AVMutableVideoCompositionLayerInstruction for the first track
    AVMutableVideoCompositionLayerInstruction *firstlayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:firstTrack];
    AVAssetTrack *firstAssetTrack = [[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    UIImageOrientation firstAssetOrientation_  = UIImageOrientationUp;
    BOOL isFirstAssetPortrait_  = NO;
    CGAffineTransform firstTransform = firstAssetTrack.preferredTransform;
    if (firstTransform.a == 0 && firstTransform.b == 1.0 && firstTransform.c == -1.0 && firstTransform.d == 0) {
        firstAssetOrientation_ = UIImageOrientationRight;
        isFirstAssetPortrait_ = YES;
    }
    if (firstTransform.a == 0 && firstTransform.b == -1.0 && firstTransform.c == 1.0 && firstTransform.d == 0) {
        firstAssetOrientation_ =  UIImageOrientationLeft;
        isFirstAssetPortrait_ = YES;
    }
    if (firstTransform.a == 1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == 1.0) {
        firstAssetOrientation_ =  UIImageOrientationUp;

    }
    if (firstTransform.a == -1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == -1.0) {
        firstAssetOrientation_ = UIImageOrientationDown;
    }
//    [firstlayerInstruction setTransform:firstAssetTrack.preferredTransform atTime:kCMTimeZero];

//    [firstlayerInstruction setCropRectangle:self.view.bounds atTime:kCMTimeZero];





    CGFloat scale = [self getScaleFromAsset:firstAssetTrack];

    firstTransform = CGAffineTransformScale(firstTransform, scale, scale);

    [firstlayerInstruction setTransform:firstTransform atTime:kCMTimeZero];

    // 2.4 - Add instructions
    mainInstruction.layerInstructions = [NSArray arrayWithObjects:firstlayerInstruction,nil];
    AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
    mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
    mainCompositionInst.frameDuration = CMTimeMake(1, 30);

//    CGSize videoSize = firstAssetTrack.naturalSize;
    CGSize videoSize = self.view.bounds.size;
    BOOL isPortrait_ = [self isVideoPortrait:firstAsset];
    if(isPortrait_) {
        videoSize = CGSizeMake(videoSize.height, videoSize.width);
    }
    NSLog(@"%@", NSStringFromCGSize(videoSize));
    mainCompositionInst.renderSize = videoSize;




    // 3 - Audio track
    AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];
    [AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, firstAsset.duration)
                        ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

    // 4 - Get path
    NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"cutoutput.mov"];
    NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
    NSFileManager *manager = [[NSFileManager alloc] init];
    if ([manager fileExistsAtPath:outputPath])
    {
        [manager removeItemAtPath:outputPath error:nil];
    }
    // 5 - Create exporter
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                      presetName:AVAssetExportPresetHighestQuality];
    exporter.outputURL=outputURL;
    exporter.outputFileType = AVFileTypeQuickTimeMovie;
    exporter.shouldOptimizeForNetworkUse = YES;
    exporter.videoComposition = mainCompositionInst;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        switch ([exporter status])
        {
            case AVAssetExportSessionStatusFailed:
                NSLog(@"Export failed: %@ : %@", [[exporter error] localizedDescription], [exporter error]);
                completionBlock(nil);

                break;
            case AVAssetExportSessionStatusCancelled:

                NSLog(@"Export canceled");
                completionBlock(nil);

                break;
            default: {
                NSURL *outputURL = exporter.outputURL;
                dispatch_async(dispatch_get_main_queue(), ^{
                    completionBlock(outputURL);
                });

                break;
            }
        }
    }];
}
11
задан Darren 12 January 2014 в 22:20
поделиться

1 ответ

AVCaptureVideoDataOutput - это конкретный подкласс класса AVCaptureOutput, который вы используете для обработки несжатых кадров из захваченного видео или для доступа к сжатым кадрам.

Экземпляр AVCaptureVideoDataOutput создает видеофрагменты, которые вы можете обрабатывать с использованием других носителей API-интерфейсы. Вы можете получить доступ к кадрам с помощью метода делегата captureOutput:didOutputSampleBuffer:fromConnection:.

AVCaptureVideoDataOutput Вы используете пресет на сеансе, чтобы указать качество и разрешение изображения, которые вы хотите. Предустановка - это константа, которая идентифицирует один из нескольких возможных конфигураций; в некоторых случаях фактическая конфигурация зависит от устройства:

https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html

фактические значения, которые эти пресеты представляют для различных устройств, см. « https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html » и «Захват неподвижных изображений».

Если вы хотите установить конфигурацию, зависящую от размера, вы должны проверить, поддерживается ли она до ее установки:

if ([session canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
    session.sessionPreset = AVCaptureSessionPreset1280x720;
}
else {
    // Handle the failure.
}
2
ответ дан codercat 15 August 2018 в 12:57
поделиться