AV-自定義相機(jī) 錄制視頻

1.懶加載各對象

lazy var captureSession : AVCaptureSession = {

? ? ? ? let captureSessionTmp = AVCaptureSession()

? ? ? ? if captureSessionTmp.canSetSessionPreset(AVCaptureSession.Preset.photo) {

? ? ? ? ? ? captureSessionTmp.sessionPreset = AVCaptureSession.Preset.photo

? ? ? ? }

? ? ? ? return captureSessionTmp

? ? }()

? ? // MARK: previewLayer

? ? lazy var captureVideoPreviewLayer : AVCaptureVideoPreviewLayer = {

? ? ? ? let captureVideoPreviewLayerTmp = AVCaptureVideoPreviewLayer.init(session: captureSession)

? ? ? ? captureVideoPreviewLayerTmp.videoGravity = AVLayerVideoGravity.resizeAspectFill

? ? ? ? return captureVideoPreviewLayerTmp

? ? }()

? ? // MARK: camera

? ? lazy var captureDeviceCamera : AVCaptureDevice? = {

? ? ? ? return captureDeviceInputCamera?.device

? ? }()

? ? // MARK: video input

? ? lazy var captureDeviceInputCamera : AVCaptureDeviceInput? = {

? ? ? ? let captureDevice = getCameraDeviceWithPosition(position: AVCaptureDevice.Position.back)

? ? ? ? do {

? ? ? ? ? ? let captureDeviceInputCameraTmp = try AVCaptureDeviceInput.init(device: captureDevice!)

? ? ? ? ? ? return captureDeviceInputCameraTmp

? ? ? ? }catch {

? ? ? ? }

? ? ? ? return nil

? ? }()

? ? // MARK: audio input

? ? lazy var captureDeviceInputAudio : AVCaptureDeviceInput? = {

? ? ? ? let captureDevice = AVCaptureDevice.devices(for: AVMediaType.audio).first

? ? ? ? do {

? ? ? ? ? ? let captureDeviceInputAudioTmp = try AVCaptureDeviceInput.init(device: captureDevice!)

? ? ? ? ? ? return captureDeviceInputAudioTmp

? ? ? ? }catch {

? ? ? ? }

? ? ? ? return nil

? ? }()

? ? // MARK: movie output

? ? lazy var captureMovieFileOutput : AVCaptureMovieFileOutput = {

? ? ? ? let captureMovieFileOutputTmp = AVCaptureMovieFileOutput()

? ? ? ? let captureConnection = captureMovieFileOutputTmp.connection(with: AVMediaType.video)

? ? ? ? //? ? ? ? if (captureConnection?.isVideoStabilizationSupported)! {

? ? ? ? captureConnection?.preferredVideoStabilizationMode = AVCaptureVideoStabilizationMode.auto

? ? ? ? //? ? ? ? }

? ? ? ? captureConnection?.videoOrientation = (captureVideoPreviewLayer.connection?.videoOrientation)!

? ? ? ? return captureMovieFileOutputTmp

? ? }()

2.初始化相機(jī)

if captureSession.canAddInput(captureDeviceInputCamera!) {

? ? ? ? ? ? ? ? captureSession.addInput(captureDeviceInputCamera!)

}

if captureSession.canAddInput(captureDeviceInputAudio!) {

? ? ? ? ? ? captureSession.addInput(captureDeviceInputAudio!)

}

if captureSession.canAddOutput(captureMovieFileOutput) {

? ? ? ? ? ? captureSession.addOutput(captureMovieFileOutput)

}

3.運(yùn)行session

captureSession.startRunning()

4.開始錄制視頻

if captureSession.canSetSessionPreset(AVCaptureSession.Preset.high) {

? ? ? ? ? ? captureSession.sessionPreset = AVCaptureSession.Preset.high

?}

?let videoUrl = URL.init(fileURLWithPath: MTVideoFileManager.shared.videoFilePath())

?captureMovieFileOutput.startRecording(to: videoUrl, recordingDelegate: self)

5.停止錄制視頻

captureMovieFileOutput.stopRecording()

6.停止session

captureSession.stopRunning()

7.合成視頻,并保存

func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

? ? ? ? let asset = AVAsset.init(url: outputFileURL)

? ? ? ? let composition = AVMutableComposition()

? ? ? ? let videoTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)

? ? ? ? let videoAssetTrack = asset.tracks(withMediaType: AVMediaType.video).first

? ? ? ? do {

? ? ? ? ? ? try videoTrack?.insertTimeRange(CMTimeRange.init(start: kCMTimeZero, duration: (videoAssetTrack?.timeRange.duration)!), of: videoAssetTrack!, at: kCMTimeZero)

? ? ? ? ? ? let layerInstruction = AVMutableVideoCompositionLayerInstruction.init(assetTrack: videoTrack!)

? ? ? ? ? ? let totalDuration = CMTimeAdd(kCMTimeZero, (videoAssetTrack?.timeRange.duration)!)

? ? ? ? ? ? let t1 = CGAffineTransform.init(translationX: -1*(videoAssetTrack?.naturalSize.width)!/2, y: -1*(videoAssetTrack?.naturalSize.height)!/2)

? ? ? ? ? ? layerInstruction.setTransform(t1, at: kCMTimeZero)

? ? ? ? ? ? var renderSize = CGSize(width: 0, height: 0)

? ? ? ? ? ? renderSize.width = max(renderSize.width, (videoAssetTrack?.naturalSize.height)!)

? ? ? ? ? ? renderSize.height = max(renderSize.height, (videoAssetTrack?.naturalSize.width)!)

? ? ? ? ? ? let renderW = min(renderSize.width, renderSize.height)


? ? ? ? ? ? let instruction = AVMutableVideoCompositionInstruction()

? ? ? ? ? ? instruction.timeRange = CMTimeRange.init(start: kCMTimeZero, duration: totalDuration)

? ? ? ? ? ? instruction.layerInstructions = [layerInstruction]

? ? ? ? ? ? let mainComposition = AVMutableVideoComposition()

? ? ? ? ? ? mainComposition.instructions = [instruction]

? ? ? ? ? ? mainComposition.frameDuration = CMTimeMake(1, 30)

? ? ? ? ? ? mainComposition.renderSize = CGSize(width: renderW, height: renderW)


? ? ? ? ? ? let exporter = AVAssetExportSession.init(asset: composition, presetName: AVAssetExportPresetMediumQuality)

? ? ? ? ? ? exporter?.videoComposition = mainComposition

? ? ? ? ? ? exporter?.outputURL = outputFileURL

? ? ? ? ? ? exporter?.shouldOptimizeForNetworkUse = true

? ? ? ? ? ? exporter?.outputFileType = AVFileType.mov

? ? ? ? ? ? exporter?.exportAsynchronously {

? ? ? ? ? ? ? ? DispatchQueue.main.async {

? ? ? ? ? ? ? ? ? ? let lib = ALAssetsLibrary()

? ? ? ? ? ? ? ? ? ? lib.writeVideoAtPath(toSavedPhotosAlbum: outputFileURL, completionBlock: { (url, error) in

? ? ? ? ? ? ? ? ? ? ? ? if (error != nil) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? print(error)

? ? ? ? ? ? ? ? ? ? ? ? ? ? self.delegate?.recordFinished(error: error as! NSError, url: nil)

? ? ? ? ? ? ? ? ? ? ? ? }else if (url != nil) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? print(url)

? ? ? ? ? ? ? ? ? ? ? ? ? ? MTVideoFileManager.shared.clearFileWithUrl(url: outputFileURL)

? ? ? ? ? ? ? ? ? ? ? ? ? ? self.delegate?.recordFinished(error: nil, url: outputFileURL)

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? } catch {

? ? ? ? ? ? print(error)

? ? ? ? }

? ? }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容