Правильный способ остановить запись видео (finishWriting) с AVAssetWriter и без сбоев

Я записываю видео с AVAssetWriter, Пользователь может отправить видео, затем я позвоню finishWritingили отмените запись, тогда я позвоню cancelWriting,

Как я записываю:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!){
        guard !message_to_send else{
            return
        }
        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
        }
        guard let sb=sampleBuffer else{
            return
        }

        if w.status == .unknown /*&& start_recording_time==nil*/{
            if captureOutput==video_output{
                print("\nSTART RECORDING")
                w.startWriting()
                start_recording_time=CMSampleBufferGetPresentationTimeStamp(sb)
                w.startSession(atSourceTime: start_recording_time!)
            }else{
                return
            }
        }

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

        guard w.status == .writing else{
            print("not writing")
            return
        }

        if captureOutput==audio_output{
            if audio_writer.isReadyForMoreMediaData && video_written{
                audio_writer.append(sb)
            }else{
                print("audio writer not ready OR video not written yet")
            }
        }else if captureOutput==video_output{
            if video_writer.isReadyForMoreMediaData /*&& is_recording*/{
                video_writer.append(sb)   // << this line gets called after stop_record is called and causes a crash
                if !video_written{
                    print("added 1st video frame")
                    video_written=true
                }
                //print("write video")
            }else{
                print("video writer not ready")
            }
        }
    }
}

Как мне остановить запись:

func stop_record(){
        print("\nstop_record")
        guard is_recording else{
            print("not recording > return")
            return
        }

        is_recording=false
        cam_q.async{
            self.is_recording=false
        }

        print("file writer status", file_writer.status.rawValue)
        if file_writer.status.rawValue==1{
            self.video_writer?.markAsFinished()
            print("video finished")
            self.audio_writer?.markAsFinished()
            print("audio finished")
        }else{
            print("not writing")
        }

        if !self.message_to_send{
            print("cancel writing")
            self.file_writer.cancelWriting()
            return
        }

        file_writer.finishWriting(){
            print("finished writing")
            DispatchQueue.main.async{
                let st=self.file_writer.status
                if st == .failed{
                    print("status: failed")
                }else if st == .completed{
                    print("status: completed")
                }else if st == .cancelled{
                    print("status: cancelled")
                }else{
                    print("status: unknown")
                }

                if let e=self.file_writer.error{
                    print("stop record error:", e)
                }

                if self.message_to_send{
                    send_message()
                }
            }
        }
    }

Когда я звоню stop_recordиногда он падает. Даже если file_writer должен прекратить писать, и если я сделаю несколько проверок в didOutputSampleBufferэта строка называется:

video_writer.append (SB)

И я получаю:

stop_record

Статус записи файла 1

видео закончено

аудио закончено

libC++abi.dylib: завершается с необработанным исключением типа NSException

Я попробовал тот же код без звонка markAsFinished но это также дает сбой (чаще я бы сказал).

Мне интересно, если это проблема потока (так как stop_record а также didOutputSampleBuffer методы не вызываются в одном потоке). Во всяком случае, я не знаю, что я делаю не так. Если бы кто-то мог помочь мне в этом, я был бы очень признателен.

0 ответов

Другие вопросы по тегам