Правильный способ остановить запись видео (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
методы не вызываются в одном потоке). Во всяком случае, я не знаю, что я делаю не так. Если бы кто-то мог помочь мне в этом, я был бы очень признателен.