我无法弄清楚如何处理前置摄像头视频拍摄方向。在捕捉视频和图片以及拍摄照片时为前置摄像头处理的所有旋转时,我都为后置摄像头处理了所有旋转,并且除了前置摄像头视频捕获外,还保存了正确方向的捕获视频和图片。
第一个问题是在横向模式下,视频无法以正确的方向正确保存。第二个问题是保存的视频是镜像的。虽然我知道如何使用前置摄像头处理图像的这种镜像效果,但我不确定要为视频处理它的内容。
我在尝试找到专门针对这一问题的任何内容时遇到了很多麻烦,但未能这样做。如果有人能指出我解决这个特定问题的线程,那就太好了。
无论哪种方式,这里调用的方法是在设备方向改变时处理视频方向。如果正在使用前置摄像头,我不确定要添加到我的代码中的确切内容。
/**************************************************************************
DEVICE ORIENTATION DID CHANGE
**************************************************************************/
func deviceOrientationDidChange() {
println("DEVICE ORIENTATION DID CHANGE CALLED")
let orientation: UIDeviceOrientation = UIDevice.currentDevice().orientation
//------ IGNORE THESE ORIENTATIONS ------
if orientation == UIDeviceOrientation.FaceUp || orientation == UIDeviceOrientation.FaceDown || orientation == UIDeviceOrientation.Unknown || orientation == UIDeviceOrientation.PortraitUpsideDown || self.currentOrientation == orientation {
println("device orientation does not need to change --- returning...")
return
}
self.currentOrientation = orientation
//------ APPLY A ROTATION USING THE STANDARD ROTATION TRANSFORMATION MATRIX in R3 ------
/*
x y z
--- ---
x | cosø sinø 0 |
y | -sinø consø 0 |
z | 0 0 1 |
--- ---
*/
//----- PERFORM BUTTON AND VIDEO DATA BUFFER ROTATIONS ------
switch orientation {
case UIDeviceOrientation.Portrait:
rotateButtons(self.degrees0)
if self.usingFrontCamera == true {
}
else {
}
println("Device Orientation Portrait")
break
case UIDeviceOrientation.LandscapeLeft:
println("Device Orientation LandScapeLeft")
rotateButtons(self.degrees90)
if self.usingFrontCamera == true {
println("Using front camera, rotation in landscape left")
// if let connection = self.captureConnection {
//
// connection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
//
// println("Capture connection Orientation is LandScape Right")
// }
// else {
//
// println("Capture connection is nil, could not change video orientation")
// }
}
else {
if let connection = self.captureConnection {
connection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
println("Capture connection Orientation is LandScape Right")
}
else {
println("Capture connection is nil, could not change video orientation")
}
}
break
case UIDeviceOrientation.LandscapeRight:
println("Device Orientation LandscapeRight")
rotateButtons(-self.degrees90)
if self.usingFrontCamera == true {
println("Using front camera, rotation in landscape right")
// if let connection = self.captureConnection {
//
// connection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
//
// println("Capture connection Orientation is LandScape Left")
// }
// else {
//
// println("Capture connection is nil, could not change video orientation")
// }
}
else {
if let connection = self.captureConnection {
connection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
println("Capture connection Orientation is LandScape Left")
}
else {
println("Capture connection is nil, could not change video orientation")
}
}
break
default:
break
}
}
答案 0 :(得分:14)
基于这个答案:Video Saving in the wrong orientation AVCaptureSession
我遇到了同样的问题,并且能够在此帖后修复它。
var videoConnection:AVCaptureConnection?
for connection in self.fileOutput.connections {
for port in connection.inputPorts! {
if port.mediaType == AVMediaTypeVideo {
videoConnection = connection as? AVCaptureConnection
if videoConnection!.supportsVideoMirroring {
videoConnection!.videoMirrored = true
}
}
}
}
}
请告诉我詹姆斯是否有帮助
答案 1 :(得分:1)
接受的答案只会在预览中反映视频。您需要转换视频。
func mirrorVideo(inputURL: URL, completion: @escaping (_ outputURL : URL?) -> ())
{
let videoAsset: AVAsset = AVAsset( url: inputURL )
let clipVideoTrack = videoAsset.tracks( withMediaType: AVMediaType.video ).first! as AVAssetTrack
let composition = AVMutableComposition()
composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID())
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.width)
videoComposition.frameDuration = CMTimeMake(1, 30)
let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30))
var transform:CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0)
transform = transform.translatedBy(x: -clipVideoTrack.naturalSize.width, y: 0.0)
transform = transform.rotated(by: CGFloat(Double.pi/2))
transform = transform.translatedBy(x: 0.0, y: -clipVideoTrack.naturalSize.width)
transformer.setTransform(transform, at: kCMTimeZero)
instruction.layerInstructions = [transformer]
videoComposition.instructions = [instruction]
// Export
let exportSession = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPreset640x480)!
let fileName = UniqueIDGenerator.generate().appending(".mp4")
let filePath = documentsURL.appendingPathComponent(fileName)
let croppedOutputFileUrl = filePath
exportSession.outputURL = croppedOutputFileUrl
exportSession.outputFileType = AVFileType.mp4
exportSession.videoComposition = videoComposition
exportSession.exportAsynchronously {
if exportSession.status == .completed {
DispatchQueue.main.async(execute: {
completion(croppedOutputFileUrl)
})
return
} else if exportSession.status == .failed {
print("Export failed - \(String(describing: exportSession.error))")
}
completion(nil)
return
}
}
在 AVCaptureFileOutputRecordingDelegate
中 func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
self.mirrorVideo(inputURL: outputFileURL) { (url) in
self.delegate!.videoRecordingEnded(videoURL: url!)
}
}
答案 2 :(得分:0)
Kesong在Sam的答案中的评论可用于转换视频本身,而不仅仅是预览。确保先检查是否支持videoMirroring,并确保在设置isVideoMirrored属性之前禁用自动调整视频镜像,否则应用程序可能会崩溃。
以下代码适用于Swift5。您可以在将AVCaptureSession附加到AVCaptureMovieFileOutput后使用此代码。
if let videoConnection = movieFileOutput.connection(with: .video) {
if videoConnection.isVideoMirroringSupported {
if frontCamera { //For selfie camera, flip the output video so it doesn't appear mirrored
videoConnection.automaticallyAdjustsVideoMirroring = false
videoConnection.isVideoMirrored = true
} else {
videoConnection.automaticallyAdjustsVideoMirroring = true
}
}
}