Record and upload to Firebase - Swift

Hey All,

I have been trying and searching but i just can’t find anything or figure out how to record and upload a video from Swift to firebase storage. I have Firebase all set up and am able to authenticate users and store there information on Firebase.

— CameraViewController & CameraView. I am able to start/stop recording, but after this it just saves it to my phone and thats it. This is were im having issues, i’m not sure how to send it to firebase storage/cloud from the recording view area and show a success on the UI view after upload.

Please Help!!

Camera Record View Code:

import SwiftUI

struct RecordCameraView: View {

@State var isRecording = false
var cameraView = CameraView()

var body: some View {
VStack {
ZStack {
cameraView
VStack {
HStack {
Spacer()
Button {
cameraView.switchCamera()
} label: {
Image(systemName: “arrow.triangle.2.circlepath.camera”)
.padding()
.foregroundColor(.white)
}
}
Spacer()
HStack {
Spacer()
Button {
if !isRecording {
cameraView.startRecording()
} else {
cameraView.stopRecording()
}
isRecording.toggle()
} label: {
Image(systemName: “record.circle”)
.font(.system(size: 60))
.foregroundColor(isRecording ? Color.red : Color.white)
}
Spacer()
}
}
}
}
}
}

struct RecordCameraView_Previews: PreviewProvider {
static var previews: some View {
RecordCameraView()
}
}

CameraViewController:

import UIKit
import AVFoundation
import SwiftUI
import PhotosUI

class CameraViewController: UIViewController {

let captureSession = AVCaptureSession()
var previewLayer: AVCaptureVideoPreviewLayer!
var activeInput: AVCaptureDeviceInput!
let movieOutput = AVCaptureMovieFileOutput()

var tempURL: URL? {
let directory = NSTemporaryDirectory() as NSString
if directory != “” {
let path = directory.appendingPathComponent(“video2.mov”)
return URL(fileURLWithPath: path)
}
return nil
}

override func viewDidLoad() {
super.viewDidLoad()

setupSession()
setupPreview()
startSession()

}

override func viewWillDisappear(_ animated: Bool) {
stopSession()
}

func setupSession() {
captureSession.beginConfiguration()
guard let camera = AVCaptureDevice.default(for: .video) else {
return
}
guard let mic = AVCaptureDevice.default(for: .audio) else {
return
}
do {
let videoInput = try AVCaptureDeviceInput(device: camera)
let audioInput = try AVCaptureDeviceInput(device: mic)
for input in [videoInput, audioInput] {
if captureSession.canAddInput(input) {
captureSession.addInput(input)
}
}
activeInput = videoInput
} catch {
print(“Error setting device input: (error)”)
return
}
captureSession.addOutput(movieOutput)
captureSession.commitConfiguration()
}

func camera(for position: AVCaptureDevice.Position) → AVCaptureDevice? {
let discovery = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .unspecified)
let devices = discovery.devices.filter {
$0.position == position
}
return devices.first
}

public func switchCamera() {
let position: AVCaptureDevice.Position = (activeInput.device.position == .back) ? .front : .back
guard let device = camera(for: position) else {
return
}
captureSession.beginConfiguration()
captureSession.removeInput(activeInput)
do {
activeInput = try AVCaptureDeviceInput(device: device)
} catch {
print(“error: (error.localizedDescription)”)
return
}
captureSession.addInput(activeInput)
captureSession.commitConfiguration()
}

func setupPreview() {
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = view.bounds
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
view.layer.addSublayer(previewLayer)
}

func startSession() {
if !captureSession.isRunning {
DispatchQueue.global(qos: .default).async { [weak self] in
self?.captureSession.startRunning()
}
}
}

func stopSession() {
if captureSession.isRunning {
DispatchQueue.global(qos: .default).async() { [weak self] in
self?.captureSession.stopRunning()
}
}
}

public func captureMovie() {
guard let connection = movieOutput.connection(with: .video) else {
return
}
if connection.isVideoStabilizationSupported {
connection.preferredVideoStabilizationMode = .auto
}
let device = activeInput.device
if device.isSmoothAutoFocusSupported {
do {
try device.lockForConfiguration()
device.isSmoothAutoFocusEnabled = true
device.unlockForConfiguration()
} catch {
print(“error: (error)”)
}
}
guard let outUrl = tempURL else { return }
movieOutput.startRecording(to: outUrl, recordingDelegate: self)
}

public func stopRecording() {
if movieOutput.isRecording {
movieOutput.stopRecording()
}
}

}

extension CameraViewController: AVCaptureFileOutputRecordingDelegate {
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
if let error = error {
print(“error: (error.localizedDescription)”)
} else {
PHPhotoLibrary.requestAuthorization { status in
if status == .authorized {
PHPhotoLibrary.shared().performChanges {
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputFileURL)
} completionHandler: { (success, error) in

      }
    }
  }
}

}
}