Created
May 11, 2010 22:18
-
-
Save ucnv/397955 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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