I have a custom view in a storyboard with a ViewController to show me the output of a AVCaptureSessionPreviewLayer (in this case, webcam footage). When using a custom view in my normal window, all is fine and I see video output.
But when I want to use a custom view in a sheet dialog, the video is not visible even though the webcam indicates that is running.
Here is the ViewController code:
import Cocoa
import AVKit
class RecordViewController: NSViewController {
let captureSession = AVCaptureSession()
var captureDevice : AVCaptureDevice?
var previewLayer : AVCaptureVideoPreviewLayer?
#IBOutlet weak var camera: NSView!
override func viewDidLoad() {
super.viewDidLoad()
camera.wantsLayer = true;
camera.layer = CALayer()
// Do any additional setup after loading the view, typically from a nib.
captureSession.sessionPreset = AVCaptureSession.Preset.medium
// Get all audio and video devices on this machine
let devices = AVCaptureDevice.devices()
// Find the FaceTime HD camera object
for device in devices {
print(device)
// Camera object found and assign it to captureDevice
if ((device as AnyObject).hasMediaType(AVMediaType.video)) {
print(device)
captureDevice = device as? AVCaptureDevice
}
}
if captureDevice != nil {
do {
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.frame = (self.camera.layer?.frame)!
// Add previewLayer into custom view
self.camera.layer?.addSublayer(previewLayer!)
// Start camera
captureSession.startRunning()
} catch {
print(AVCaptureSessionErrorKey.description)
}
} }
}
Change the line:
previewLayer?.frame = (self.camera.layer?.frame)!
to:
previewLayer?.frame = self.camera.bounds
And if you want to make your camera fill your customView use this line too:
previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
Related
I am new in Swift and I try to implement a camera app in landscape mode (left and right).
I tried a video tutorial, the camera app basically works but just in portrait mode (not landscape).
If I enable landscape left + right in the project (and I disenable portrait mode), the camera looks like this:
What am I doing wrong? I found some posts about the same problem, but none of them helped me to solve the problem.
Best Regards
I tried affine transformation like CGAffineTransform(rotationAngle: -90) but this also doesn't solve the problem.
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var cameraView: UIView!
var captureSession: AVCaptureSession?
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var backCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 10.2, *)
{
let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
do
{
let input = try AVCaptureDeviceInput(device: captureDevice!)
captureSession = AVCaptureSession()
captureSession?.addInput(input)
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
videoPreviewLayer?.frame = view.layer.bounds
cameraView.layer.addSublayer(videoPreviewLayer!)
captureSession?.startRunning()
}
catch
{
print("error")
}
}
}
Try this:
private var previewLayer: AVCaptureVideoPreviewLayer?
previewLayer?.connection?.videoOrientation = .landscapeLeft
previewLayer?.connection?.videoOrientation = .portrait
I am learning Swift - making progress. My application should scan a barcode. I am trying to show the camera in the middle of the screen between two strips of spaces above and below the UIview. There is a button at bottom strip of space to save the barcode number. My issue is, I need to show the status bar at the top of the screen with signal strength, time, battery etc., when user is scanning, but it is covered by the UI view when it open camera. I have reviewed other posts and incorporated the suggestions, but the issue persists. Any help is appreciated.
I have uploaded image showing the covered status bar.
Here is my code:
class ScannerViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
#IBOutlet weak var cameraView: UIView!
#IBOutlet weak var selectScan1: UIButton!
var captureSession: AVCaptureSession!
var previewLayer: AVCaptureVideoPreviewLayer!
override func viewDidLoad() {
super.viewDidLoad()
// view.backgroundColor = UIColor.black
captureSession = AVCaptureSession()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed()
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417]
} else {
failed()
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
previewLayer?.frame = self.cameraView.layer.frame
cameraView.layer.addSublayer(previewLayer!)
// **** note: select click to bounds check box in storyboard
captureSession.startRunning()
}
I try to use my camera's view (blurred) as background in my main menu.
I'm a beginner and have no idea how to do this...
please don't answer with "use ARSCNView"; I've tried this.
(best: send me a code in swift; I shouldn't be too long huh?)
After trying your code I have these errors:
my code
import UIKit
import AVFoundation
class TestingViewController: UIViewController {
let session: AVCaptureSession = AVCaptureSession()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
session.sessionPreset = AVCaptureSession.Preset.high
if let device = AVCaptureDevice.default(for: AVMediaType.video) {
do {
try session.addInput(AVCaptureDeviceInput(device: device))
} catch {
print(error.localizedDescription)
}
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
self.view.layer.addSublayer(previewLayer)
previewLayer.frame = self.view.layer.bounds
}
session.startRunning()
let blur = UIBlurEffect(style: .regular)
let blurView = UIVisualEffectView(effect: blur)
blurView.frame = self.view.bounds
blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(blurView)
}
}
try this updated code and dont forget to add
"Privacy - Camera Usage Description" in your info.plist file
Want to preload textureAtlases before game starts, so I decided to put scene starter code into completion handler, but for some reason app crashes. Here is my code:
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let gpuAtlas = SKTextureAtlas(named: "GP")
let ppAtlas = SKTextureAtlas(named: "PP")
SKTextureAtlas.preloadTextureAtlases([gpuAtlas, ppAtlas]) {
if let view = self.view as? SKView {
let scene = GameScene(size: self.view.bounds.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var prefersStatusBarHidden: Bool {
return true
}
}
If I remove preload texture atlas method everything will work as usual, but I want preload textures to have a change to get rid of first keyframe freeze because of loading textures in cache.
Error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Update:
It crashes on GameScene.swift file in method didSimulatePhysics.
What I do wrong guys?
Try this (use main thread for manipulation with view and weak self):
SKTextureAtlas.preloadTextureAtlases([gpuAtlas, ppAtlas]) { [weak self] in
guard let gameView = self?.view as? SKView else { return }
DispatchQueue.main.async {
let scene = GameScene(size: gameView.bounds.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
gameView.presentScene(scene)
gameView.ignoresSiblingOrder = true
gameView.showsFPS = true
gameView.showsNodeCount = true
}
}
Did you check if scene is optional? If so:
guard let scene = GameScene(size: gameView.bounds.size) else { return }
This
let gpuAtlas = SKTextureAtlas(named: "GP")
let ppAtlas = SKTextureAtlas(named: "PP")
SKTextureAtlas.preloadTextureAtlases([GP, PP]) {}
should not compile - the variables are named gpuAtlas and ppAtlas and not GP and PP.
I am trying to program a button to set a UserDefault to true. And when the view loads I want it to check if the value of the user default is true. If it is I want it to follow through with a line of code.
Here is my code:
import UIKit
import SpriteKit
import AVFoundation
var bombSoundEffect: AVAudioPlayer!
let instruct = UserDefaults.standard
class GameViewController: UIViewController {
#IBOutlet weak var intructions: UIButton!
#IBAction func intructions(_ sender: AnyObject) {
instruct.set(true, forKey: "instructions")
}
override func viewDidLoad() {
super.viewDidLoad()
if instruct.value(forKey: "instructions") {
intructions.isHidden = true
}
let path = Bundle.main.path(forResource: "Untitled2.wav", ofType:nil)!
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOf: url)
bombSoundEffect = sound
sound.numberOfLoops = -1
sound.play()
} catch {
// couldn't load file :(
}
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .aspectFill
scene.size = self.view.bounds.size
skView.presentScene(scene)
}
}
Change
if instruct.value(forKey: "instructions")
to
if instruct.bool(forKey: "instructions")