From bba4658dd34114fcc0e997dd35e8a5b53a014781 Mon Sep 17 00:00:00 2001 From: prlanzarin <4529051+prlanzarin@users.noreply.github.com> Date: Tue, 15 Aug 2023 22:03:09 -0300 Subject: [PATCH] fix(recording): remux bbb-webrtc-recorder and KMS files during archive Kurento may *rarely* generate WebM/MKV files with corrupt or absent SeekHead sectors. bbb-webrtc-recorder also doesn't generate SeekHead or even the Cues sectors by default. While those are are *optional* fields by spec, files need to be seekable for our recording processing scripts to work. This commit adds a remuxing step for Kurento and bbb-webrtc-recorder raw files that is executed during the archive phase. It should re-include any of the missing fields that make files seekable and restore the Cues sector in WebM files. --- .../core/scripts/archive/archive.rb | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/record-and-playback/core/scripts/archive/archive.rb b/record-and-playback/core/scripts/archive/archive.rb index 6f0283c38e..0074f1c64c 100755 --- a/record-and-playback/core/scripts/archive/archive.rb +++ b/record-and-playback/core/scripts/archive/archive.rb @@ -111,6 +111,37 @@ def delete_audio(meeting_id, audio_dir) end end +def remux_and_archive(source_dir, dest_dir) + files = Dir.glob("#{source_dir}/*") + + if files.empty? + BigBlueButton.logger.warn("No media files found in #{source_dir}") + return + end + + BigBlueButton.logger.info("Remuxing and archiving files at #{source_dir}") + FileUtils.mkdir_p(dest_dir) + + files .each do |file| + ext = File.extname(file) + next if ext.empty? + # These can potentially be webm (VP8/VP9), mp4 (H.264), or mkv (VP8/VP9/H.264) + output_basename = File.join(dest_dir, File.basename(file, ext)) + format = { + extension: ext.delete_prefix('.'), + parameters: [ + %w[-c copy], + ] + } + BigBlueButton::EDL.encode( + nil, + file, + format, + output_basename + ) + end +end + def archive_directory(source, dest) BigBlueButton.logger.info("Archiving contents of #{source}") FileUtils.mkdir_p(dest) @@ -207,14 +238,14 @@ archive_notes(meeting_id, notes_endpoint, notes_formats, raw_archive_dir) # Presentation files archive_directory("#{presentation_dir}/#{meeting_id}/#{meeting_id}", "#{target_dir}/presentation") # Kurento media -archive_directory("#{kurento_screenshare_dir}/#{meeting_id}", "#{target_dir}/deskshare") -archive_directory("#{kurento_video_dir}/#{meeting_id}", "#{target_dir}/video/#{meeting_id}") +remux_and_archive("#{kurento_screenshare_dir}/#{meeting_id}", "#{target_dir}/deskshare") +remux_and_archive("#{kurento_video_dir}/#{meeting_id}", "#{target_dir}/video/#{meeting_id}") # mediasoup media archive_directory("#{mediasoup_screenshare_dir}/#{meeting_id}", "#{target_dir}/deskshare") archive_directory("#{mediasoup_video_dir}/#{meeting_id}", "#{target_dir}/video/#{meeting_id}") # bbb-webrtc-recorder media -archive_directory("#{webrtc_recorder_screenshare_dir}/#{meeting_id}", "#{target_dir}/deskshare") -archive_directory("#{webrtc_recorder_video_dir}/#{meeting_id}", "#{target_dir}/video/#{meeting_id}") +remux_and_archive("#{webrtc_recorder_screenshare_dir}/#{meeting_id}", "#{target_dir}/deskshare") +remux_and_archive("#{webrtc_recorder_video_dir}/#{meeting_id}", "#{target_dir}/video/#{meeting_id}") # If this was the last (or only) segment in a recording, delete the original media files if break_timestamp.nil?