Convert supposed seconds to duration?

97 views Asked by At

I'm new to Ruby so I'm probably going about this completely wrong, but using taglib-ruby I keep getting a wrong result unless it's a wrong amount of seconds maybe nanoseconds?

I tried with bash and mediainfo a different movie but worked ok ...

$(date -ud "@$(($seconds/1000))" +'%_H:%M')
def get_duration_hrs_and_mins(milliseconds)
    return '' unless milliseconds

    hours, milliseconds   = milliseconds.divmod(1000 * 60 * 60)
    minutes, milliseconds = milliseconds.divmod(1000 * 60)
    seconds, milliseconds = milliseconds.divmod(1000)
    "#{hours}h #{minutes}m #{seconds}s #{milliseconds}ms"
end

TagLib::MP4::File.open("filename.mp4") do |mp4|
    seconds = mp4.length
    puts get_duration_hrs_and_mins(seconds)
end

The amount of seconds is 1932993085 and the duration should be roughly 2 h 15 min.

1

There are 1 answers

1
Mark Reed On BEST ANSWER

I'm afraid you are misinformed. The length attribute of a TagLib::MP4::File object is inherited from the regular File class and just tells you the size of the file in bytes; it has nothing to do with the duration of the contained media:

$ ls -l test.mp4
-rw-r--r--@ 1 user  staff  39001360 Aug 14  2015 test.mp4
$ ruby -rtaglib -e 'TagLib::MP4::File.open("test.mp4"){|f|puts f.length}'
39001360

The particular file I'm examining in the above code snippet happens to be 25 seconds long, but there's no way to tell that from the fact that it's about 39 megabytes in size.

What you want is the #length method of the TagLib::MP4::Properties object, not the ::File one. You can get that by calling #audio_properties on the File object:

TagLib::MP4::File.open("filename.mp4") do |mp4|
  seconds = mp4.audio_properties.length
  puts get_duration_hrs_and_mins(seconds)
end

That return value is seconds, not milliseconds, so you need to adjust your get_duration method accordingly. Really you just want something like this:

total_seconds = mp4.audio_properties.length
total_minutes, seconds = total_seconds.divmod(60)
total_hours, minutes = total_minutes.divmod(60)
days, hours = total_hours.divmod(24)

puts "Duration is #{days}d#{hours}h#{minutes}m#{seconds}s"