• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 使用 AVAsset/AVCaptureSession 的方形视频方向不会从横向变为纵向

[复制链接]
菜鸟教程小白 发表于 2022-12-12 11:53:28 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在尝试使用 AVCaptureSession 创建方形视频,并且我成功捕获了视频,但问题是如果我的设备是纵向模式并且我正在捕获视频,那么它的方向记录正确,但如果我的设备是横向的,我捕捉视频我想将此视频方向更改为纵向。以下代码用于在捕获后裁剪视频:

-(void)cropViewNSURL*)outputfile
{
    AVAsset *asset = [AVAsset assetWithURLutputfile];
    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition];
    videoComposition.frameDuration = CMTimeMake(1, 30);
    videoComposition.renderSize =CGSizeMake(clipVideoTrack.naturalSize.height, clipVideoTrack.naturalSize.height);


    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30));

    // rotate to portrait
    AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];
    CGAffineTransform t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.height, -(clipVideoTrack.naturalSize.width - clipVideoTrack.naturalSize.height) /2 );
    CGAffineTransform t2 = CGAffineTransformRotate(t1, M_PI_2);

    CGAffineTransform finalTransform = t2;
    [transformer setTransform:finalTransform atTime:kCMTimeZero];
    instruction.layerInstructions = [NSArray arrayWithObject:transformer];
    videoComposition.instructions = [NSArray arrayWithObject: instruction];


    NSString *outputPath = [NSString stringWithFormat"%@%@", NSTemporaryDirectory(), @"video.mp4"];
    NSURL *exportUrl = [NSURL fileURLWithPathutputPath];

    [[NSFileManager defaultManager]  removeItemAtURL:exportUrl error:nil];


    //Export
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ;
    exporter.videoComposition = videoComposition;
    exporter.outputURL = exportUrl;
    exporter.outputFileType = AVFileTypeMPEG4;


    [exporter exportAsynchronouslyWithCompletionHandler:^
     {
         dispatch_async(dispatch_get_main_queue(), ^{
             //Call when finished
             [self exportDidFinish:exporter];
         });
     }];
}



Best Answer-推荐答案


我只是通过使用以下代码和步骤来解决问题:

首先我的设备方向是锁定的,我的应用程序只支持纵向,所以我认为我只能获得纵向但是我通过横向模式捕获视频,所以使用 Core-motion 我使用以下方法获取设备方向代码

#import

@interface ViewController ()
{
     AVCaptureVideoOrientation orientationLast, orientationAfterProcess;
  CMMotionManager *motionManager;
}

@implementation ViewController

- (void)initializeMotionManager{
    motionManager = [[CMMotionManager alloc] init];
    motionManager.accelerometerUpdateInterval = .2;
    motionManager.gyroUpdateInterval = .2;

    [motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
                                        withHandler:^(CMAccelerometerData  *accelerometerData, NSError *error) {
                                            if (!error) {
                                                [self outputAccelertionData:accelerometerData.acceleration];
                                            }
                                            else{
                                                NSLog(@"%@", error);
                                            }
                                        }];
}
- (void)outputAccelertionDataCMAcceleration)acceleration{
    AVCaptureVideoOrientation orientationNew;

    if (acceleration.x >= 0.75) {
        orientationNew = AVCaptureVideoOrientationLandscapeLeft;
    }
    else if (acceleration.x <= -0.75) {
        orientationNew =AVCaptureVideoOrientationLandscapeRight;
    }
    else if (acceleration.y <= -0.75) {
        orientationNew =AVCaptureVideoOrientationPortrait;
    }
    else if (acceleration.y >= 0.75) {
        orientationNew =AVCaptureVideoOrientationPortraitUpsideDown;
    }
    else {
        // Consider same as last time
        return;
    }

    if (orientationNew == orientationLast)
        return;

    orientationLast = orientationNew;
}

所以基于设备旋转 orientationLast 更新设备方向。之后,当我点击录制视频的按钮时,我设置了 AVCaptureConnection 方向。

AVCaptureConnection *CaptureConnection = [MovieFileOutput connectionWithMediaType:AVMediaTypeVideo];

    if ([CaptureConnection isVideoOrientationSupported])
    {
        [CaptureConnection setVideoOrientationrientationLast];
    }

现在拍摄视频后。我做了以下代码的裁剪时间,效果很好。

-(void)cropViewNSURL*)outputfile
{
     AVAsset *asset = [AVAsset assetWithURLutputfile];


    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition];
    videoComposition.frameDuration = CMTimeMake(1, 30);

    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30));

    CGSize videoSize = [[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] naturalSize];
    float scaleFactor;

    if (videoSize.width > videoSize.height) {

        scaleFactor = videoSize.height/320;
    }
    else if (videoSize.width == videoSize.height){

        scaleFactor = videoSize.height/320;
    }
    else{
        scaleFactor = videoSize.width/320;
    }



    CGFloat cropOffX = 0;
    CGFloat cropOffY = 0;
    CGFloat cropWidth = 320 *scaleFactor;
    CGFloat cropHeight = 320 *scaleFactor;

    videoComposition.renderSize = CGSizeMake(cropWidth, cropHeight);

    AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];

    UIImageOrientation videoOrientation = [self getVideoOrientationFromAsset:asset];

    CGAffineTransform t1 = CGAffineTransformIdentity;
    CGAffineTransform t2 = CGAffineTransformIdentity;

    switch (videoOrientation) {
        case UIImageOrientationUp:
            t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.height - cropOffX, 0 - cropOffY );
            t2 = CGAffineTransformRotate(t1, M_PI_2 );
            break;
        case UIImageOrientationDown:
            t1 = CGAffineTransformMakeTranslation(0 - cropOffX, clipVideoTrack.naturalSize.width - cropOffY ); // not fixed width is the real height in upside down
            t2 = CGAffineTransformRotate(t1, - M_PI_2 );
            break;
        case UIImageOrientationRight:
            t1 = CGAffineTransformMakeTranslation(0 - cropOffX, 0 - cropOffY );
            t2 = CGAffineTransformRotate(t1, 0 );
            break;
        case UIImageOrientationLeft:
            t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.width - cropOffX, clipVideoTrack.naturalSize.height - cropOffY );
            t2 = CGAffineTransformRotate(t1, M_PI  );
            break;
        default:
            NSLog(@"no supported orientation has been found in this video");
            break;
    }

    CGAffineTransform finalTransform = t2;
    [transformer setTransform:finalTransform atTime:kCMTimeZero];

    //add the transformer layer instructions, then add to video composition
    instruction.layerInstructions = [NSArray arrayWithObject:transformer];
    videoComposition.instructions = [NSArray arrayWithObject: instruction];


    NSString *outputPath = [NSString stringWithFormat"%@%@", NSTemporaryDirectory(), @"video.mp4"];
    NSURL *exportUrl = [NSURL fileURLWithPathutputPath];

    [[NSFileManager defaultManager]  removeItemAtURL:exportUrl error:nil];


    //Export
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ;
    exporter.videoComposition = videoComposition;
    exporter.outputURL = exportUrl;
    exporter.outputFileType = AVFileTypeMPEG4;


    [exporter exportAsynchronouslyWithCompletionHandler:^
     {
         dispatch_async(dispatch_get_main_queue(), ^{
             //Call when finished
             [self exportDidFinish:exporter];
         });
     }];

}

- (UIImageOrientation)getVideoOrientationFromAssetAVAsset *)asset
{
    AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    CGSize size = [videoTrack naturalSize];
    CGAffineTransform txf = [videoTrack preferredTransform];

    if (size.width == txf.tx && size.height == txf.ty)
        return UIImageOrientationLeft; //return UIInterfaceOrientationLandscapeLeft;
    else if (txf.tx == 0 && txf.ty == 0)
        return UIImageOrientationRight; //return UIInterfaceOrientationLandscapeRight;
    else if (txf.tx == 0 && txf.ty == size.width)
        return UIImageOrientationDown; //return UIInterfaceOrientationPortraitUpsideDown;
    else
        return UIImageOrientationUp;  //return UIInterfaceOrientationPortrait;
}

关于ios - 使用 AVAsset/AVCaptureSession 的方形视频方向不会从横向变为纵向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38912280/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap