ios - 如何在运行 session 期间更改 AVCaptureMovieFileOutput 视频方向?

标签 ios iphone video avfoundation

我已经编写了一个捕获设备视频输入的代码,到目前为止它运行良好。这是我设置的

// add preview layer
_previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.videoView.layer addSublayer:_previewLayer];

// add movie output
_movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
[_session addOutput:_movieFileOutput];
AVCaptureConnection *movieFileOutputConnection = [_movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
movieFileOutputConnection.videoOrientation = [self videoOrientationFromCurrentDeviceOrientation];

// start session
[_session startRunning];

地点:

- (AVCaptureVideoOrientation) videoOrientationFromCurrentDeviceOrientation {
    switch ([[UIApplication sharedApplication] statusBarOrientation]) {
        case UIInterfaceOrientationPortrait: {
            return AVCaptureVideoOrientationPortrait;
        }
        case UIInterfaceOrientationLandscapeLeft: {
            return AVCaptureVideoOrientationLandscapeLeft;
        }
        case UIInterfaceOrientationLandscapeRight: {
            return AVCaptureVideoOrientationLandscapeRight;
        }
        case UIInterfaceOrientationPortraitUpsideDown: {
            return AVCaptureVideoOrientationPortraitUpsideDown;
        }
        case UIInterfaceOrientationUnknown: {
            return 0;
        }
    }
}

现在当界面方向改变时我希望我的输出也改变,所以我有这个:

- (void) updatePreviewLayer {
    _previewLayer.frame = CGRectMake(0, 0, self.videoView.frame.size.width, self.videoView.frame.size.height);
    _previewLayer.connection.videoOrientation = [self videoOrientationFromCurrentDeviceOrientation];
    [_session beginConfiguration];
    AVCaptureConnection *movieFileOutpurConnection = [_movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    movieFileOutpurConnection.videoOrientation = [self videoOrientationFromCurrentDeviceOrientation];
    [_session commitConfiguration];
}

但是,可惜它不起作用。似乎一旦我第一次在电影输出上设置视频方向,它就会保持不变,以后无法更改。因此,如果我开始以横向模式拍摄,然后更改为纵向模式,则视频在横向模式下没问题,但纵向模式会旋转。如果我以纵向模式开始也是一样的,横向将被旋转。

有什么办法可以做到这一点吗?

最佳答案

尝试在开始 session 之前添加:

[_movieFileOutput setRecordsVideoOrientationAndMirroringChanges:YES asMetadataTrackForConnection:movieFileOutputConnection];

此方法的头文件文档使其听起来非常像您正在寻找的内容:

Controls whether or not the movie file output will create a timed metadata track that records samples which reflect changes made to the given connection's videoOrientation and videoMirrored properties during recording.

那里有更多有趣的信息,我会全部阅读。

但是,此方法实际上并不会旋转您的帧,它使用定时元数据来指示播放器在播放时执行此操作,因此可能并非所有播放器都支持此功能。如果这是一个交易破坏者,那么你可以放弃 AVCaptureMovieFileOutput 支持较低级别的 AVCaptureVideoDataOutput + AVAssetWriter 组合,其中你的 videoOrientation 更改实际上旋转了帧,导致文件可以在任何播放器中正确播放:

If an AVCaptureVideoDataOutput instance's connection's videoOrientation or videoMirrored properties are set to non-default values, the output applies the desired mirroring and orientation by physically rotating and or flipping sample buffers as they pass through it.

附注如果您只更改一个属性,我认为您不需要 beginConfiguration/commitConfiguration 对,因为这是将多个修改批处理到一个原子更新中。

关于ios - 如何在运行 session 期间更改 AVCaptureMovieFileOutput 视频方向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39830428/

相关文章:

ios - 如何在 Swift 中将数据从外部数据库填充到 UItableView

objective-c - 从 NSUserDefaults 检索数据 - 在一个 View 中有效,但在另一个 View 中失败

iphone - iOS - 在后台执行写入核心数据的多个 AFJSONRequestOperations

ios - 在 swift 3 中为货币格式的字符串设置删除线属性文本

java - 我希望这段代码从 android studio 循环

ios - 在 Sprite Kit 中识别触摸时,Sprite 节点不会移动

iOS Swift 将日历组件 int 月份转换为中型字符串月份

ios - 查看使用 Lightning 端口连接到 iPhone 的设备的电池百分比

javascript - 将 video.js 集成到 Angular Web 应用程序中

video - HTML5 视频 : Force abort of buffering