Last active
August 29, 2015 14:03
-
-
Save meise/151b7b5520dbf5dd50f6 to your computer and use it in GitHub Desktop.
ffprobe output parser for deprecated ffprobe versions without json output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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