Skip to content

Instantly share code, notes, and snippets.

@missingno15
Created June 8, 2017 02:11
Show Gist options
  • Save missingno15/ad8e324895a4be9f01b96b085815f2a5 to your computer and use it in GitHub Desktop.
Save missingno15/ad8e324895a4be9f01b96b085815f2a5 to your computer and use it in GitHub Desktop.
Mute the audio of certain parts of a video with ffmpeg via Ruby CLI script
require "optparse"
require "active_support/all"
options = []
input = nil
output = nil
has_two_timestamps= ->(arg) {
if arg.split(",").count == 2
nil
else
"Needs to have two timestamps (e.g. '01:46:48,01:48:46')"
end
}
intervals_are_delimited_with_colons = ->(arg) {
start_interval, end_interval = arg.split(",")
if /\d{2}:\d{2}:\d{2}/.match?(start_interval.to_s) && /\d{2}:\d{2}:\d{2}/.match?(end_interval.to_s)
nil
else
"Intervals must be separated by colons (e.g. 01:48:46')"
end
}
intervals_have_proper_start_and_end = ->(arg) {
# start should not be greater than end
intervals = arg.split(",").map { |interval| interval.split(":") }
start_interval = intervals[0] || []
end_interval = intervals[1] || []
start_in_seconds = (start_interval[0].to_i.hours + start_interval[1].to_i.minutes + start_interval[2].to_i.seconds).to_i
end_in_seconds = (end_interval[0].to_i.hours + end_interval[1].to_i.minutes + end_interval[2].to_i.seconds).to_i
if start_in_seconds > end_in_seconds
nil
else
"The end interval must be greater than the start interval"
end
}
checks = [
has_two_timestamps,
intervals_are_delimited_with_colons,
intervals_have_proper_start_and_end
]
option_parser = OptionParser.new do |opts|
opts.on("-t", "--interval INTERVAL", "Specify time interval to be muted") do |t|
# Check if interval is in the following format
# 1:46:48,1:48:46
errors = checks.map { |check| check.call(t) }.compact
options << [t, errors]
end
opts.on("-i", "--input INPUT", "Name of the input file") do |i|
if o.empty?
fail "Input file must be provided"
else
input = i
end
end
opts.on("-o", "--output OUTPUT", "Name of the output file") do |o|
if o.empty?
fail "Output file must be provided"
else
output = o
end
end
end
option_parser.parse!
# See if there are any errors
option_errors = options.select { |interval| _t, errors = interval; errors.any? }
option_errors << ["", ["An input file was not detected"]] if input.nil?
option_errors << ["", ["An output file was not detected, you need to put an "]] if output.nil?
if option_errors.any?
puts "\n\n"
error_message = option_errors.inject("Some of the timestamps given were found to have the following errors:\n\n") do |message, interval|
timestamp, errors = interval
message << timestamp + "\n"
message << errors.join("\n")
message << "\n\n"
message
end
puts error_message
else
af = options.map do |set|
timestamps, _errors = set
start_time, end_time = timestamps.split(",").map { |timestamp| timestamp.split(":").map(&:to_i) }
start_time_in_seconds = start_time[0].hours + start_time[1].minutes + start_time[2].seconds
end_time_in_seconds = end_time[0].hours + end_time[1].minutes + end_time[2].seconds
"volume=enable='between(t,#{start_time_in_seconds},#{end_time_in_seconds})':volume=0"
end.join(", ")
# ffmpeg -i 20170608004526_SHOWROOM_AKB48のオールナイトニッポン.flv -af "volume=enable='between(t,1720, 1852)':volume=0, volume=enable='between(t,5822,5940)':volume=0, volume=enable='between(t,6479,6597)':volume=0, volume=enable='between(t,7964,8088)':volume=0" -vcodec copy 20170608004526_SHOWROOM_AKB48のオ ールナイトニッポンmaster.mp4
`ffmpeg -i #{input} -af "#{af}" -vcodec copy #{output}`
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment