录制视频时在前后摄像头之间切换
Posted
技术标签:
【中文标题】录制视频时在前后摄像头之间切换【英文标题】:Switch between front and back camera while recording a video 【发布时间】:2017-12-26 20:50:17 【问题描述】:我创建了一个自定义摄像头,并尝试添加一个功能,用户可以在。我现在的方法是在他们切换相机时停止并开始一个新视频,但它会切断一点视频,我不知道为什么。我怎样才能让它像 snapchat 一样,以便它获得完整的视频,并且在他们切换相机时不会切断任何东西。到目前为止,这是我的代码
@objc func switchCameraInput()
self.captureSession.beginConfiguration()
var existingConnection:AVCaptureDeviceInput!
for connection in self.captureSession.inputs
let input = connection as! AVCaptureDeviceInput
if input.device.hasMediaType(AVMediaType.video)
existingConnection = input
self.captureSession.removeInput(existingConnection)
turnFlashOff()
var newCamera:AVCaptureDevice!
if let oldCamera = existingConnection
if oldCamera.device.position == .back
newCamera = self.cameraWithPosition(position: .front)
else
newCamera = self.cameraWithPosition(position: .back)
var newInput:AVCaptureDeviceInput!
do
newInput = try AVCaptureDeviceInput(device: newCamera)
self.captureSession.addInput(newInput)
catch
ProgressHUD.showError(error.localizedDescription)
self.captureSession.commitConfiguration()
// This is where i handle switching while recording
if self.movieFileOutput.isRecording
hasSwappedCamera = true
turnFlashOff()
//self.movieFileOutput.stopRecording()
self.movieFileOutput.connection(with: AVMediaType.video)?.videoOrientation = self.videoOrientation()
self.movieFileOutput.maxRecordedDuration = self.maxRecordedDuration()
self.movieFileOutput.startRecording(to: URL(fileURLWithPath:self.videoFileLocation()), recordingDelegate: self)
turnOnFlash()
【问题讨论】:
看来这个问题可以帮到你...***.com/questions/44577331/… @BHendricks 这是在目标 c 中,你有没有机会帮我快速解决? 【参考方案1】:由于 the question 我认为这将有助于回答您在 Objective-C 中的问题,并且您更喜欢 Swift,我已经“翻译”了下面的所有代码。
请注意,我没有编译这个,并且知道一些东西不会编译启动。像 AVMediaTypeVideo
这样的枚举值在 Swift 中通常只是 .video
。另外,我很确定答案有一些不正确的代码,主要是围绕将isFrontRecording
和isBackRecording
布尔值设置回false
。我认为这些应该发生在completionHandler
中,但正如我所提到的,我没有编译这个,所以请谨慎对待。我包含了该问题(Objective-C)中的所有代码以及我对 Swift 的快速而肮脏的翻译。
我希望这会有所帮助:)
目标-C:
/* Front camera settings */
@property bool isFrontRecording;
@property (strong, nonatomic) AVCaptureDeviceInput *videoInputBack;
@property (strong, nonatomic) AVCaptureStillImageOutput *imageOutputBack;
@property (strong, nonatomic) AVCaptureSession *sessionBack;
/* Back camera settings */
@property bool isBackRecording;
@property (strong, nonatomic) AVCaptureDeviceInput *videoInputFront;
@property (strong, nonatomic) AVCaptureStillImageOutput *imageOutputFront;
@property (strong, nonatomic) AVCaptureSession *sessionFront;
斯威夫特:
var isFrontRecording: Bool
var videoInputBack: AVCaptureDeviceInput
var imageOutputBack: AVCaptureStillImageOutput
var sessionBack: AVCaptureSession
var isBackRecording: Bool
var videoInputFront: AVCaptureDeviceInput
var imageOutputFront: AVCaptureStillImageOutput
var sessionFront: AVCaptureSession
目标-C
- (void)viewDidLoad
[super viewDidLoad];
[self setupBackAVCapture];
self.isFrontRecording = NO;
self.isBackRecording = NO;
- (void)setupBackAVCapture
NSError *error = nil;
self.sessionBack = [[AVCaptureSession alloc] init];
self.sessionBack.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.videoInputBack = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
[self.sessionBack addInput:self.videoInputBack];
self.imageOutputBack = [[AVCaptureStillImageOutput alloc] init];
[self.sessionBack addOutput:self.imageOutputBack];
斯威夫特:
override func viewDidLoad()
super.viewDidLoad()
setupBackAVCapture()
isFrontRecording = false
isBackRecording = false
func setupBackAVCapture()
var error: NSError = nil
sessionBack = AVCaptureSession()
sessionBack.sessionPreset = AVCaptureSessionPresetPhoto
let camera: AVCaptureDevice = AVCaptureDevice(defaultDeviceWithMediaType: AVMediaTypeVideo)
videoInputBack = AVCaptureDeviceInput(withDevice: camera, error: error)
sessionBack.addInput(videoInputBack)
imageOutputBack = AVCaptureStillImageOutput()
sessionBack.addOutput(imageOutputBack)
目标-C:
- (IBAction)buttonCapture:(id)sender
[self takeBackPhoto];
- (void)takeBackPhoto
[self.sessionBack startRunning];
if (!self.isFrontRecording)
self.isFrontRecording = YES;
AudioservicesPlaySystemSound(kSystemSoundID_Vibrate);
AVCaptureConnection *videoConnection = [self.imageOutputBack connectionWithMediaType:AVMediaTypeVideo];
if (videoConnection == nil)
return;
[self.imageOutputBack
captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
if (imageDataSampleBuffer == NULL)
return;
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
[self.imageView setImage:image];
[self.sessionBack stopRunning];
// Set up front camera setting and capture photo.
[self setupFrontAVCapture];
[self takeFrontPhoto];
];
self.isFrontRecording = NO;
斯威夫特:
@IBOutlet func buttonCapture(sender: Any)
takeBackPhoto()
func takeBackPhoto()
sessionBack.startRunning()
if !isFrontRecording
isFrontRecording = true
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
let videoConnection: AVCaptureConnection = imageOutputBack.connectionWithMediaType(AVMediaTypeVideo)
guard let videoConnection = videoConnection else
return
imageOutputBack.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler:
imageDataSampleBuffer: CMSSampleBufferRef, error: NSError in
guard let imageDataSampleBuffer = imageDataSampleBuffer else
return
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
let image = UIImage(data: imageData)
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil)
self.imageView.setImage(image)
self.sessionback.stopRunning()
// Set up front camera setting and capture photo.
self.setupFronAVCapture()
self.takeFrontPhoto()
)
isFrontRecording = false
目标-C
- (void)setupFrontAVCapture
NSError *error = nil;
self.sessionFront = [[AVCaptureSession alloc] init];
self.sessionFront.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
camera = [self cameraWithPosition:AVCaptureDevicePositionFront];
self.videoInputFront = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
[self.sessionFront addInput:self.videoInputFront];
self.imageOutputFront = [[AVCaptureStillImageOutput alloc] init];
[self.sessionFront addOutput:self.imageOutputFront];
- (void)takeFrontPhoto
[self.sessionFront startRunning];
if (!self.isBackRecording)
self.isBackRecording = YES;
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
AVCaptureConnection *videoConnection = [self.imageOutputFront connectionWithMediaType:AVMediaTypeVideo];
if (videoConnection == nil)
return;
[self.imageOutputFront
captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
if (imageDataSampleBuffer == NULL)
return;
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
[self.imageViewBack setImage:image];
[self.sessionFront stopRunning];
];
self.isBackRecording = NO;
斯威夫特:
func setupFrontAVCapture()
let error: NSError = nil
sessionFront = AVCaptureSession()
sessionFront.sessionPreset = AVCaptureSessionPresentPhoto
var camera: AVCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
camera = camera.cameraWithPosition(AVCaptureDevicePositionFront)
videoInputFront = AVCaptureDeviceInput(withDevice: camera, error: error)
sessionFront.addInput(videoInputFront)
imageOutputFront = AVCaptureStillImageOutput()
sessionFront.addOutput(imageOutputFront)
func takeFrontPhoto()
sessionFront.startRunning()
if !isBackRecording
isBackRecording = true
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
let videoConnection: AVCaptureConnection = imageOutputFront.connectionWithMediaType(AVMediaTypeVideo)
guard let videoConnection = videoConnection else
return
imageOutputFront.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler:
imageDataSampleBuffer: CMSampleBufferRef, error: NSError in
guard let imageDataSampleBuffer = imageDataSampleBuffer else
return
let imageData: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
let image = UIImage(data: imageData)
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil)
self.imageViewBack.setImage(image)
self.sessionFront.stopRunning()
)
isBackRecording = false
祝你好运,让你的项目开始工作!
【讨论】:
它适用于静止图像,但在视频录制时切换相机仍然不清楚。【参考方案2】:我为这个完全相同的问题找到了一个合适的解决方案,而不是用一个捕获会话和一个输出来切换输入,您必须为每个输入(相机)创建一个会话,然后在它们之间切换输出。
您可以在这里找到更多详细信息:https://***.com/a/54770398/2448590
【讨论】:
以上是关于录制视频时在前后摄像头之间切换的主要内容,如果未能解决你的问题,请参考以下文章