From 4392b0d462424341586753df1b1e11c13bbc7bdb Mon Sep 17 00:00:00 2001 From: germanocaumo Date: Wed, 7 Jul 2021 13:26:24 +0000 Subject: [PATCH] feat(recording): process published external videos Generate a external_videos.json file at the recordings with an array of played external videos url and timestamp. This file will be published along with the other presentation format files and can be used to display at the playback. --- .../recordandplayback/generators/events.rb | 44 +++++++++++++++++++ .../scripts/publish/presentation.rb | 34 ++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/record-and-playback/core/lib/recordandplayback/generators/events.rb b/record-and-playback/core/lib/recordandplayback/generators/events.rb index 8a27ed1dd0c1..cb01f2f32673 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/events.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/events.rb @@ -492,6 +492,23 @@ def self.get_record_status_events(events_xml) rec_events.sort_by {|a| a[:timestamp]} end + def self.get_external_video_events(events_xml) + BigBlueButton.logger.info "Getting external video events" + external_videos_events = [] + events_xml.xpath("//event[@eventname='StartExternalVideoRecordEvent']").each do |event| + s = { + :timestamp => event['timestamp'].to_i, + :external_video_url => event.at_xpath("externalVideoUrl").text + } + external_videos_events << s + end + events_xml.xpath("//event[@eventname='StopExternalVideoRecordEvent']").each do |event| + s = { :timestamp => event['timestamp'].to_i } + external_videos_events << s + end + external_videos_events.sort_by {|a| a[:timestamp]} + end + # Get events when the moderator wants the recording to start or stop def self.get_start_and_stop_rec_events(events_xml, allow_empty_events=false) BigBlueButton.logger.info "Getting start and stop rec button events" @@ -507,6 +524,17 @@ def self.get_start_and_stop_rec_events(events_xml, allow_empty_events=false) rec_events.sort_by {|a| a[:timestamp]} end + # Get events when the moderator wants the recording to start or stop + def self.get_start_and_stop_external_video_events(events_xml) + BigBlueButton.logger.info "Getting start and stop externalvideo events" + external_video_events = BigBlueButton::Events.get_external_video_events(events_xml) + if external_video_events.size.odd? + # user did not click to stop external video before ending meeting + external_video_events << { :timestamp => BigBlueButton::Events.last_event_timestamp(events_xml) } + end + external_video_events.sort_by {|a| a[:timestamp]} + end + # Match recording start and stop events def self.match_start_and_stop_rec_events(rec_events) BigBlueButton.logger.info ("Matching record events") @@ -522,6 +550,22 @@ def self.match_start_and_stop_rec_events(rec_events) matched_rec_events end + # Match external video start and stop events + def self.match_start_and_stop_external_video_events(external_video_events) + BigBlueButton.logger.info ("Matching external video events") + matched_external_video_events = [] + external_video_events.each_with_index do |evt,i| + if i.even? + matched_external_video_events << { + :start_timestamp => evt[:timestamp], + :stop_timestamp => external_video_events[i + 1][:timestamp], + :external_video_url => evt[:external_video_url], + } + end + end + matched_external_video_events + end + # Adjust the recoding start and stop events to trim them to a meeting # segment def self.trim_start_and_stop_rec_events(rec_events, start, stop) diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index 5e4f1b2822a3..e048a85ff205 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1202,6 +1202,38 @@ def processPollEvents(events, package_dir) end end +def processExternalVideoEvents(events, package_dir) + BigBlueButton.logger.info("Processing external video events") + + # Retrieve external video events + external_video_events = BigBlueButton::Events.match_start_and_stop_external_video_events( + BigBlueButton::Events.get_start_and_stop_external_video_events(@doc)) + + external_videos = [] + $rec_events.each do |re| + external_video_events.each do |event| + #BigBlueButton.logger.info("Processing rec event #{re} and external video event #{event}") + timestamp = (translateTimestamp(event[:start_timestamp]) / 1000).to_i + # do not add same external_video twice + if (external_videos.find {|ev| ev[:timestamp] == timestamp}.nil?) + if ((event[:start_timestamp] >= re[:start_timestamp] and event[:start_timestamp] <= re[:stop_timestamp]) || + (event[:start_timestamp] < re[:start_timestamp] and event[:stop_timestamp] >= re[:start_timestamp])) + external_videos << { + :timestamp => timestamp, + :external_video_url => event[:external_video_url] + } + end + end + end + end + + if not external_videos.empty? + File.open("#{package_dir}/external_videos.json", "w") do |f| + f.puts(external_videos.to_json) + end + end +end + $shapes_svg_filename = 'shapes.svg' $panzooms_xml_filename = 'panzooms.xml' $cursor_xml_filename = 'cursor.xml' @@ -1401,6 +1433,8 @@ def processPollEvents(events, package_dir) processPollEvents(@doc, package_dir) + processExternalVideoEvents(@doc, package_dir) + # Write slides.xml to file File.open("#{package_dir}/slides_new.xml", 'w') { |f| f.puts $slides_doc.to_xml }