class EasyVideoUtils

Public Class Methods

new(vid_in=nil, vid_out='video.mp4', out: vid_out, working_dir: '/tmp', debug: false) click to toggle source
# File lib/easyvideo_utils.rb, line 75
def initialize(vid_in=nil, vid_out='video.mp4', out: vid_out, 
               working_dir: '/tmp', debug: false)

  @file_out, @working_dir, @debug = out, working_dir, debug
  
  if vid_in.is_a? String then
    @file_in = vid_in
  elsif vid_in.is_a? Array
    @files_in = vid_in
  end

end

Public Instance Methods

add_audio(audio_file, show: false) click to toggle source

Add an audio track to a video which contains no audio

# File lib/easyvideo_utils.rb, line 90
def add_audio(audio_file, show: false)

  command = "ffmpeg -i #{@file_in} -i #{audio_file} -codec copy " + 
            "-shortest #{@file_out} -y"
  run command, show

end
add_subtitles(file, show: false) click to toggle source

To add subtitles, supply a .srt file

# File lib/easyvideo_utils.rb, line 100
def add_subtitles(file, show: false)
     
  command = "ffmpeg -i #{@file_in} -i #{file} -c copy -c:s mov_" + 
            "text #{@file_out} -y"
  run command, show
  
end
capture_desktop(show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 108
def capture_desktop(show: false)

  command = "ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i " + 
  ":0.0+0,0 #{@file_out}"
  run command, show

end
concat(files=@files_in, show: false) click to toggle source

Concatenate 2 or more videos

Notes:

  • Video must be of same format and codec

  • Only video with no audio is currently supported

# File lib/easyvideo_utils.rb, line 122
def concat(files=@files_in, show: false)
  
  inputs = files.map {|file| "-i #{file}"}.join(' ')
  filter = files.map.with_index {|file,i| "[%s:v]" % i}.join(' ')
  
  command = "ffmpeg #{inputs} \ " + 
  " -filter_complex \"#{filter} concat=n=#{files.length}:v=1 [v]\" \ " + 
  " -map \"[v]\"  #{@file_out}"

  run command, show
  
end
convert(show: false)
Alias for: transcode
create_poster(audiox=nil, imagex=nil, image: imagex, audio: audiox, show: false) click to toggle source

creates a video from an audio file along with a single image file

# File lib/easyvideo_utils.rb, line 137
def create_poster(audiox=nil, imagex=nil, image: imagex, 
                  audio: audiox, show: false)
  command = "ffmpeg -loop 1 -i #{image} -i #{audio} -c:v libx264 -c:a " + 
      "aac -strict experimental -b:a 192k -shortest #{@file_out}"
  run command, show
end
create_slideshow(ext: '.jpg', image_duration: 5, show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 144
def create_slideshow(ext: '.jpg', image_duration: 5, show: false)
  
  file_mask = @file_in || "image-%03d" + ext
  command = "ffmpeg -r 1/#{image_duration} -i #{file_mask} -c:v " + 
      "libx264 -r 30 -pix_fmt yuv420p #{@file_out}"  
  run command, show
  
end
duration() click to toggle source

Duration returned in seconds

# File lib/easyvideo_utils.rb, line 155
def duration()
  
  s = `exiftool #{@file_in}`
  puts 's: ' + s.inspect if @debug
  r = s[/Duration.*(\d{1,2}:\d{2}:\d{2})/,1]

  puts 'r: ' + r.inspect if @debug    
  
  if r then
    a = r.split(':').map(&:to_i)
    return Subunit.new(units={minutes:60, hours:60, seconds: 0}, a).to_i
  end
  
  puts 'r: ' + r.inspect if @debug
  s[/Duration.*: (\d+\.\d+) s/,1].to_f

end
extract_images(show: false, ext: '.png', rate: 1) click to toggle source

Extract images from the video

switches used:

-r – Set the frame rate. I.e the number of frames to be extracted into images per second. -f – Indicates the output format i.e image format in our case.

# File lib/easyvideo_utils.rb, line 180
def extract_images(show: false, ext: '.png', rate: 1)
  command = "ffmpeg -i #{@file_in} -r #{rate} -f image2 image-%2d#{ext}"
  run command, show
end
grab_image(start_time=1, show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 190
def grab_image(start_time=1, show: false)
  command = "avconv -i #{@file_in} -ss #{start_time.to_s} -frames:v 1 #{@file_out} -y"
  run command, show
end
info(show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 185
def info(show: false)
  command = "avprobe #{@file_in}"
  run command, show
end
play(show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 195
def play(show: false)
  command = "mplayer #{@file_out}"
  run command, show
end
preview(show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 200
def preview(show: false)
  command = "ffplay #{@file_out}"
  run command, show
end
remove_audio(show: false) click to toggle source
# File lib/easyvideo_utils.rb, line 205
def remove_audio(show: false)
  command = "ffmpeg -i #{@file_in} -an #{@file_out}"
  run command, show
end
remove_video(show: false) click to toggle source

removes the video track which leaves the audio track e.g. ffmpeg -i input.mp4 -vn output.mp3

# File lib/easyvideo_utils.rb, line 213
def remove_video(show: false)
  command = "ffmpeg -i #{@file_in} -vn #{@file_out}"
  run command, show
end
resize(scale='320x240', show: false) click to toggle source

Resize e.g. to 320x240

# File lib/easyvideo_utils.rb, line 220
def resize(scale='320x240', show: false)
  command = "avconv -i #{@file_in} -s #{scale} #{@file_out} -y"
  run command, show
end
Also aliased as: scale
scale(scale='320x240', show: false)
Alias for: resize
screencast(duration: 6, scale: 0.75, window: true) click to toggle source

starts recoring after 2 seconds for a duration of 6 seconds

# File lib/easyvideo_utils.rb, line 230
def screencast(duration: 6, scale: 0.75, window: true)
  
  gif_file = @file_out.sub(/\w+$/,'gif')
  
  EasyImgUtils.new(out: gif_file)\
      .screencast(duration: duration, scale: scale, window: window)
  EasyVideoUtils.new(gif_file, @file_out).transcode
  
end
slowdown(speed=:x2, show: false) click to toggle source

slow down a video

note: presentation timestamp (PTS) 'x2' = half speed; 'x4' = quarter speed

# File lib/easyvideo_utils.rb, line 245
def slowdown(speed=:x2, show: false)
  
  factor = {x1_5: 1.5, x2: 2.0, x4: 4.0}[speed.to_s.sub('.','_').to_sym]
  command = "ffmpeg -i #{@file_in} -vf \"setpts=#{factor}*PTS\" " + 
      "#{@file_out} -y"
  run command, show
  
end
speedup(speed=:x2, show: false) click to toggle source

speed up a video

note: presentation timestamp (PTS) 'x2' = double speed; 'x4' = quadruple speed

# File lib/easyvideo_utils.rb, line 259
def speedup(speed=:x2, show: false)
  
  h = {x1_5: 0.75, x2: 0.5, x4: 0.25, x6: 0.166, x8: 0.125, x16: 0.0625, 
       x32: 0.03125, x64: 0.015625}
  factor = h[speed.to_s.sub('.','_').to_sym]
  command = "ffmpeg -i #{@file_in} -vf \"setpts=#{factor}*PTS\" " + 
      "#{@file_out} -y"
  run command, show
  
end
transcode(show: false) click to toggle source

Transcodes avi -> mp4

# File lib/easyvideo_utils.rb, line 272
def transcode(show: false)
  
  return gif_to_mp4() if File.extname(@file_in) == '.gif'
  
  command = "ffmpeg -i #{@file_in} #{@file_out} -y"
  run command, show    

end
Also aliased as: convert
trim(start_time, duration, show: false) click to toggle source

Trim the start and end of the video times can be expressed in human time format e.g. '1m 4s', '2m 30'

# File lib/easyvideo_utils.rb, line 286
def trim(start_time, duration, show: false)
      
  t1 = "%02d:%02d:%02d" % (start_time.to_s.sub(/m/,'\00s').split(/\D/)\
                           .reverse + [0,0]).take(3).reverse
  
  command = "avconv -i #{@file_in} -ss #{t1} -t #{duration.to_s} " + 
      "-codec copy #{@file_out}"
  run command, show
  
end
youtube_dl(show: false) click to toggle source

Download a video from YouTube

# File lib/easyvideo_utils.rb, line 299
def youtube_dl(show: false)    
  
  command = "youtube-dl -f 'bestvideo[ext=mp4]+" + 
      "bestaudio[ext=m4a]/best[ext=mp4]/best' #{@file_in}"
  command += ' -o ' + @file_out if @file_out
  run command, show    

end

Private Instance Methods

gif_to_mp4(show: false) click to toggle source

see unix.stackexchange.com/questions/40638/how-to-do-i-convert-an-animated-gif-to-an-mp4-or-mv4-on-the-command-line

# File lib/easyvideo_utils.rb, line 312
def gif_to_mp4(show: false)
  
  command = "ffmpeg -i %s -movflags faststart -pix_fmt yuv420p \
      -vf \"scale=trunc(iw/2)*2:trunc(ih/2)*2\" %s" % [@file_in, @file_out]
  run command, show
  
end
run(command, show=false) click to toggle source
# File lib/easyvideo_utils.rb, line 320
def run(command, show=false)

  if show then 
    command
  else
    puts "Using ->" + command
    system command
  end

end