Swift IOS使用AVFoundation录制视频和音频

时间:2016-03-05 04:38:06

标签: ios swift avfoundation

我可以通过以下问题成功抓取录制的视频 here

基本上

  1. 继承自AVCaptureFileOutputRecordingDelegate原型
  2. 循环使用可用设备
  3. 使用相机创建会话
  4. 开始录制
  5. 停止录制
  6. 通过实施上述原型方法获取录制视频
  7. 但该文件没有附带音频。

    根据this问题,我必须分别录制音频并使用上述类合并视频和音频

    但我不知道如何同时实现视频和音频录制。

    for device in devices {
                // Make sure this particular device supports video
                if (device.hasMediaType(AVMediaTypeVideo)) {
                    // Finally check the position and confirm we've got the back camera
                    if(device.position == AVCaptureDevicePosition.Back) {
                        captureDevice = device as? AVCaptureDevice
                        if captureDevice != nil {
                            print("Capture device found")
    
                            beginSession()
                        }
                    }
                }
            }
    

    在此循环中,只有可用的设备类型是.Front和.Back

5 个答案:

答案 0 :(得分:3)

找到答案,这个答案与this代码

一致

可以通过

完成
  1. 声明另一个捕获设备变量
  2. 循环设备并初始化摄像头和音频捕获设备变量
  3. 将音频输入添加到会话
  4. <强>码

    var captureDevice : AVCaptureDevice?
    var captureAudio :AVCaptureDevice?
    

    循环浏览设备并初始化捕获设备

    var captureDeviceVideoFound: Bool = false
    var captureDeviceAudioFound:Bool = false
    
    // Loop through all the capture devices on this phone
    for device in devices {
    // Make sure this particular device supports video
        if (device.hasMediaType(AVMediaTypeVideo)) {
    // Finally check the position and confirm we've got the front camera
            if(device.position == AVCaptureDevicePosition.Front) {
    
                captureDevice = device as? AVCaptureDevice //initialize video
                if captureDevice != nil {
                    print("Capture device found")
                    captureDeviceVideoFound = true; 
                }
            }
        }
        if(device.hasMediaType(AVMediaTypeAudio)){
            print("Capture device audio init")
            captureAudio = device as? AVCaptureDevice //initialize audio
            captureDeviceAudioFound = true
        }
    }
    if(captureDeviceAudioFound && captureDeviceVideoFound){
        beginSession() 
    }
    

    内部会话

    try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
    try captureSession.addInput(AVCaptureDeviceInput(device: captureAudio))
    

    这将输出带有音频的视频文件。无需合并音频或做任何事情。

    此苹果文档helps

答案 1 :(得分:1)

遵循@Mumu 的回答,但它对我不起作用,因为调用了仅返回视频设备的 AVCaptureDevice.DiscoverySession.init。

这是我的适用于 iOS 14、Swift 5 的版本:

var captureSession: AVCaptureSession? = nil
var camera: AVCaptureDevice? = nil
var microphone: AVCaptureDevice? = nil
var videoOutput: AVCaptureFileOutput? = nil
var previewLayer: AVCaptureVideoPreviewLayer? = nil

func findDevices() {
    camera = nil
    microphone = nil

    //Search for video media type and we need back camera only
    let session = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInWideAngleCamera],
            mediaType: AVMediaType.video, position: AVCaptureDevice.Position.back)
    var devices = (session.devices.compactMap{$0})
    //Search for microphone
    let asession = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInMicrophone],
            mediaType: AVMediaType.audio, position: AVCaptureDevice.Position.unspecified)
    //Combine all devices into one list
    devices.append(contentsOf: asession.devices.compactMap{$0})
    for device in devices {
        if device.position == .back {
            do {
                try device.lockForConfiguration()
                device.focusMode = .continuousAutoFocus
                device.flashMode = .off
                device.whiteBalanceMode = .continuousAutoWhiteBalance
                device.unlockForConfiguration()
                camera = device
            } catch {
            }
        }
        if device.hasMediaType(.audio) {
            microphone = device
        }
    }
}

func initVideoRecorder()->Bool {
    captureSession = AVCaptureSession()
    guard let captureSession = captureSession else {return false}

    captureSession.sessionPreset = .hd4K3840x2160
    findDevices()

    guard let camera = camera else { return false}
    do {
        let cameraInput = try AVCaptureDeviceInput(device: camera)
        captureSession.addInput(cameraInput)
    } catch {
        self.camera = nil
        return false
    }

    if let audio = microphone {
        do {
            let audioInput = try AVCaptureDeviceInput(device: audio)
            captureSession.addInput(audioInput)
        } catch {
        }
    }

    videoOutput = AVCaptureMovieFileOutput()
    if captureSession.canAddOutput(videoOutput!) {
        captureSession.addOutput(videoOutput!)
        captureSession.startRunning()
        videoOutput?.connection(with: .video)?.videoOrientation = .landscapeRight
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer?.videoGravity = .resizeAspect
        previewLayer?.connection?.videoOrientation = .landscapeRight
        return true
    }

    return false
}

func startRecording()->Bool {
    guard let captureSession = captureSession, captureSession.isRunning else {return false}
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let fileUrl = paths[0].appendingPathComponent(getVideoName())
    try? FileManager.default.removeItem(at: fileUrl)
    videoOutput?.startRecording(to: fileUrl, recordingDelegate: self)
    return true
}

答案 2 :(得分:0)

我也有这个问题,但是当我分组添加视频输入和声音输入后,音频工作。这是我添加输入的代码。

 if (cameraSession.canAddInput(deviceInput) == true && cameraSession.canAddInput(audioDeviceInput) == true) {//detects if devices can be added
            cameraSession.addInput(deviceInput)//adds video
            cameraSession.addInput(audioDeviceInput)//adds audio
        }

此外,我发现你必须先输入视频,否则就不会有音频。我最初在两个if语句中使用它们,但我发现将它们放在一个可以将视频和音频记录在一起。希望这会有所帮助。

答案 3 :(得分:0)

以下是使用AVFoundation框架记录带音频的视频的方法。这些步骤是:

1。准备会议:

        self.captureSession = AVCaptureSession()

2。准备可用的视频和音频设备:

        let session = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInWideAngleCamera, .builtInMicrophone], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)

        let cameras = (session.devices.compactMap{$0})

        for camera in cameras {
            if camera.position == .front {
                self.frontCamera = camera
            }
            if camera.position == .back {
                self.rearCamera = camera

                try camera.lockForConfiguration()
                camera.focusMode = .continuousAutoFocus
                camera.unlockForConfiguration()
            }
        }

        // Add audio device
        self.audioDevice = AVCaptureDevice.default(for: AVMediaType.audio)

3。准备会话输入:

        guard let captureSession = self.captureSession else {
            throw CameraControllerError.captureSessionIsMissing
        }

        if let rearCamera = self.rearCamera {
            self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera)
            if captureSession.canAddInput(self.rearCameraInput!) {
                captureSession.addInput(self.rearCameraInput!)
                self.currentCameraPosition = .rear
            } else {
                throw CameraControllerError.inputsAreInvalid
            }
        }

        else if let frontCamera = self.frontCamera {
            self.frontCameraInput = try AVCaptureDeviceInput(device: frontCamera)
            if captureSession.canAddInput(self.frontCameraInput!) {
                captureSession.addInput(self.frontCameraInput!)
                self.currentCameraPosition = .front
            } else {
                throw CameraControllerError.inputsAreInvalid
            }
        }

        else {
            throw CameraControllerError.noCamerasAvailable
        }

        // Add audio input
        if let audioDevice = self.audioDevice {
            self.audioInput = try AVCaptureDeviceInput(device: audioDevice)
            if captureSession.canAddInput(self.audioInput!) {
                captureSession.addInput(self.audioInput!)
            } else {
                throw CameraControllerError.inputsAreInvalid
            }
        }

4。准备输出:

        self.videoOutput = AVCaptureMovieFileOutput()
        if captureSession.canAddOutput(self.videoOutput!) {
            captureSession.addOutput(self.videoOutput!)
        }
        captureSession.startRunning()

5。开始录制:

       func recordVideo(completion: @escaping (URL?, Error?)-> Void) {
            guard let captureSession = self.captureSession, captureSession.isRunning else {
                 completion(nil, CameraControllerError.captureSessionIsMissing)
                 return
            }

            let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            let fileUrl = paths[0].appendingPathComponent("output.mp4")
            try? FileManager.default.removeItem(at: fileUrl)
            videoOutput!.startRecording(to: fileUrl, recordingDelegate: self)
            self.videoRecordCompletionBlock = completion
        }

6。停止录制:

        func stopRecording(completion: @escaping (Error?)->Void) {
             guard let captureSession = self.captureSession, captureSession.isRunning else {
                  completion(CameraControllerError.captureSessionIsMissing)
                  return
             }
            self.videoOutput?.stopRecording()
        }

7。实施委托:

    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
         if error == nil {
           //do something
         } else {
            //do something
         }
    }

我从这里想到了:https://www.appcoda.com/avfoundation-swift-guide/

这是完整的项目https://github.com/rubaiyat6370/iOS-Tutorial/

答案 4 :(得分:-1)

录制带音频的视频

//Get Video Device

if let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] {
    for device in devices {
        if device.hasMediaType(AVMediaTypeVideo) {
            if device .position == AVCaptureDevicePosition.back{
                videoCaptureDevice = device
            }
        }
    }
    if videoCaptureDevice != nil {
        do {
            // Add Video Input
            try self.captureSession.addInput(AVCaptureDeviceInput(device: videoCaptureDevice))
            // Get Audio Device
            let audioInput = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio)
            //Add Audio Input
            try self.captureSession.addInput(AVCaptureDeviceInput(device: audioInput))
            self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
            previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
            previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.portrait
            self.videoView.layer.addSublayer(self.previewLayer)
            //Add File Output
            self.captureSession.addOutput(self.movieOutput)
            captureSession.startRunning()
        }catch {
            print(error)
        }

有关详细信息,请参阅此链接:

https://medium.com/@santhosh3386/ios-avcapturesession-record-video-with-audio-23c8f8c9a8f8