Save AVCaptureVideoDataOutput to movie file using AVAssetWriter in Swift

后端 未结 1 936
南旧
南旧 2020-12-24 09:32

I\'ve been looking all over the web and can\'t seem to find a tutorial or help in what I need.

Using AVFoundation and the Dlib library I\'ve created an

相关标签:
1条回答
  • 2020-12-24 09:50

    I was able to find out how to use AVAssetWriter. In case anyone else needs help the code I used is as follows:

    func setUpWriter() {
    
        do {
            outputFileLocation = videoFileLocation()
            videoWriter = try AVAssetWriter(outputURL: outputFileLocation!, fileType: AVFileType.mov)
    
            // add video input
            videoWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: [
                AVVideoCodecKey : AVVideoCodecType.h264,
                AVVideoWidthKey : 720,
                AVVideoHeightKey : 1280,
                AVVideoCompressionPropertiesKey : [
                    AVVideoAverageBitRateKey : 2300000,
                    ],
                ])
    
            videoWriterInput.expectsMediaDataInRealTime = true
    
            if videoWriter.canAdd(videoWriterInput) {
                videoWriter.add(videoWriterInput)
                print("video input added")
            } else {
                print("no input added")
            }
    
            // add audio input
            audioWriterInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: nil)
    
            audioWriterInput.expectsMediaDataInRealTime = true
    
            if videoWriter.canAdd(audioWriterInput!) {
                videoWriter.add(audioWriterInput!)
                print("audio input added")
            }
    
    
            videoWriter.startWriting()
        } catch let error {
            debugPrint(error.localizedDescription)
        }
    
    
    }
    
    func canWrite() -> Bool {
        return isRecording && videoWriter != nil && videoWriter?.status == .writing
    }
    
    
     //video file location method
    func videoFileLocation() -> URL {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
        let videoOutputUrl = URL(fileURLWithPath: documentsPath.appendingPathComponent("videoFile")).appendingPathExtension("mov")
        do {
        if FileManager.default.fileExists(atPath: videoOutputUrl.path) {
            try FileManager.default.removeItem(at: videoOutputUrl)
            print("file removed")
        }
        } catch {
            print(error)
        }
    
        return videoOutputUrl
    }
    
    // MARK: AVCaptureVideoDataOutputSampleBufferDelegate
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    
        let writable = canWrite()
    
        if writable,
            sessionAtSourceTime == nil {
            // start writing
            sessionAtSourceTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
            videoWriter.startSession(atSourceTime: sessionAtSourceTime!)
            //print("Writing")
        }
    
        if output == videoDataOutput {
            connection.videoOrientation = .portrait
    
            if connection.isVideoMirroringSupported {
                connection.isVideoMirrored = true
            }
        }
    
        if writable,
            output == videoDataOutput,
            (videoWriterInput.isReadyForMoreMediaData) {
            // write video buffer
            videoWriterInput.append(sampleBuffer)
            //print("video buffering")
        } else if writable,
            output == audioDataOutput,
            (audioWriterInput.isReadyForMoreMediaData) {
            // write audio buffer
            audioWriterInput?.append(sampleBuffer)
            //print("audio buffering")
        }
    
    }
    
    // MARK: Start recording
    func start() {
        guard !isRecording else { return }
        isRecording = true
        sessionAtSourceTime = nil
        setUpWriter()
        print(isRecording)
        print(videoWriter)
        if videoWriter.status == .writing {
            print("status writing")
        } else if videoWriter.status == .failed {
            print("status failed")
        } else if videoWriter.status == .cancelled {
            print("status cancelled")
        } else if videoWriter.status == .unknown {
            print("status unknown")
        } else {
            print("status completed")
        }
    
    }
    
    // MARK: Stop recording
    func stop() {
        guard isRecording else { return }
        isRecording = false
        videoWriterInput.markAsFinished()
        print("marked as finished")
        videoWriter.finishWriting { [weak self] in
            self?.sessionAtSourceTime = nil
        }
        //print("finished writing \(self.outputFileLocation)")
        captureSession.stopRunning()
        performSegue(withIdentifier: "videoPreview", sender: nil)
    }
    

    I now have another problem where this solution doesn't work when I'm using AVCaptureMetadataOutput, AVCaptureVideoDataOutput and AVCaptureAudioDataOutput together. The app crashes when I add AVCaptureAudioDataOutput.

    0 讨论(0)
提交回复
热议问题