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
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])
|
|
|