Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
...
  • 3 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
Showing with 194 additions and 331 deletions.
  1. +179 −72 lib/timelapse_generator.rb
  2. +0 −257 prepare_for_movie.rb
  3. +15 −2 start_timelapse1.rb
View
251 lib/timelapse_generator.rb
@@ -21,6 +21,8 @@ def initialize
@log = Logger.new(STDOUT)
@log.level = Logger::INFO
+
+ reset_frames
end
attr_accessor :log
@@ -46,6 +48,11 @@ def only_enabled_for_timelapse!
@log.info "There are only #{@defs.size} enabled for timelapse"
end
+ def only_this!(_desc)
+ @defs = @defs.select { |u| u[:desc] == _desc }
+ @log.info "There are only #{@defs.size} enabled for timelapse"
+ end
+
# importer can search thought many paths for downloaded images
def add_to_import_paths(_new_path = '.')
@import_paths << _new_path
@@ -167,7 +174,8 @@ def calculate_extreme_times
# sort coords according to time of dawn
def desc_sorted_by_coords
- @desc_sorted = @defs.sort { |a, b| a[:coord][:lon] <=> b[:coord][:lon] }.collect { |a| a[:desc] }
+ _sorted = @defs.sort { |a, b| a[:coord][:lon] <=> b[:coord][:lon] } rescue @defs
+ @desc_sorted = _sorted.collect { |a| a[:desc] }
end
# get webcam definition by desc
@@ -183,11 +191,12 @@ def sunrise_and_sunset_by_desc_and_time(_desc, _time)
return [_sunrise, _sunset]
end
+ # get images from one webcam within time range
def select_images_by_desc_and_times(_desc, _time_from, _time_to)
@stored_webcams[_desc].select { |w| w[:time] >= _time_from and w[:time] <= _time_to }.sort { |a, b| a[:time] <=> b[:time] }
end
- # i'm too lazy to document it :]
+ # get the '_limit' of images nearest to '_time'
def select_images_most_accurate(_desc, _time, _time_range = 10*60, _limit = 100)
_images = select_images_by_desc_and_times(_desc, _time - _time_range, _time + _time_range)
_images = _images.sort { |a, b| (a[:time] - _time).abs <=> (b[:time] - _time).abs }
@@ -196,78 +205,18 @@ def select_images_most_accurate(_desc, _time, _time_range = 10*60, _limit = 100)
return _images
end
- # create timelapse using all images, only during the day
- def generate_day_timelapse
- # movie frames
+ # clear frame tables
+ def reset_frames
@frames = Array.new
-
- finished = false
- day = 0
- while not finished do
- # loop by time/days, from first_time to
-
- @stored_webcams.keys.each do |_desc|
- # loop by provider
- _time = @min_time + day * 24*3600
- _sunrise, _sunset = sunrise_and_sunset_by_desc_and_time(_desc, _time)
- @log.debug "Adding photos from #{_desc} from #{_sunrise} to #{_sunset}"
-
- webcams_partial = select_images_by_desc_and_times(_desc, _sunrise, _sunset)
- @log.debug "...added #{webcams_partial.size} images"
- @frames += webcams_partial
- end
-
- # next day
- day += 1
-
- # end condition
- if @min_time + day * 24*3600 > @max_time
- finished = true
- end
- @log.info "Added #{@frames.size} images"
- end
- end
-
- # create timelapse using couple of images during noon
- def generate_noon_everyday_timelapse(limit = 1)
- # movie frames
- @frames = Array.new
-
- finished = false
- day = 0
- while not finished do
- # loop by time/days, from first_time to
-
- @stored_webcams.keys.each do |_desc|
- # loop by provider
- _time = @min_time + day * 24*3600
- _sunrise, _sunset = sunrise_and_sunset_by_desc_and_time(_desc, _time)
- _noon = Time.at( (_sunrise.to_i + _sunset.to_i) / 2 )
- @log.debug "Adding some photos from #{_desc} from noon #{_noon}"
-
- webcams_partial = select_images_most_accurate(_desc, _noon, 3600, limit)
- @log.debug "...added #{webcams_partial.size} images"
- @frames += webcams_partial
- end
-
- # next day
- day += 1
-
- # end condition
- if @min_time + day * 24*3600 > @max_time
- finished = true
- end
- end
-
- @log.info "Added #{@frames.size} images"
end
- def create_images_list(absolute_path = true)
+ ## -- rendering output
+ def create_images_list(output_name = nil, absolute_path = true)
# create symlinks
Dir.mkdir 'tmp' if not File.exist?('tmp')
Dir.mkdir 'tmp/timelapse' if not File.exist?('tmp/timelapse')
- @timelapse_output_name = Time.now.to_i.to_s
+ @timelapse_output_name = output_name || Time.now.to_i.to_s
@timelapse_output_file = File.absolute_path("tmp/timelapse/video_#{@timelapse_output_name}.avi")
@timelapse_images_list_file = File.absolute_path("tmp/timelapse/list_#{@timelapse_output_name}.txt")
@@ -280,7 +229,7 @@ def create_images_list(absolute_path = true)
f.close
end
- def create_render_command(_options = { }, preset = nil)
+ def render_command(_options = { }, preset = nil)
if preset.to_s == 'HD'
_options = _options.merge(
{
@@ -318,11 +267,169 @@ def create_render_command(_options = { }, preset = nil)
fps_string = "-mf fps=#{fps} "
options_string = "-ovc xvid -xvidencopts noqpel:nogmc:trellis:nocartoon:nochroma_me:chroma_opt:lumi_mask:max_iquant=7:max_pquant=7:max_bquant=7:bitrate=#{bitrate}:threads=120 "
output_string = "-o \"#{output}\" -oac copy "
- command_youtube = "mencoder #{input_string}#{fps_string}#{scale_crop_string}#{options_string}#{output_string}"
+ command = "mencoder #{input_string}#{fps_string}#{scale_crop_string}#{options_string}#{output_string}"
+
+ return command
+ end
+
+ def create_render_command(_options = { }, preset = nil)
+ command = render_command(_options, preset)
+ save_command_to_file(command, @timelapse_output_name)
+ end
+
+ def save_command_to_file(command, name)
+ _script_file = File.absolute_path("tmp/timelapse/video_#{name}.sh")
+ File.open(_script_file, 'w') do |f|
+ f.puts command
+ end
+ end
+
+ ## -- end of rendering output code
- @timelapse_script_file = File.absolute_path("tmp/timelapse/video_#{@timelapse_output_name}.sh")
- File.open(@timelapse_script_file, 'w') do |f|
- f.puts command_youtube
+ # add images for timelapse using all images, all webcams, only during the day, day by day
+ def add_images_daily_timelapse
+ add_images_for_webcams_during_day(@stored_webcams.keys)
+ end
+
+ # add images for timelapse using selected webcams, only during the day, day by day
+ def add_images_for_webcams_during_day(_descs)
+ _descs = [_descs] unless _descs.kind_of?(Array)
+
+ finished = false
+ day = 0
+ while not finished do
+ # loop by time/days, from first_time to
+
+ _descs.keys.each do |_desc|
+ # loop by provider
+ _time = @min_time + day * 24*3600
+ _sunrise, _sunset = sunrise_and_sunset_by_desc_and_time(_desc, _time)
+ @log.debug "Adding photos from #{_desc} from #{_sunrise} to #{_sunset}"
+
+ webcams_partial = select_images_by_desc_and_times(_desc, _sunrise, _sunset)
+ @log.debug "...added #{webcams_partial.size} images"
+ @frames += webcams_partial
+ end
+
+ # next day
+ day += 1
+
+ # end condition
+ if @min_time + day * 24*3600 > @max_time
+ finished = true
+ end
+ @log.info "Added #{@frames.size} images"
+ end
+ end
+
+ # add images for timelapse using a few (ex. 1) images during noon
+ def add_images_noon_everyday_for_webcam(_desc, limit = 1)
+ finished = false
+ day = 0
+ while not finished do
+ # loop by time/days, from first_time to
+
+ # loop by provider
+ _time = @min_time + day * 24*3600
+ _sunrise, _sunset = sunrise_and_sunset_by_desc_and_time(_desc, _time)
+ _noon = Time.at((_sunrise.to_i + _sunset.to_i) / 2)
+ @log.debug "Adding some photos from #{_desc} from noon #{_noon}"
+
+ webcams_partial = select_images_most_accurate(_desc, _noon, 3600, limit)
+ @log.debug "...added #{webcams_partial.size} images"
+ @frames += webcams_partial
+
+ # next day
+ day += 1
+
+ # end condition
+ if @min_time + day * 24*3600 > @max_time
+ finished = true
+ end
end
+
+ @log.info "Added #{@frames.size} images"
+ end
+
+ # add all images from one webcam, even night shots
+ def add_images_for_webcam_whole_day(_desc)
+ @frames += select_images_by_desc_and_times(_desc, @min_time, @max_time)
+ @log.info "Added #{@frames.size} images"
+ end
+
+
+ ## -- one method to generate timelapse
+ # create everything for making separated timelapse per webcam
+ #
+ # types:
+ # * :separated - if true every webcam has separated output video file
+ # * :day - if true only images during the day
+ # * :all - if true ignore :use_in_timelapse flag in definition
+ # * :descs - Array of webcam desc used only
+ def generate_separated_movies(_options = { })
+ load_config
+
+ only_with_coords! if _options[:only_with_coords!] or _options[:day]
+ only_enabled_for_timelapse! if _options[:only_enabled_for_timelapse] or not _options[:all]
+
+ _separated = _options[:separated]
+ _only_day = _options[:day] || _options[:only_day]
+
+ # only selected webcams
+ if _options[:descs]
+ new_defs = Array.new
+ _options[:descs].each do |_desc|
+ new_defs << def_by_desc(_desc)
+ end
+ @defs = new_defs
+ end
+
+ # adding optional paths
+ _options[:paths] ||= Array.new
+ _options[:paths].each do |path|
+ add_to_import_paths(path)
+ end
+
+ _options[:mencoder_options] ||= Hash.new
+ _options[:name] ||= Time.now.strftime('%m_%d__%H_%m')
+ _name = _options[:name]
+
+ # import images and initial processing
+ import_all_files
+ calculate_extreme_times
+ desc_sorted_by_coords
+
+ @command = ""
+
+ if _separated
+ @defs.each do |webcam|
+ reset_frames
+ _desc = webcam[:desc]
+
+ if _only_day
+ add_images_for_webcams_during_day(_desc)
+ else
+ add_images_for_webcam_whole_day(_desc)
+ end
+
+ # create list, command, ...
+ create_images_list("#{_name}_#{_desc}")
+ @command += render_command(_options[:mencoder_options])
+ @command += "\n\n"
+ end
+ else
+ # in one file
+ if _only_day
+ add_images_daily_timelapse
+ create_images_list(_name)
+ @command += render_command(_options[:mencoder_options])
+ @command += "\n\n"
+ else
+ # how it should be implemented?
+ raise NotImplementedError
+ end
+ end
+
+ save_command_to_file(@command, _name)
end
end
View
257 prepare_for_movie.rb
@@ -1,257 +0,0 @@
-require 'rubygems'
-require 'solareventcalculator'
-require 'yaml'
-
-class KickAssAwesomeTimelapseGenerator
-
- #PATH = '/home/olek/pliki.big/webcam_downloader/pulling/webcam_downloader'
- PATH = '.'
-
- #TYPE = :civil # normal day
- #TYPE = :official # shortest day
- TYPE = :nautical # day is longer than :civil
- #TYPE = :astronomical # longest day
-
- def initialize
- urls = YAML::load(File.open('defs.yml'))
- @defs = Array.new
- urls.each do |u|
- @defs += u[:array]
- end
- end
-
- attr_reader :defs
-
- def import_files
- # select only defs with coords
- us_tmp = defs.select { |u| not u[:coord].nil? and not u[:coord][:lat].nil? and not u[:coord][:lon].nil? }
- us = us_tmp.select { |u| u[:use_in_timelapse] == true }
- @us = us
- puts "Only #{us_tmp.size} has coords from #{defs.size}, and only #{us.size} are enabled"
-
- puts "Importing webcams"
- @stored_webcams = Hash.new
-
- us.each do |u|
- desc = u[:desc]
- # here will be Array of webcams
- @stored_webcams[desc] = Array.new
- not_stored_count = 0
-
- Dir[File.join(PATH, "pix", desc, "*.jpg")].each do |f|
- h = Hash.new
- h[:filename] = f
- # supa-dupa-lazy
- h[:time] = Time.at(f[/\d{4,20}/].to_i)
-
- # normally only day images are interesting
- # unless there is :night => true in defs
-
- if u[:night] or is_day_now?(u[:coord][:lat], u[:coord][:lon], h[:time])
- @stored_webcams[desc] << h
- else
- not_stored_count += 1
- end
-
- end
-
- # must be sorted
- @stored_webcams[desc] = @stored_webcams[desc].sort { |a, b| a[:time] <=> b[:time] }
- puts "Imported for #{desc} #{@stored_webcams[desc].size}, not imported #{not_stored_count}"
- end
- end
-
- def sunrise(lat, lon, time)
- #puts "#{lat} #{lon} #{time}"
- calc = SolarEventCalculator.new(time, BigDecimal.new(lat.to_s), BigDecimal.new(lon.to_s))
- stime = case TYPE
- when :civil then
- calc.compute_utc_civil_sunrise
- when :official then
- calc.compute_utc_official_sunrise
- when :nautical then
- calc.compute_utc_nautical_sunrise
- when :astronomical then
- calc.compute_utc_astronomical_sunrise
- else
- calc.compute_utc_civil_sunrise
- end
- return stime.localtime if not stime.nil?
- return Time.mktime(time.year, time.month, time.day, 0)
- end
-
- def sunset(lat, lon, time)
- calc = SolarEventCalculator.new(time, BigDecimal.new(lat.to_s), BigDecimal.new(lon.to_s))
- stime = case TYPE
- when :civil then
- calc.compute_utc_civil_sunset
- when :official then
- calc.compute_utc_official_sunset
- when :nautical then
- calc.compute_utc_nautical_sunset
- when :astronomical then
- calc.compute_utc_astronomical_sunset
- else
- calc.compute_utc_civil_sunset
- end
- return stime.localtime if not stime.nil?
- return Time.mktime(time.year, time.month, time.day, 0) + 24*3600
- end
-
- def is_day_now?(lat, lon, time)
- _sunrise = sunrise(lat, lon, time)
- _sunset = sunset(lat, lon, time)
- # puts " #{_sunrise} - #{_sunset}"
- return (time >= _sunrise and time <= _sunset)
- end
-
- def save
- d = Hash.new
- d["@stored_webcams"] = @stored_webcams
-
- File.open('timelapse.yml', 'w') do |f|
- f.puts d.to_yaml
- end
- puts "Saved"
- end
-
- def reload
- d = YAML::load(File.open('timelapse.yml'))
- @stored_webcams = d["@stored_webcams"]
- puts "Loaded"
- end
-
- def generate_timelapse_script
- first_time = nil
- last_time = nil
- puts "Getting first and last time"
-
- keys_ordered = @us.sort { |a, b| a[:coord][:lon] <=> b[:coord][:lon] }.collect { |a| a[:desc] }
-
- #@stored_webcams.keys.each do |k|
- keys_ordered.each do |k|
- sw = @stored_webcams[k]
- if sw.size > 0
- # some providers has no images
- first_time = sw.first[:time] if first_time.nil?
- first_time = sw.first[:time] if first_time > sw.first[:time]
-
- last_time = sw.last[:time] if last_time.nil?
- last_time = sw.last[:time] if last_time < sw.last[:time]
- end
- end
- puts "First time at #{first_time}"
- puts "Last time at #{last_time}"
-
- # movie frames
- @frames = Array.new
-
- # TODO maybe something to sort by providers/webcams?
-
- finished = false
- day = 0
- while not finished do
- # loop by time/days, from first_time to
-
- @stored_webcams.keys.each do |k|
- # loop by provider
-
- # calculate sunrise and sunset
- webcam_def = @defs.select { |d| d[:desc] == k }.first
- lat = webcam_def[:coord][:lat]
- lon = webcam_def[:coord][:lon]
- time = first_time + day * 24*3600
- _sunrise = sunrise(lat, lon, time)
- _sunset = sunset(lat, lon, time)
-
- puts "Adding photos from #{k} from #{_sunrise} to #{_sunset}"
- webcams_partial = @stored_webcams[k].select { |w| w[:time] >= _sunrise and w[:time] <= _sunset }
- webcams_partial = webcams_partial.sort { |a, b| a[:time] <=> b[:time] }
- puts "...added #{webcams_partial.size} images"
-
- @frames += webcams_partial.collect { |w| w[:filename] }
- end
-
- # next day
- day += 1
-
- # end condition
- if first_time + day * 24*3600 > last_time
- finished = true
- end
- end
-
- puts "Finished with #{@frames.size} images"
- File.open('timelapse_frames.yml', 'w') do |f|
- f.puts @frames.to_yaml
- end
- puts "Frames saved"
-
- # create symlinks
- Dir.mkdir 'tmp' if not File.exist?('tmp')
- Dir.mkdir 'tmp/timelapse' if not File.exist?('tmp/timelapse')
-
- f = File.new('tmp/timelapse/list.txt', 'w')
- @frames.each_with_index do |t, i|
- f.puts t
- end
- f.close
-
- # HD
- width = 1280
- height = 720
- ratio = width.to_f / height.to_f
- # ratio - "16:9"
- bitrate = 6000
- fps = 25
-
- # -1 true aspect ratio
- # -2 fit into movie size, aspect not maintained
- aspect_ratio_type = -2
-
- scale_crop_string = "-aspect #{ratio} -vf scale=#{aspect_ratio_type}:#{height},crop=#{width}:#{height} -sws 9 "
- input_string = "\"mf://@tmp/timelapse/list.txt\" "
- fps_string = "-mf fps=#{fps} "
- youtube_string = "-ovc xvid -xvidencopts noqpel:nogmc:trellis:nocartoon:nochroma_me:chroma_opt:lumi_mask:max_iquant=7:max_pquant=7:max_bquant=7:bitrate=#{bitrate}:threads=120 "
- youtube_output_string = "-o video_yhd.avi -oac copy "
-
- command_youtube = "mencoder #{input_string}#{fps_string}#{scale_crop_string}#{youtube_string}#{youtube_output_string}"
- puts "# youtube hd", command_youtube
-
- # 480p
- width = 854
- height = 480
- ratio = width.to_f / height.to_f
- bitrate = 4000
-
- scale_crop_string = "-aspect #{ratio} -vf scale=#{aspect_ratio_type}:#{height},crop=#{width}:#{height} -sws 9 "
- youtube_string = "-ovc xvid -xvidencopts noqpel:nogmc:trellis:nocartoon:nochroma_me:chroma_opt:lumi_mask:max_iquant=7:max_pquant=7:max_bquant=7:bitrate=#{bitrate}:threads=120 "
- youtube_output_string = "-o video_1.avi -oac copy "
-
- command_youtube = "mencoder #{input_string}#{fps_string}#{scale_crop_string}#{youtube_string}#{youtube_output_string}"
- puts "# youtube 480p", command_youtube
-
-
- #command_vimeo = "mencoder \"mf://@tmp/timelapse/list.txt\" -mf fps=25:w=#{width}:h=#{height} -profile x264-vimeo -o video_vimeo.avi"
- #puts "# youube 480p", command_youtube
-
- #command_youtube = "mencoder \"mf://@tmp/timelapse/list.txt\" -mf fps=25:w=#{width}:h=#{height} -sws 9 -vf scale=#{width}:#{height} -aspect #{ratio} -ovc xvid -xvidencopts noqpel:nogmc:trellis:nocartoon:nochroma_me:chroma_opt:lumi_mask:max_iquant=7:max_pquant=7:max_bquant=7:bitrate=#{bitrate}:threads=120 -o video_1.avi -oac copy"
- #puts "# vimeo", command_vimeo
-
- end
-
-end
-
-# take some time, load images info and check sunrise/sunset
-process = true
-
-t = KickAssAwesomeTimelapseGenerator.new
-if process
- t.import_files
- t.save
-else
- t.reload
-end
-
-t.generate_timelapse_script
-
View
17 start_timelapse1.rb
@@ -1,5 +1,18 @@
load 'lib/timelapse_generator.rb'
t = KickAssAwesomeTimelapseGenerator.new
+t.generate_separated_movies(
+ {
+ all: true,
+ descs: ['stawy'],
+ separated: true,
+ day: false,
+ paths: [
+ '/home/olek/pliki.big/webcam_downloader/pulling/webcam_downloader/pix_part_1',
+ '/home/olek/pliki.big/webcam_downloader/pulling/webcam_downloader/pix'
+ ]
+ })
+
+return 0
#t.log.level = Logger::DEBUG
t.load_config
t.only_with_coords!
@@ -11,8 +24,8 @@
t.desc_sorted_by_coords
# many timelapse types
-#t.generate_day_timelapse
-t.generate_noon_everyday_timelapse
+#t.add_images_daily_timelapse
+t.add_images_noon_everyday_for_webcam('stawy')
t.create_images_list
t.create_render_command

No commit comments for this range

Something went wrong with that request. Please try again.