首页 > 解决方案 > 视频文件有音频,但视频播放器看不到或播放音频

问题描述

我使用 AVAssetWriter、AVAssetWriterInput 等从 iPhone 的相机/麦克风创建了一个视频文件,当我在 iMovie、QuickTime 播放器和 Davinci Resolve 中播放生成的视频时,似乎没有音频。iMovie 的音频波形为空,尽管 QuickTime 检查器显示存在音轨。

但是,我使用 Ocenaudio 打开了相同的视频文件,它可以完全正常地读取和播放音频。所以我知道音频在某个地方。

我使用了广泛可用的代码来使用 AVAssetWriter,例如:

previewVideoWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: videoOutputSettings)
previewVideoWriterInput.expectsMediaDataInRealTime = true
previewAudioWriterInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: audioOutputSettings)
previewAudioWriterInput.expectsMediaDataInRealTime = true

if previewVideoWriter.canAdd(previewVideoWriterInput) == true { previewVideoWriter.add(previewVideoWriterInput) }
if previewVideoWriter.canAdd(previewAudioWriterInput) == true { previewVideoWriter.add(previewAudioWriterInput) }

主要区别在于我在 captureOutput() 函数中对视频数据使用 CIFilter。这是我的 captureOutout() 代码的简化版本:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    recordingQueue.async {
        autoreleasepool {
            if output == self.previewVideoOutput {
                let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
                let cameraImage = CIImage(cvPixelBuffer: pixelBuffer!)
                if self.currentFilter != nil { self.currentFilter.setValue(cameraImage, forKey: kCIInputImageKey) }
                let filteredImage = UIImage(ciImage: self.currentFilter != nil ? self.currentFilter.value(forKey: kCIOutputImageKey) as! CIImage : cameraImage)

                let timeStampie = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
                self.previewProgressTimeStamp = timeStampie
                if self.previewFirstFrameTimeStamp == CMTime.zero {
                    self.previewFirstFrameTimeStamp = self.previewProgressTimeStamp
                }
                self.previewProgressTimeStamp = CMTimeSubtract(self.previewProgressTimeStamp, self.previewFirstFrameTimeStamp)
                if self.previewVideoWriterInput.isReadyForMoreMediaData {
                    let appendSuccess = self.previewVideoAdapter.append(self.pixelBufferFromImage(filteredImage)!, withPresentationTime: self.previewProgressTimeStamp)
                }
            }
            else if output == self.previewAudioOutput {
                if self.previewAudioWriterInput.isReadyForMoreMediaData {
                    let appendSuccess = self.previewAudioWriterInput.append(sampleBuffer)
                }
            }
        }
    }
}

这是我在完成录制时使用的代码:

if previewVideoWriterInput != nil {
    previewVideoWriterInput.markAsFinished()
    previewAudioWriterInput.markAsFinished()
}
if previewVideoWriter != nil {
    previewVideoWriter.endSession(atSourceTime: previewProgressTimeStamp)
    previewVideoWriter.finishWriting { () -> Void in
        self.recordingCompletedHandler?()
    }
}

任何想法为什么视频播放器看不到正在写入视频文件的音频?我将如何解决这个问题?

编辑:

这是我用来按要求设置 AVCapture 输出的代码。

captureSession = AVCaptureSession()
captureSession.beginConfiguration()

captureSession.sessionPreset = .vga640x480
captureSession.usesApplicationAudioSession = true

if frontCameraInput != nil && captureSession.canAddInput(frontCameraInput) == true { captureSession.addInput(frontCameraInput) }
if let audioCaptureDeviceInput = AVCaptureDevice.default(for: .audio) { audioCaptureDevice = audioCaptureDeviceInput }
if audioCaptureDevice != nil {
    do {
        audioCaptureDeviceInput = try AVCaptureDeviceInput(device: audioCaptureDevice)
    } catch let error {
        print("\(error.localizedDescription)")
    }
}

if audioCaptureDeviceInput != nil && captureSession.canAddInput(audioCaptureDeviceInput) == true { captureSession.addInput(audioCaptureDeviceInput) }

previewVideoOutput.setSampleBufferDelegate(self, queue: recordingQueue)
previewAudioOutput.setSampleBufferDelegate(self, queue: recordingQueue)

if captureSession.canAddOutput(previewVideoOutput) { captureSession.addOutput(previewVideoOutput) }
if captureSession.canAddOutput(previewAudioOutput) { captureSession.addOutput(previewAudioOutput) }

captureSession.commitConfiguration()

标签: iosswiftaudiovideoavassetwriter

解决方案


推荐阅读