ios - 使用 AVAssetWriter 录制视频 : first frames are black

标签 ios swift avassetwriter avassetwriterinput

我正在用 AVAssetWriter 录制视频(用户也可以只切换到音频)。我在应用程序启动时开始录制。 但是第一帧是黑色(或非常暗)。当我从音频切换到视频时也会发生这种情况。 感觉 AVAssetWriter 和/或 AVAssetWriterInput 还没有准备好记录。我怎样才能避免这种情况?

我不知道这是否有用,但我也使用 GLKView 来显示视频。

func start_new_record(){
    do{
        try self.file_writer=AVAssetWriter(url: self.file_url!, fileType: AVFileTypeMPEG4)
        if video_on{
            if file_writer.canAdd(video_writer){
                file_writer.add(video_writer)
            }
        }
        if file_writer.canAdd(audio_writer){
            file_writer.add(audio_writer)
        }
    }catch let e as NSError{
        print(e)
    }
}

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!){
    guard is_recording else{
        return
    }

    guard CMSampleBufferDataIsReady(sampleBuffer) else{
        print("data not ready")
        return
    }

    guard let w=file_writer else{
        print("video writer nil")
        return
    }

    if w.status == .unknown && start_recording_time==nil{
        if (video_on && captureOutput==video_output) || (!video_on && captureOutput==audio_output){
            print("START RECORDING")
            file_writer?.startWriting()
            start_recording_time=CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
            file_writer?.startSession(atSourceTime: start_recording_time!)
        }else{
            return
        }
    }

    if w.status == .failed{
        print("failed /", w.error ?? "")
        return
    }

    if captureOutput==audio_output{
        if audio_writer.isReadyForMoreMediaData{
            if !video_on || (video_on && video_written){
                audio_writer.append(sampleBuffer)
                //print("write audio")
            }
        }else{
            print("audio writer not ready")
        }
    }else if video_output != nil && captureOutput==video_output{
        if video_writer.isReadyForMoreMediaData{
            video_writer.append(sampleBuffer)
            if !video_written{
                print("added 1st video frame")
                video_written=true
            }
        }else{
            print("video writer not ready")
        }
    }
}

最佳答案

SWIFT 4

解决方案 #1:

我通过在启动应用程序时尽快调用 file_writer?.startWriting() 解决了这个问题。然后,当您想要开始录制时,执行 file_writer?.startSession(atSourceTime:...)

当您完成录制并调用 finishRecording 时,当您收到表明完成的回调时,再次设置新的写入 session 。

解决方案#2:

我通过在调用 AVAssetWriter.startSession 时将开始时间增加半秒来解决这个问题,如下所示:

start_recording_time = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
let startingTimeDelay = CMTimeMakeWithSeconds(0.5, 1000000000)
let startTimeToUse = CMTimeAdd(start_recording_time!, startingTimeDelay)

file_writer?.startSession(atSourceTime: startTimeToUse)

解决方案 #3:

这里更好的解决方案是记录您收到并决定写入的第一帧的时间戳,然后以此开始您的 session 。那么你不需要任何延迟:

//Initialization, elsewhere:

var is_session_started = false
var videoStartingTimestamp = CMTime.invalid

// In code where you receive frames that you plan to write:

if (!is_session_started) {
    // Start writing at the timestamp of our earliest sample
    videoStartingTimestamp = currentTimestamp
    print ("First video sample received: Starting avAssetWriter Session: \(videoStartingTimestamp)")
    avAssetWriter?.startSession(atSourceTime: videoStartingTimestamp)

    is_session_started = true
}

// add the current frame
pixelBufferAdapter?.append(myPixelBuffer, withPresentationTime: currentTimestamp)

关于ios - 使用 AVAssetWriter 录制视频 : first frames are black,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44135223/

相关文章:

ios - 通过 AVAssetWriter 捕获视频并保存

ios - 在 iOS 今天小部件中从 url 加载图像时出现内存错误

android - 有人可以解释 Flutter 中的 Navigator 类和 Scaffold 类吗?

php - 播放视频 - 服务器配置不正确 - 12939

ios - 如何在 UIPageViewController 中以全尺寸显示图像?

ios - 查看 tableView

ios - 共享表 - 排除 UIActivityType 中未作为类型属性提供的选项

ios - 子项目找不到通过 Pods 安装的 Swift 模块

ios - 将视频的音频转换为 AAC

ios - 使用 AVAsset 的多图像到视频需要高内存