如何在 运行 会话期间更改 AVCaptureMovieFileOutput 视频方向?
How to change AVCaptureMovieFileOutput video orientation during running session?
我编写了一个捕获设备视频输入的代码,目前运行良好。这是我设置的
// 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];
}
但可惜它不起作用。似乎一旦我第一次在电影输出上设置视频方向,它就会保持不变,以后无法更改。因此,如果我开始以横向模式拍摄,然后更改为纵向模式,则视频在横向模式下没问题,但纵向模式会旋转。如果我以纵向模式开始也是一样的,横向会旋转。
有什么办法可以做到吗?
您是否尝试过在更改配置之前暂停会话?
尝试在开始会话之前添加:
[_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.
p.s。如果您只更改一个 属性,我认为您不需要 beginConfiguration
/commitConfiguration
对,因为那是为了将多个修改批处理到一个原子更新中。
我编写了一个捕获设备视频输入的代码,目前运行良好。这是我设置的
// 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];
}
但可惜它不起作用。似乎一旦我第一次在电影输出上设置视频方向,它就会保持不变,以后无法更改。因此,如果我开始以横向模式拍摄,然后更改为纵向模式,则视频在横向模式下没问题,但纵向模式会旋转。如果我以纵向模式开始也是一样的,横向会旋转。
有什么办法可以做到吗?
您是否尝试过在更改配置之前暂停会话?
尝试在开始会话之前添加:
[_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.
p.s。如果您只更改一个 属性,我认为您不需要 beginConfiguration
/commitConfiguration
对,因为那是为了将多个修改批处理到一个原子更新中。