Skip to content

Instantly share code, notes, and snippets.

@ucnv
Created May 11, 2010 22:18
Show Gist options
  • Save ucnv/397955 to your computer and use it in GitHub Desktop.
Save ucnv/397955 to your computer and use it in GitHub Desktop.
require 'tmpdir'
require 'pathname'
require 'fileutils'
require 'time'
require 'aviglitch'
class FinalCut
def initialize *paths
@ffmpeg = exec('which ffmpeg').chomp
raise 'ffmpeg doesn\'t exist.' if @ffmpeg.empty?
@mencoder = exec('which mencoder').chomp
raise 'mencoder doesn\'t exist.' if @mencoder.empty?
@original_files = paths
@tmpdir = Dir.mktmpdir
@base_file = @tmpdir + '/base.avi'
tmpfiles = paths.map do |f|
p = Pathname f
# retrun p.to_s if p.extname == 'avi'
tmp = @tmpdir + '/' + p.basename.to_s + '.avi'
exec [@ffmpeg, '-i', p.to_s, '-sameq', tmp].join(' ')
tmp
end
if tmpfiles.size > 1
exec [@mencoder, '-ovc copy -oac copy', tmpfiles, '-o', @base_file].flatten.join(' ')
else
FileUtils.cp tmpfiles.first, @base_file
end
@duration = get_duration @base_file
@cut_files = []
if block_given?
yield self
close
end
end
def cut opts
id = opts.object_id
from = opts[:from] || 0
from = from % @duration
duration = opts[:duration] || @duration
duration = @duration if duration == :whole
duration = duration % @duration unless duration == @duration
size = opts[:size]
framerate = opts[:framerate]
bitrate = opts[:bitrate]
repeat = opts[:repeat]
speed = opts[:speed]
datamosh = opts[:datamosh]
file1 = out = @tmpdir + "/#{id}a.avi"
c = [@ffmpeg, '-i', @base_file, '-sameq']
c += ['-ss', from,
'-t', duration] unless from == 0 && duration == @duration
c += ['-r', framerate] unless framerate.nil?
c += ['-b', bitrate] unless bitrate.nil?
c += ['-s', size] unless size.nil?
c << file1
exec c.join(' ')
unless repeat.nil?
file2 = @tmpdir + "/#{id}b.avi"
c = [@mencoder,
'-ovc copy -oac copy',
'-o', file2
]
c << "#{out} " * repeat
exec c.join(' ')
out = file2
end
if datamosh
file3 = @tmpdir + "/#{id}c.avi"
ag = AviGlitch.open out
ag.glitch(:keyframe) do |d|
"\000" * d.size
end
ag.output file3
out = file3
end
unless speed.nil?
file4 = @tmpdir + "/#{id}d.avi"
c = [@mencoder,
'-ovc copy -oac copy',
'-o', file4,
'-speed', speed,
out
]
exec c.join(' ')
out = file4
end
@cut_files << out
self
end
def output outfile, opt = nil
path = Pathname outfile
out = @tmpdir + '/' + path.basename.to_s + '.o.avi'
if @cut_files.size > 1
c = [@mencoder,
'-ovc lavc -oac mp3lame',
@cut_files.join(' '),
'-o', out
]
exec c.join(' ')
else
out = @cut_files.first
end
unless opt == :raw
file = @tmpdir + '/' + path.basename.to_s
c = [@ffmpeg, '-i', out, '-sameq -y', file]
exec c.join(' ')
out = file
end
FileUtils.cp out, path.to_s
self
end
def close
FileUtils.remove_entry_secure @tmpdir
end
def get_duration file = nil
file ||= @base_file
res = exec [@ffmpeg, '-i', file].join(' ')
if res =~ /Duration: ([\d:.]+),/
Time.parse($1) - Time.parse('00:00')
else
raise "Wrong file : #{file}"
end
end
private
def exec command
IO.popen(command + ' 2>&1') {|io| io.read }
end
class << self
alias open new
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment