diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..8b9ddf3 --- /dev/null +++ b/Gemfile @@ -0,0 +1 @@ +gem 'ruby_sscanf' diff --git a/vodcmp.rb b/vodcmp.rb index 846f3af..aba9782 100644 --- a/vodcmp.rb +++ b/vodcmp.rb @@ -8,16 +8,62 @@ =end require "json" +require "ruby_sscanf" + +def cvt_time(str) + fmt0 = "%f" + fmt1 = "%d:%f" + fmt2 = "%d:%d:%f" + + case str.count(":") + when 0 + fmt = fmt0 + when 1 + fmt = fmt1 + when 2 + fmt = fmt2 + else + print "error" + exit 1 + end + + return str.sscanf(fmt) +end + +class Segment + attr_accessor :start_t + attr_accessor :end_t + + def initialize(start_str, end_str) + ts = cvt_time(start_str) + ets = cvt_time(end_str) + + @start_t = ts.reverse.map.with_index {|x, i| x * (60 ** i)}.sum + @end_t = ets.reverse.map.with_index {|x, i| x * (60 ** i)}.sum + end +end def chop(input1, time, dur, output="output.mkv") -chop_cmd = "ffmpeg -y -threads 24 -i #{input1} -ss #{time} -to #{dur} -c:v copy -c:a copy #{output}.mkv" +chop_cmd = "ffmpeg -y -threads 16 -i #{input1} -ss #{time} -to #{dur} -c:v copy -c:a copy #{output}.mkv" system(chop_cmd) end +def chop_multi(video, segments, output_path) +filter = segments.map.with_index { |s, i| + "[0:v] trim=#{s.start_t}:end=#{s.end_t}, setpts=PTS-STARTPTS [v#{i}];" \ + "[0:a] atrim=#{s.start_t}:end=#{s.end_t},asetpts=PTS-STARTPTS [a#{i}];" +} +maps = segments.map.with_index {|s, i| "-map [v#{i}] -map [a#{i}] #{output_path}/#{i}.mkv"}.join(" ") +chop_cmd = "ffmpeg -y -threads 4 -i #{video} " \ + "-filter_complex '#{filter.join(" ")}'" +chop_cmd = [chop_cmd, maps].join(" ") +system(chop_cmd) +end + #need to make different commands for nvidia and x264 def vstack(input1, input2, output="output.mkv") vstack_cmd = "ffmpeg -y " \ - "-threads 24 " \ + "-threads 16 " \ "-init_hw_device vaapi=foo:/dev/dri/renderD128 " \ "-hwaccel vaapi " \ "-hwaccel_output_format vaapi " \ @@ -57,12 +103,16 @@ def chop_video(path) time = "00:00:00" + segments = [] + `mkdir -p clips` splits.each do |split| - chop(video_file_path, time, split['time'], "clips/#{split['title'].split(" ").join("_").downcase}") + segments << Segment.new(time, split['time']) time = split['time'] end + + chop_multi(video_file_path, segments, Dir["#{path}/clips"][0]) end =begin @@ -87,13 +137,15 @@ end concatenate clips into final video =end def cat_video() - entries = Dir["output/*"].map { |entry| "file #{entry}\n" }.join + entries = Dir["output/*"] + + file = File.open("list.txt", "r+") - File.open("list.txt", "w") do |file| - file.write entries + for i in 0..entries.count - 1 do + file.write("file output/#{i}.mkv\n") end - `ffmpeg -f concat -i list.txt -c copy output.mkv` + `ffmpeg -y -f concat -i list.txt -c copy output.mkv` end def concatenate_video(p1, p2)