You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
3.4 KiB
Ruby

=begin
chop up two vods using splits as timestamps
vertically stack each clip with the same name
from each vod chopping
cut a video with ffmpeg:
ffmpeg -i input.mp4 -ss <time> -t <duration> -c:v copy -c:a copy output.mp4
=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 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 16 " \
"-init_hw_device vaapi=foo:/dev/dri/renderD128 " \
"-hwaccel vaapi " \
"-hwaccel_output_format vaapi " \
"-hwaccel_device foo " \
"-i #{input1} " \
"-hwaccel vaapi " \
"-hwaccel_output_format vaapi " \
"-hwaccel_device foo " \
"-i #{input2} " \
"-filter_hw_device foo " \
"-c:v h264_vaapi " \
"-filter_complex ' " \
"[0:v]format=nv12|vaapi,hwupload[a], " \
"[1:v]format=nv12|vaapi,hwupload[b], " \
"[0:a][1:a]amix[a], " \
"[a][b]vstack_vaapi=inputs=2[out]' " \
"-map [out] -map [a] " \
"#{output}"
system(vstack_cmd)
end
=begin
chop up the video by timestamp
=end
def chop_video(path)
entries = Dir["#{path}/*"]
split_file_path = entries.select {|e| e.end_with?(".json")}[0]
video_file_path = entries.select {|e| e.end_with?(".mkv")}[0]
split_file = File.open("#{Dir.pwd}/#{split_file_path}")
data = JSON.load split_file
game_title = data['title']
splits = data['splits']
time = "00:00:00"
segments = []
`mkdir -p clips`
splits.each do |split|
segments << Segment.new(time, split['time'])
time = split['time']
end
chop_multi(video_file_path, segments, Dir["#{path}/clips"][0])
end
=begin
stack each video and save them to output/<name of video>
=end
def stack_video(p1, p2)
e1 = Dir["#{p1}/clips/*"]
`mkdir -p output`
e1.each {|e| print "#{e}\n"}
output = lambda { |e|
o = e.split("#{p1}/clips/")[1]
e2 = e.split("#{p1}")[1]
vstack("#{p2}/#{e2}", e, "output/#{o}")
}
e1.map(&output)
end
=begin
concatenate clips into final video
=end
def cat_video()
entries = Dir["output/*"]
file = File.open("list.txt", "r+")
for i in 0..entries.count - 1 do
file.write("file output/#{i}.mkv\n")
end
`ffmpeg -y -f concat -i list.txt -c copy output.mkv`
end
def concatenate_video(p1, p2)
chop_video(p1)
chop_video(p2)
stack_video(p1, p2)
cat_video()
end
concatenate_video(ARGV[0], ARGV[1])