AVAsset方向/旋转问题

9

尝试使用Ray的优秀教程来解决方向问题。

左侧 - 视频应该看起来的样子(竖屏),右侧 - 不想要的旋转结果

enter image description here

所使用的代码

   func setUpVideoNew()
    {

        let originalVideoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
        let composition = AVMutableComposition()
        let videoTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: 1)
        let timeRange = originalVideoTrack.timeRange
        do {
            try videoTrack.insertTimeRange(timeRange, ofTrack: originalVideoTrack, atTime: kCMTimeZero)
        } catch {

        }
        let mainInstruction = AVMutableVideoCompositionInstruction()
        mainInstruction.timeRange = timeRange

        let firstlayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
        let firstAssetTrack = originalVideoTrack


        //MARK - Fix Rotation
        var firstAssetOrientation_ = UIImageOrientation.Up

        var isFirstAssetPortrait_ = false

        var firstTransform = videoTrack.preferredTransform;
        if firstTransform.a == 0 && firstTransform.b == 1.0 && firstTransform.c == -1.0 && firstTransform.d == 0 {
            firstAssetOrientation_ = UIImageOrientation.Right;
            isFirstAssetPortrait_ = true;
        }
        if (firstTransform.a == 0 && firstTransform.b == -1.0 && firstTransform.c == 1.0 && firstTransform.d == 0) {
            firstAssetOrientation_ =  UIImageOrientation.Left;
            isFirstAssetPortrait_ = true;
        }
        if (firstTransform.a == 1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == 1.0) {
            firstAssetOrientation_ =  UIImageOrientation.Up;
        }
        if (firstTransform.a == -1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == -1.0) {
            firstAssetOrientation_ = UIImageOrientation.Down;
        }

        firstlayerInstruction.setTransform(asset.preferredTransform, atTime: kCMTimeZero)
        mainInstruction.layerInstructions = [firstlayerInstruction]


        let videoComposition = AVMutableVideoComposition()
        videoComposition.frameDuration = CMTimeMake(1, 30)
        videoComposition.instructions = [mainInstruction]

        var naturalSizeFirst = CGSize()

        if(isFirstAssetPortrait_){
            naturalSizeFirst = CGSizeMake(videoTrack.naturalSize.height, videoTrack.naturalSize.width);
        } else {
            naturalSizeFirst = videoTrack.naturalSize;
        }
        videoComposition.renderSize = naturalSizeFirst
        let playerItem = AVPlayerItem(asset: composition)
        playerItem.videoComposition = videoComposition
        player = AVPlayer(playerItem: playerItem)
        let playerLayer = AVPlayerLayer(player: player)
        print(videoPreview.frame)
        print(videoPreview.bounds)
        playerLayer.frame = self.videoPreview.bounds

        player.play()
        self.videoPreview.layer.addSublayer(playerLayer)



    }

有什么建议吗?

我已经在我的问题中添加了你所需要的详细信息。如果您能说明您是否希望其他视图随视频一起旋转,以及其他视图当前旋转的状态(即您的应用程序的其余部分是否旋转),那将非常好。 - owlswipe
2个回答

2

您应该注册通知以便在状态栏改变方向时得到通知,方法如下:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("statusBarOrientationChange:"), name: UIApplicationDidChangeStatusBarOrientationNotification, object: nil)

接下来,针对此操作的 switch 语句将如下所示,用于编辑您的 AVLayer 的尺寸:

    switch (UIApplication.sharedApplication().statusBarOrientation){
        case .Unknown :
        case .PortraitUpsideDown :
        case .Portrait
        case .LandscapeLeft :
        case .LandscapeRight :
    }

当您达到正确的方向时,您需要应用CGAffineTransform,如下所示:

asset.transform = CGAffineTransformMake(M_PI * (180) / 180.0)

希望这对你有所帮助!

嘿dokun。我的应用程序只支持竖屏模式。视频无论屏幕定向如何都在旋转:\ - Roi Mulia
我明白了。你尝试过注册UIDevice方向通知吗?无论屏幕设置如何,UIDevice都会检查方向。 - dokun1
显然问题出在renderSize和transform上面。虽然我仍然没有弄清楚。 - Roi Mulia
视频可以在任何方向上进行录制,因此当视频被录制时,您期望它处于“正立”的正确方向,但如果您根据苹果公司的要求“错误地握住了您的iPhone”,则方向可能是“向右”。录制视频的用户控制方向,最好的方法是如果视频不是正立的,则自行旋转它,如果需要,我可以提供示例代码。 - harmeet07

1
如果问题出现在整个应用程序中旋转iPhone方向上:请确保您的应用程序在Info.plist文件中具有正确的支持界面方向。进入Info.plist,检查底部的两个数组(Supported Interface Orientations和Supported Interface Orientations(iPad))。确保它们都添加了所有四个方向。如果没有,请将鼠标悬停在Supported Interface Orientations上,按下下拉箭头,并按“Supported Interface Orientations”上出现的+号添加任何缺失的方向。对“Supported Interface Orientations(iPad)”数组执行相同操作。

adding supported interface orientations in Info.Plist

如果这不起作用,可能是仅视频的问题。在这里查看问题和已接受的答案:如何解决iOS中的视频方向问题。 以下是将objective-c转换为swift的好方法:https://objectivec2swift.com/#/converter/code
如果您的应用程序不旋转,并且您只想要视频旋转:
请将此代码放入您想要锁定为纵向模式的视图中:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
 return UIInterfaceOrientationMask.Portrait
}

然后,在您的视频视图中:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
 return UIInterfaceOrientationMask.All
}

为了保险起见 - 您可能也希望在两个视图上都使用此功能:

override func shouldAutorotate() -> Bool {
 return true
}

来源:如何使用Swift锁定仅主视图的纵向方向


虽然我不想让我的应用程序能够旋转,但我只需要在视频预览中使用所需的变换来显示视频。 - Roi Mulia
@RoiMulia,让我知道这是否有所帮助! - owlswipe
@RoiMulia 我添加了更多内容;有了这个,你应该能够仅旋转AVAsset的视图,而不让应用程序的其余部分旋转。 - owlswipe
嘿,约翰。很抱歉没有回复你,我不在身边。不幸的是,它没有起到帮助的作用.. :\ - Roi Mulia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接