class Lolcommits::AnimatedGif

Public Instance Methods

create(video_path:, output_path:) click to toggle source
# File lib/lolcommits/animated_gif.rb, line 5
def create(video_path:, output_path:)
  unless File.exist?(video_path)
    debug "**warning** unable to create animated gif, no video at #{video_path}"
    return
  end

  debug "creating animated gif at #{output_path}"
  system_call "ffmpeg -nostats -v quiet -i \"#{video_path}\" \"#{frames_dir}/%09d.png\" > #{null_string}"

  # use fps to set delay and number of frames to skip (for lower filesized gifs)
  fps   = video_fps(video_path)
  skip  = frame_skip(fps)
  delay = frame_delay(fps, skip)
  debug "animated gif choosing every #{skip} frames with a frame delay of #{delay} (video fps: #{fps})"

  # create the looping animated gif from frames (delete frame files except every #{skip} frame)
  Dir["#{frames_dir}/*.png"].each do |frame_filename|
    basename = File.basename(frame_filename)
    frame_number = basename.split('.').first.to_i
    File.delete(frame_filename) if frame_number % skip != 0
  end

  # convert to animated gif with delay and gif optimisation
  system_call "convert -layers OptimizeTransparency -delay #{delay} -loop 0 \"#{frames_dir}/*.png\" -coalesce \"#{output_path}\""

  # remove tmp frames dir
  FileUtils.rm_rf(frames_dir)
end

Private Instance Methods

debug(message) click to toggle source
Calls superclass method
# File lib/lolcommits/animated_gif.rb, line 73
def debug(message)
  super("#{self.class}: #{message}")
end
frame_delay(fps, skip) click to toggle source
# File lib/lolcommits/animated_gif.rb, line 44
def frame_delay(fps, skip)
  # calculate frame delay
  delay = ((100.0 * skip) / fps.to_f).to_i
  delay < 6 ? 6 : delay # hard limit for IE browsers
end
frame_skip(fps) click to toggle source
# File lib/lolcommits/animated_gif.rb, line 56
def frame_skip(fps)
  # of frames to skip depends on video fps
  case fps
  when 0..15
    2
  when 16..28
    3
  else
    4
  end
end
frames_dir() click to toggle source
# File lib/lolcommits/animated_gif.rb, line 36
def frames_dir
  @frames_dir ||= Dir.mktmpdir
end
null_string() click to toggle source
# File lib/lolcommits/animated_gif.rb, line 40
def null_string
  Lolcommits::Platform.platform_windows? ? 'nul' : '/dev/null'
end
system_call(call_str, capture_output: false) click to toggle source
# File lib/lolcommits/animated_gif.rb, line 68
def system_call(call_str, capture_output: false)
  debug "making system call for \n #{call_str}"
  capture_output ? `#{call_str}` : system(call_str)
end
video_fps(file) click to toggle source
# File lib/lolcommits/animated_gif.rb, line 50
def video_fps(file)
  # inspect fps of the captured video file (default to 29.97)
  fps = system_call("ffmpeg -nostats -v quiet -i \"#{file}\" 2>&1 | sed -n \"s/.*, \\(.*\\) fp.*/\\1/p\"", capture_output: true)
  fps.to_i < 1 ? 29.97 : fps.to_f
end