forked from vitorgalvao/tiny-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhuman-media-time
More file actions
executable file
·86 lines (65 loc) · 2.69 KB
/
Copy pathhuman-media-time
File metadata and controls
executable file
·86 lines (65 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env ruby
require 'open3'
require 'optparse'
# Options
ARGV.push('--help') if ARGV.empty?
options = {}
OptionParser.new do |opt|
opt.banner = <<~EOS
Output total running time of files in a human-readable way.
Usage:
#{File.basename($PROGRAM_NAME)} [options] <path...>
Options:
EOS
opt.on('-u [s|d|h|m]', '--unit [s|d|h|m]', 'Output a whole number of the total time rounded to the unit.') { |unit| options[:unit] = unit }
opt.on('-p [s|d|h|m]', '--precision [s|d|h|m]', 'Output human-readable result rounded and truncated to the chosen unit. Values of zero are ommited.') { |unit| options[:precision] = unit }
end.parse!
# Parse time values
total_time = {} # Each unit has the total value of everything
split_time = {} # Each unit has its corresponding value with the others discounted
ms_total = ARGV.map { |file| Open3.capture2('mediainfo', '--Output=General;%Duration%,', file).first.split(',').map(&:to_i) }.flatten.reduce(0, :+)
# Building the hashes in this order simplifies the 'reduce' later on
total_time['d'] = (ms_total.to_f / (1000 * 60 * 60 * 24))
total_time['h'] = (ms_total.to_f / (1000 * 60 * 60))
total_time['m'] = (ms_total.to_f / (1000 * 60))
total_time['s'] = (ms_total.to_f / 1000)
split_time['d'] = total_time['d'] % 365
split_time['h'] = total_time['h'] % 24
split_time['m'] = total_time['m'] % 60
split_time['s'] = total_time['s'] % 60
def unit_time(precision_unit, input_hash)
input_hash[precision_unit].round
end
def human_time(precision_unit, input_hash)
# The split_times hash includes floats, so here is where we round the values we want and discard the ones we do not
time_hash = {}
input_hash.keys.each do |unit|
if unit == precision_unit
time_hash[unit] = input_hash[unit].round
break # Since we already reached our desired precision, all further keys can be ignored
end
time_hash[unit] = input_hash[unit].to_i
end
# Normalise rare cases where rounding precision would give an underisable result
# Without this, a starting point of '1d 23h 50m 53s' rounded to hours would result in '1d 24h' instead of '2d'
if time_hash['s'] == 60
time_hash['m'] += 1
time_hash.delete('s')
end
if time_hash['m'] == 60
time_hash['h'] += 1
time_hash.delete('m')
end
if time_hash['h'] == 24
time_hash['d'] += 1
time_hash.delete('h')
end
time_hash.reject! { |_, value| value.zero? } # Eliminate zeros.
time_hash.reduce('') { |string, (key, value)| string + "#{value}#{key} " }.strip
end
if options[:unit]
puts unit_time(options[:unit], total_time)
exit 0
end
options[:precision] = 's' if options[:precision].nil? # If no precision is given, assume seconds
puts human_time(options[:precision], split_time)