1

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.

jamesc
  • 12,423
  • 15
  • 74
  • 113
espr3ss0
  • 33
  • 1
  • 3
  • The formatting of code blocks at stackoverflow.com is explained [here](https://meta.stackexchange.com/questions/22186/how-do-i-format-my-code-blocks). – Cary Swoveland Sep 04 '19 at 00:34
  • I can't understand what the sentence "I tried with bash and mediainfo a different movie but worked ok" means. – Amit Kumar Gupta Sep 04 '19 at 01:17
  • You are asking how to use TagLib but you don't say what TagLib library you are using? I assume taglib-ruby? It seems to me that you are passing seconds into a method that is expecting milliseconds, Why? – jamesc Sep 04 '19 at 01:32
  • 1932993085 seconds is 14 hours 31 minutes and 25 seconds as evidenced by `Time.at(1932993085).utc.strftime("%H:%M:%S")` – jamesc Sep 04 '19 at 01:42
  • No. 1932993085 seconds is over 61 years. What you've shown is that POSIX time 1932993085 corresponds to a point in time whose time of day is 2:31:25 pm UTC. In particualar, it's that time on April 3, 2031 AD. – Mark Reed Sep 04 '19 at 02:37

1 Answers1

0

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"
Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • There really should be 2 duration properties because sometimes the audio track is less than the video. – espr3ss0 Sep 04 '19 at 11:50