Skip to content

Instantly share code, notes, and snippets.

@meise
Last active August 29, 2015 14:03
Show Gist options
  • Save meise/151b7b5520dbf5dd50f6 to your computer and use it in GitHub Desktop.
Save meise/151b7b5520dbf5dd50f6 to your computer and use it in GitHub Desktop.
ffprobe output parser for deprecated ffprobe versions without json output.
require 'pathname'
require 'open3'
# ffprobe output parser for deprecated ffprobe versions.
class FfprobeParser
# Get media properties for given file.
#
# @example Get properties for a given file.
# FfprobeParser.properties('/srv/file/video.mp4')
# => { legth: 4232, width: 576, height: 1024 }
#
# @param file [String] media file to get information for
# @return properties [Hash] parsed properties
def self.properties(file)
ffprobe_output = ffprobe(check_filepath(file))
parse(ffprobe_output)
end
# Parse ffprobe output string.
#
# @todo
# Ugly regex parsing. Implement better string parser or even better switch
# to ffprobe json output if possible.
# @param string [String] to parse
# @return properties [Hash]
def self.parse(string)
# check string encoding
string = check_giving_encoding(string)
# let's have a hash to store some information
hash = {}
# matching 00:00:00.00 after 'Duration: '
length = /[Duration]+:\s+(\d+:\d+:\d+\.\d+)/.match(string)[1]
hash[:length] = convert_length_to_seconds(length)
# only video files have width and height attributes
if string =~ /Stream\s#.*\sVideo/
hash[:video] = true
# matching 123x456 and split to an array
match = /,\s(\d+x\d+)/.match(string)[1].split('x')
hash[:width] = match.first
hash[:height] = match.last
end
hash
end
class << self
private
# Convert ffprobe length into seconds.
#
# @param string [String] ffproble output length
# @return length [Fixnum] converted length
def convert_length_to_seconds(string)
hours, minutes, seconds = string.split(':')
# remove microseconds from seconds e.g. 42.23
seconds = /(\d{2})\.\d{2}/.match(seconds)[1].to_i
(hours.to_i * 60 * 60)+(minutes.to_i * 60)+seconds
end
# Check that we can use string operations on given string and encoding.
#
# @param string [String] to check
# @return string [String] with valid™ encoding format
def check_giving_encoding(string)
begin
string.match(/i like utf-8/)
rescue
string.force_encoding('ISO-8859-1')
end
string
end
# Call ffprobe system command and return output as string.
#
# @param file [Pathname] to open
# @return string [String] ffprobe output
def ffprobe(file)
stdin, stdout, stderr = Open3.popen3("ffprobe '#{file}'")
stderr.read
end
# Convert file path to pathname object if the file exist
#
# @param file [String] pathname to check and convert to pathname object
# @return file [Pathname] object
def check_filepath(file)
file = Pathname(file)
unless file.exist?
STDERR.puts "File #{file} does not exist!"
exit 1
end
file
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment