AVAssetWriter从音频切换到视频会使第一帧变黑

时间:2017-05-18 08:25:13

标签: ios swift avcapturesession avassetwriter

我录制了音频和视频文件。用户可以仅从视频切换到音频,从音频切换到视频。 但是当我从音频切换到视频时,第一帧是黑色的。

切换

func switch_to_audio(){
    capture_session.beginConfiguration()
    capture_session.removeInput(video_input)
    capture_session.removeOutput(video_output)
    init_audio_writer(video_on: false)
    capture_session.commitConfiguration()
    start_new_record()
}

func init_audio_writer(video_on:Bool){
    if video_on{
        let video_settings=[
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 44100,
            AVEncoderBitRateKey:128000,
            AVNumberOfChannelsKey: NSNumber(value:1)] as [String : Any]
        audio_writer=AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: video_settings)
    }else{
        let audio_settings=[
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 44100,
            AVEncoderBitRateKey:128000,
            AVNumberOfChannelsKey: NSNumber(value:1)] as [String : Any]

        audio_writer=AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: audio_settings)
    }
}

func switch_to_video(){
    capture_session.beginConfiguration()
    capture_session.addInput(video_input)
    capture_session.addOutput(video_output)
    init_audio_writer(video_on:true)
    capture_session.commitConfiguration()
}

记录

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 && is_recording{
        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")
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好的,愚蠢的错误......

启动应用时,我会初始化我的AVCaptureSession,添加输入,输出等等。我只是在调用start_new_record时过早地调用commitConfiguration捕获会话。

至少我的代码可能对某些人有用。