https://superhahnah.com/swift-avcapture-settings/
https://superhahnah.com/swift-camera-position-switching/
今、録画アプリを試しに作っているのですが。
上記の二つのサイトを使い(自分好みに少々改良)録画アプリに切り替え機能をつけたのですが、録画開始ボタンを押した時エラーが発生してしまいました。
かなり長くて申し訳ないのですが、下記のコードでどこを直せばよろしいでしょうか?
録画アプリのコード
import UIKit import AVFoundation class PlayVideoViewController: UIViewController, AVCaptureFileOutputRecordingDelegate{ var captureSession: AVCaptureSession? = nil var previewLayer: AVCaptureVideoPreviewLayer? = nil var videoDevice: AVCaptureDevice? let fileOutput = AVCaptureMovieFileOutput() var reverseButton: UIButton = UIButton() var recordAcitnoButton = UIButton() override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black self.setupCaptureSession(withPosition: .back) self.setupPreviewLayer() self.setupReverseButton() self.zoomSlider() self.recordButton() } func setupCaptureSession(withPosition cameraPosition: AVCaptureDevice.Position) { self.videoDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType.video, position: cameraPosition) let audioDevice: AVCaptureDevice? = AVCaptureDevice.default(for: AVMediaType.audio) self.captureSession = AVCaptureSession() // add video input to a capture session let videoInput = try! AVCaptureDeviceInput(device: self.videoDevice!) self.captureSession?.addInput(videoInput) let audioInput = try! AVCaptureDeviceInput(device: audioDevice!) captureSession?.addInput(audioInput) // add capture output let captureOutput: AVCaptureMovieFileOutput = AVCaptureMovieFileOutput() self.captureSession?.addOutput(captureOutput) self.fileOutput.maxRecordedDuration = CMTimeMake(value: 60, timescale: 1) captureSession?.sessionPreset = AVCaptureSession.Preset.high self.captureSession?.startRunning() } func setupPreviewLayer() { // camera apreview layer self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession!) self.previewLayer?.frame = self.view.bounds self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill self.view.layer.addSublayer(self.previewLayer!) } func setupReverseButton() { // camera-reversing button self.reverseButton.frame = CGRect(x: 0, y: 0, width: 300, height: 70) self.reverseButton.center = self.view.center self.reverseButton.backgroundColor = UIColor.lightGray.withAlphaComponent(0.5) self.reverseButton.setTitle("Reverse Camera Position", for: .normal) self.reverseButton.setTitleColor(UIColor.white, for: .normal) self.reverseButton.setTitleColor(UIColor.lightGray, for: .disabled) self.reverseButton.addTarget(self, action: #selector(self.onTapReverseButton(sender:)), for: .touchUpInside) self.view.addSubview(self.reverseButton) } @objc func onTapReverseButton(sender: UIButton) { self.reverseCameraPosition() } func reverseCameraPosition() { self.captureSession?.stopRunning() self.captureSession?.inputs.forEach { input in self.captureSession?.removeInput(input) } self.captureSession?.outputs.forEach { output in self.captureSession?.removeOutput(output) } // prepare new camera preview let newCameraPosition: AVCaptureDevice.Position = self.videoDevice?.position == .front ? .back : .front self.setupCaptureSession(withPosition: newCameraPosition) let newVideoLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession!) newVideoLayer.frame = self.view.bounds newVideoLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill // horizontal flip UIView.transition(with: self.view, duration: 1.0, options: [.transitionFlipFromLeft], animations: nil, completion: { _ in // replace camera preview with new one self.view.layer.replaceSublayer(self.previewLayer!, with: newVideoLayer) self.previewLayer = newVideoLayer }) } func zoomSlider() { let slider: UISlider = UISlider() let sliderWidth: CGFloat = self.view.bounds.width * 0.75 let sliderHeight: CGFloat = 40 let sliderRect: CGRect = CGRect(x: (self.view.bounds.width - sliderWidth) / 2, y: self.view.bounds.height - 80, width: sliderWidth, height: sliderHeight) slider.frame = sliderRect slider.minimumValue = 0.0 slider.maximumValue = 1.0 slider.value = 0.0 slider.addTarget(self, action: #selector(self.onSliderChanged(sender:)), for: .valueChanged) self.view.addSubview(slider) } @objc func onSliderChanged(sender: UISlider) { do { try self.videoDevice?.lockForConfiguration() self.videoDevice?.ramp( toVideoZoomFactor: (self.videoDevice?.minAvailableVideoZoomFactor)! + CGFloat(sender.value) * ((self.videoDevice?.maxAvailableVideoZoomFactor)! - (self.videoDevice?.minAvailableVideoZoomFactor)!), withRate: 30.0) self.videoDevice?.unlockForConfiguration() } catch { print("Failed to change zoom.") } } func recordButton() { self.recordAcitnoButton = UIButton(frame: CGRect(x: 0, y: 0, width: 80, height: 80)) self.recordAcitnoButton.backgroundColor = .white self.recordAcitnoButton.tintColor = .red self.recordAcitnoButton.setImage(UIImage(systemName: "video.slash.fill"), for: .normal) self.recordAcitnoButton.layer.masksToBounds = true self.recordAcitnoButton.layer.cornerRadius = 30 self.recordAcitnoButton.layer.position = CGPoint(x: self.view.bounds.width / 2, y:self.view.bounds.height - 130) self.recordAcitnoButton.addTarget(self, action: #selector(self.onClickRecordButton(sender:)), for: .touchUpInside) self.view.addSubview(recordAcitnoButton) } @objc func onClickRecordButton(sender: UIButton) { if self.fileOutput.isRecording { // stop recording fileOutput.stopRecording() self.recordAcitnoButton.backgroundColor = .white self.recordAcitnoButton.tintColor = .red self.recordAcitnoButton.setImage(UIImage(systemName: "video.slash.fill"), for: .normal) } else { // start recording let tempDirectory: URL = URL(fileURLWithPath: NSTemporaryDirectory()) let fileURL: URL = tempDirectory.appendingPathComponent("mytemp1.mov") fileOutput.startRecording(to: fileURL, recordingDelegate: self) self.recordAcitnoButton.backgroundColor = .red self.recordAcitnoButton.tintColor = .white self.recordAcitnoButton.setImage(UIImage(systemName: "video.fill"), for: .normal) } } func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) { // show alert let alert: UIAlertController = UIAlertController(title: "Recorded!", message: outputFileURL.absoluteString, preferredStyle: .alert) let okAction: UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil) alert.addAction(okAction) self.present(alert, animated: true, completion: nil) } }
このコードを書く前から色々とグーグルで検索したり思考錯誤をし書いてみたのですが、結局はエラーが出てしまうことや自分の思いどうりにいく結果が出せていないため、皆様の知識をお貸しくださればとても幸いです。
あなたの回答
tips
プレビュー