236 lines
8.7 KiB
Swift
236 lines
8.7 KiB
Swift
//
|
||
// PlayContoller9.swift
|
||
// tdvideo
|
||
//
|
||
// Created by mac on 2024/2/21.
|
||
//
|
||
|
||
/*
|
||
拍摄空间视频
|
||
*/
|
||
import UIKit
|
||
import AVFoundation
|
||
import Photos
|
||
import AVKit
|
||
import VideoToolbox
|
||
|
||
class PlayContoller9: UIViewController, AVCaptureFileOutputRecordingDelegate {
|
||
|
||
//AVCaptureSession --- 单摄像头
|
||
var session = AVCaptureMultiCamSession()//多摄像头
|
||
var wideAngleCameraDeviceInput: AVCaptureDeviceInput?//广角摄像头 .builtInWideAngleCamera
|
||
var ultraWideCameraDeviceInput: AVCaptureDeviceInput?//超广角 .builtInUltraWideCamera
|
||
|
||
|
||
var wideAngleCameraVideoPreviewLayer: AVCaptureVideoPreviewLayer?//广角摄像头
|
||
var ultraWideCameraVideoPreviewLayer: AVCaptureVideoPreviewLayer?//超广角
|
||
|
||
var wideAngleCameraMovieOutput: AVCaptureMovieFileOutput?
|
||
var ultraWideCameraMovieOutput: AVCaptureMovieFileOutput?
|
||
|
||
|
||
|
||
var isRecording = false
|
||
|
||
|
||
var startRecordingButton: UIButton?
|
||
|
||
var leftEyeVideoURL:URL?
|
||
var rightEyeVideoURL:URL?
|
||
var outputVideoURL: URL?
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
view.backgroundColor = .white
|
||
|
||
outputVideoURL = URL.documentsDirectory.appendingPathComponent("output.MOV")
|
||
|
||
configureSession()
|
||
setupUI()
|
||
}
|
||
|
||
private func configureSession() {
|
||
session.beginConfiguration()
|
||
defer {
|
||
session.commitConfiguration()
|
||
}
|
||
|
||
// 配置后置摄像头 .builtInWideAngleCamera 广角摄像头(默认设备 --- 主摄,28mm左右焦段) .back 后置摄像头
|
||
guard let backCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
|
||
print("Could not find the back camera")
|
||
return
|
||
}
|
||
|
||
do {
|
||
wideAngleCameraDeviceInput = try AVCaptureDeviceInput(device: backCamera)
|
||
|
||
guard let wideAngleCameraDeviceInput = wideAngleCameraDeviceInput,
|
||
session.canAddInput(wideAngleCameraDeviceInput) else {
|
||
print("Could not add back camera input")
|
||
return
|
||
}
|
||
session.addInput(wideAngleCameraDeviceInput)
|
||
} catch {
|
||
print("Could not create back camera device input: \(error)")
|
||
return
|
||
}
|
||
|
||
// .builtInUltraWideCamera 超广角(默认设备的0.5x,只能使用AVCaptureDeviceDiscoverySession获取) .back 后置摄像头
|
||
guard let frontCamera = AVCaptureDevice.default(.builtInUltraWideCamera, for: .video, position: .back) else {
|
||
print("Could not find the front camera")
|
||
return
|
||
}
|
||
|
||
do {
|
||
ultraWideCameraDeviceInput = try AVCaptureDeviceInput(device: frontCamera)
|
||
|
||
guard let ultraWideCameraDeviceInput = ultraWideCameraDeviceInput,
|
||
session.canAddInput(ultraWideCameraDeviceInput) else {
|
||
print("Could not add front camera input")
|
||
return
|
||
}
|
||
session.addInput(ultraWideCameraDeviceInput)
|
||
} catch {
|
||
print("Could not create front camera device input: \(error)")
|
||
return
|
||
}
|
||
|
||
// 配置音频输入设备
|
||
guard let audioDevice = AVCaptureDevice.default(for: .audio) else {
|
||
print("Could not find audio device")
|
||
return
|
||
}
|
||
|
||
do {
|
||
let audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)
|
||
|
||
guard session.canAddInput(audioDeviceInput) else {
|
||
print("Could not add audio input")
|
||
return
|
||
}
|
||
|
||
session.addInput(audioDeviceInput)
|
||
} catch {
|
||
print("Could not create audio device input: \(error)")
|
||
return
|
||
}
|
||
|
||
// 配置后置摄像头输出
|
||
wideAngleCameraMovieOutput = AVCaptureMovieFileOutput()
|
||
guard let wideAngleCameraMovieOutput = wideAngleCameraMovieOutput,
|
||
session.canAddOutput(wideAngleCameraMovieOutput) else {
|
||
print("Could not add the back camera movie output")
|
||
return
|
||
}
|
||
session.addOutput(wideAngleCameraMovieOutput)
|
||
|
||
// 配置前置摄像头输出
|
||
ultraWideCameraMovieOutput = AVCaptureMovieFileOutput()
|
||
guard let ultraWideCameraMovieOutput = ultraWideCameraMovieOutput,
|
||
session.canAddOutput(ultraWideCameraMovieOutput) else {
|
||
print("Could not add the front camera movie output")
|
||
return
|
||
}
|
||
session.addOutput(ultraWideCameraMovieOutput)
|
||
|
||
// 配置预览图层
|
||
wideAngleCameraVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
|
||
wideAngleCameraVideoPreviewLayer?.frame = CGRect(x: 0, y: 0, width: view.frame.size.width / 2, height: view.frame.size.height / 2)
|
||
if let wideAngleCameraVideoPreviewLayer = wideAngleCameraVideoPreviewLayer {
|
||
view.layer.addSublayer(wideAngleCameraVideoPreviewLayer)
|
||
}
|
||
|
||
ultraWideCameraVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
|
||
ultraWideCameraVideoPreviewLayer?.frame = CGRect(x: view.frame.size.width / 2, y: 0, width: view.frame.size.width / 2, height: view.frame.size.height / 2)
|
||
if let ultraWideCameraVideoPreviewLayer = ultraWideCameraVideoPreviewLayer {
|
||
view.layer.addSublayer(ultraWideCameraVideoPreviewLayer)
|
||
}
|
||
|
||
DispatchQueue.global().async {
|
||
self.session.startRunning()
|
||
}
|
||
}
|
||
|
||
private func setupUI() {
|
||
startRecordingButton = UIButton(type: .system)
|
||
startRecordingButton?.setTitle("Start Recording", for: .normal)
|
||
startRecordingButton?.setTitleColor(UIColor.brown, for: UIControl.State.normal)
|
||
startRecordingButton?.addTarget(self, action: #selector(toggleRecording(_:)), for: .touchUpInside)
|
||
startRecordingButton?.frame = CGRect(x: 0, y: view.frame.size.height - 250, width: view.frame.size.width, height: 50)
|
||
view.addSubview(startRecordingButton!)
|
||
}
|
||
|
||
@objc private func toggleRecording(_ sender: UIButton) {
|
||
if isRecording {
|
||
stopRecording()
|
||
} else {
|
||
startRecording()
|
||
}
|
||
}
|
||
|
||
private func startRecording() {
|
||
guard let wideAngleCameraMovieOutput = wideAngleCameraMovieOutput,
|
||
let ultraWideCameraMovieOutput = ultraWideCameraMovieOutput else {
|
||
print("Movie output not configured")
|
||
return
|
||
}
|
||
|
||
let time = Date().timeIntervalSince1970
|
||
let name1 = "back" + String(time) + ".mov"
|
||
let name2 = "front" + String(time) + ".mov"
|
||
let backCameraOutputURL = URL.documentsDirectory.appending(path:name1)
|
||
let frontCameraOutputURL = URL.documentsDirectory.appending(path:name2)
|
||
|
||
wideAngleCameraMovieOutput.startRecording(to: backCameraOutputURL, recordingDelegate: self)
|
||
ultraWideCameraMovieOutput.startRecording(to: frontCameraOutputURL, recordingDelegate: self)
|
||
|
||
isRecording = true
|
||
startRecordingButton?.setTitle("Stop Recording", for: .normal)
|
||
}
|
||
|
||
private func stopRecording() {
|
||
guard let wideAngleCameraMovieOutput = wideAngleCameraMovieOutput,
|
||
let ultraWideCameraMovieOutput = ultraWideCameraMovieOutput else {
|
||
print("Movie output not configured")
|
||
return
|
||
}
|
||
|
||
wideAngleCameraMovieOutput.stopRecording()
|
||
ultraWideCameraMovieOutput.stopRecording()
|
||
|
||
isRecording = false
|
||
startRecordingButton?.setTitle("Start Recording", for: .normal)
|
||
}
|
||
|
||
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
|
||
if let error = error {
|
||
print("Video recording finished with error: \(error.localizedDescription)")
|
||
} else {
|
||
if output == wideAngleCameraMovieOutput {
|
||
print("Back camera video recorded: \(outputFileURL)")
|
||
leftEyeVideoURL = outputFileURL
|
||
} else if output == ultraWideCameraMovieOutput {
|
||
print("Front camera video recorded: \(outputFileURL)")
|
||
rightEyeVideoURL = outputFileURL
|
||
}
|
||
createSpVideo()
|
||
}
|
||
}
|
||
|
||
func createSpVideo(){
|
||
|
||
if(rightEyeVideoURL != nil && leftEyeVideoURL != nil){
|
||
let spatialVideoWriter = SpatialVideoWriter()
|
||
Task {
|
||
spatialVideoWriter.writeSpatialVideo(leftEyeVideoURL: leftEyeVideoURL!, rightEyeVideoURL: rightEyeVideoURL!, outputVideoURL: outputVideoURL!) { success, error in
|
||
if success {
|
||
print("空间视频生成成功")
|
||
} else if let error = error {
|
||
print("生成空间视频失败:\(error.localizedDescription)")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|