Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev2.7 heuristic thumbnails #217

Open
wants to merge 11 commits into
base: test27_showDif_heuristicthumb
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
require 'rubygems'
require 'nokogiri'

class Range
def intersection(other)
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
new_min = self.cover?(other.min) ? other.min : other.cover?(min) ? min : nil
new_max = self.cover?(other.max) ? other.max : other.cover?(max) ? max : nil
new_min && new_max ? new_min..new_max : nil
end
alias_method :&, :intersection
end

module BigBlueButton
class Presentation
# Get the presentations.
Expand Down Expand Up @@ -110,35 +120,81 @@ def self.get_text_from_slide(textfiles_dir, slide_num)
end

# Get from events the presentation that will be used for preview.
def self.get_presentation_for_preview(process_dir)
def self.get_presentation_for_preview(process_dir, heuristic_thumbnails, number_thumbnails)
events_xml = "#{process_dir}/events.xml"
BigBlueButton.logger.info("Task: Getting from events the presentation to be used for preview")
presentation = {}
presentation = []
doc = Nokogiri::XML(File.open(events_xml))
presentation_filenames = {}
doc.xpath("//event[@eventname='ConversionCompletedEvent']").each do |conversion_event|
presentation_filenames[conversion_event.xpath("presentationName").text] = conversion_event.xpath("originalFilename").text
end
doc.xpath("//event[@eventname='SharePresentationEvent']").each do |presentation_event|
# Extract presentation data from events
presentation_id = presentation_event.xpath("presentationName").text
presentation_filename = presentation_filenames[presentation_id]
# Set textfile directory
textfiles_dir = "#{process_dir}/presentation/#{presentation_id}/textfiles"
# Set presentation hashmap to be returned
unless presentation_filename == "default.pdf"
presentation[:id] = presentation_id
presentation[:filename] = presentation_filename
presentation[:slides] = {}
for i in 1..3
if File.file?("#{textfiles_dir}/slide-#{i}.txt")
text_from_slide = self.get_text_from_slide(textfiles_dir, i)
presentation[:slides][i] = { :alt => text_from_slide == nil ? '' : text_from_slide }
sesseion_end = doc.xpath('//event[last()]')[0].attributes['timestamp'].value.to_i
slide_events = doc.xpath("//event[@eventname='GotoSlideEvent']")
slide_time = {}
current_slide = nil
current_ts = nil
slide_events.each_with_index do |e, i|
if i > 0
time_shown = current_ts..e.attributes["timestamp"].value.to_i
if slide_time[current_slide]
slide_time[current_slide].push(time_shown)
else
slide_time[current_slide] = [time_shown]
end
end
current_slide = e.at('id').text
current_ts = e.attributes["timestamp"].value.to_i
end
if current_ts
time_shown = current_ts..sesseion_end
if slide_time[current_slide]
slide_time[current_slide].push(time_shown)
else
slide_time[current_slide] = [time_shown]
end
end
#BigBlueButton.logger.info("slide_time: #{slide_time}")

record_time = []
record_events = doc.xpath("//event[@eventname='RecordStatusEvent']")
record_events.each_with_index do |e, i|
if i.odd?
record_time.push(record_events[i-1].attributes["timestamp"].value.to_i..e.attributes["timestamp"].value.to_i)
end
end
if record_events.size.odd?
record_time.push(record_events[-1].attributes["timestamp"].value.to_i..sesseion_end)
end
#BigBlueButton.logger.info("record_time: #{record_time}")

# Intersect with the recorded periods
slide_time_recorded = {}
slide_time.each do |id, periods|
periods.each do |period|
record_time.each do |record|
intersected_period = period.intersection(record)
if slide_time_recorded[id]
slide_time_recorded[id].push(intersected_period)
else
slide_time_recorded[id] = [intersected_period]
end
end
# Break because something else than default.pdf was found
break
end
slide_time_recorded[id].compact! if slide_time_recorded[id]
end
#BigBlueButton.logger.info("slide_time_recorded: #{slide_time_recorded}")

slide_time_sort = slide_time_recorded.map{|k, v| [k, v.inject(0){|s, n| s += n.size}] }.sort_by{|_, v| -v} if heuristic_thumbnails
BigBlueButton.logger.info("Thumbnail candidates: #{slide_time_sort}")
slide_time_sort.each do |st|
break if presentation.size >= number_thumbnails
p, s = st[0].split('/')
presentation_filename = presentation_filenames[p]
next if presentation_filename == "default.pdf"
textfiles_dir = "#{process_dir}/presentation/#{p}/textfiles"
text_from_slide = self.get_text_from_slide(textfiles_dir, s) if File.file?("#{textfiles_dir}/slide-#{s}.txt")
presentation.push({ :id => p, :filename => presentation_filename, :i => s, :alt => text_from_slide == nil ? '' : text_from_slide, :duration => st[1] })
end
presentation
end
Expand Down
4 changes: 4 additions & 0 deletions record-and-playback/presentation/scripts/presentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ deskshare_output_framerate: 5
audio_offset: 0
include_deskshare: true

# Generate thumbnails from most viewed slides
heuristic_thumbnails: false
number_thumbnails: 3

# For PRODUCTION
publish_dir: /var/bigbluebutton/published/presentation
video_formats:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1388,7 +1388,7 @@ def copy_media_files_helper(media, media_files, package_dir)
## Remove empty playback
metadata.search('recording/playback').each(&:remove)
## Add the actual playback
presentation = BigBlueButton::Presentation.get_presentation_for_preview(@process_dir.to_s)
presentation = BigBlueButton::Presentation.get_presentation_for_preview(@process_dir.to_s, @presentation_props['heuristic_thumbnails'], @presentation_props['number_thumbnails'])
Nokogiri::XML::Builder.with(metadata.at('recording')) do |xml|
xml.playback do
xml.format('presentation')
Expand All @@ -1399,10 +1399,10 @@ def copy_media_files_helper(media, media_files, package_dir)
xml.extensions do
xml.preview do
xml.images do
presentation[:slides].each do |key, val|
attributes = { width: '176', height: '136', alt: val[:alt]&.to_s || '' }
presentation.each do |p|
attributes = { width: '176', height: '136', alt: p[:alt]&.to_s || '', duration: p[:duration]/1000 }
xml.image(attributes) do
xml.text("#{playback_protocol}://#{playback_host}/presentation/#{@meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-#{key}.png")
xml.text("#{playback_protocol}://#{playback_host}/presentation/#{@meeting_id}/presentation/#{p[:id]}/thumbnails/thumb-#{p[:i]}.png")
end
end
end
Expand Down