Skip to content

Instantly share code, notes, and snippets.

@venj
Created May 20, 2012 06:56
Show Gist options
  • Save venj/2757072 to your computer and use it in GitHub Desktop.
Save venj/2757072 to your computer and use it in GitHub Desktop.
The real deal remux script that can remux videos with M4V compatible video stream. Audio stream will be encoded to 192kbps aac if it is not m4v compatible audio.
#!/usr/bin/env ruby
# Remux MP4/H264 videos (mkv, avi, etc.) to m4v.
TMPFILE = "/tmp/ffprobe_out.txt"
VIDEO_CONTAINER = ["mkv", "f4v", "avi", "divx", "ts"]
VCODECS = ["mpeg4", "h264"]
ACODECS = ["aac"]
if (`which ffmpeg` == "")
puts "You need ffmpeg to use this command."
exit 1
end
def detect(file)
system("ffprobe -v info \"#{file}\" > #{TMPFILE} 2>&1")
output = open(TMPFILE).read
vregex = /Stream .+? Video: (\w+) /
vmatch = vregex.match(output)
vcodec = vmatch[1] unless vmatch.nil?
aregex = /Stream .+? Audio: (\w+),? /
amatch = aregex.match(output)
acodec = amatch[1] unless amatch.nil?
File.unlink TMPFILE
return [acodec, vcodec]
end
def supported_files(noencode=false)
files = []
Dir["*.*"].each do |file|
acodec = detect(file)[0]
ext = file.split(".").last
next unless VIDEO_CONTAINER.include?(ext.downcase)
next if noencode && !ACODECS.include?(acodec)
files << file
end
files
end
def remux(noencode=false)
counter = 1;file_count = supported_files(noencode).size
supported_files(noencode).each do |file|
ext = file.split(".").last
name = File.basename file, ".#{ext}"
outfile = "#{name}.m4v"
acodec,vcodec = detect(file)
unless VCODECS.include?(vcodec)
puts "#{file}: video codec \"#{vcodec}\" is not compatible with m4v."
next
end
print "Remuxing #{file} (#{counter}/#{file_count})..."
other_opt = ""
other_opt = "-absf aac_adtstoasc" #if ext.downcase == "ts"
File.unlink outfile if File.exists?(outfile)
if ACODECS.include?(acodec)
system("ffmpeg -v error -i '#{file}' -c:a copy -c:v copy #{other_opt} '#{outfile}'")
else
system("ffmpeg -v error -i '#{file}' -c:a:192 aac -c:v copy #{other_opt} '#{outfile}'")
end
puts "Done"
counter += 1
end
end
if ARGV[0] == "info"
supported_files.each do |file|
acodec,vcodec = detect(file)
if VCODECS.include?(vcodec) && acodec != "aac"
puts "\"#{file}\" needs to re-encode audio track (acodec: \"#{acodec}\")."
elsif (!VCODECS.include?(vcodec))
puts "\"#{file}\" is not able to remux to M4V (vcodec: \"#{vcodec}\")."
else
puts "\"#{file}\" is M4V ready!"
end
end
elsif ARGV[0] == "noencode" || ARGV[0] == "nc"
remux(true)
else
remux
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment