3

I'm working on a project that stores data on audio tracks and requires the use of timecodes for the start and end points of the track on the audio. I also need to calculate and display the duration of the track. Eg. a track starts at 0:01:30 and finishes at 0:04:12. So its duration is a total of 2 mins and 42 secs.

The trick is that everything needs to be displayed and handled as timecodes, so in the above example the duration needs to be displayed as 0:02:42.

So my question is how you would store the values? The easiest option would be to store the start and end times as Time in the database. Its very easy to calculate the duration and you can utilise the Rails time helpers in the forms. The only painful part is turning the duration back into a time value for display (since if I supply just the number of seconds to strptime it keeps using the current time to fill in the other fields)

The other option that I considered is storing them as numeric values (as the number of seconds). But then I have to write a lot of code to convert them to and from some type of timecode format and I can't use the Rails time helpers.

Is there another idea that I haven't considered? Is there an easy way to calculate and display the duration as a timecode format?

richard
  • 1,565
  • 2
  • 18
  • 35

1 Answers1

4

I would store them as seconds or milliseconds. I've been working on a music library manager/audio player in Ruby, and I actually had to write the two methods you would need. It's not that much code:

  # Helper method to format a number of milliseconds as a string like
  # "1:03:56.555". The only option is :include_milliseconds, true by default. If
  # false, milliseconds won't be included in the formatted string.
  def format_time(milliseconds, options = {})
    ms = milliseconds % 1000
    seconds = (milliseconds / 1000) % 60
    minutes = (milliseconds / 60000) % 60
    hours = milliseconds / 3600000

    if ms.zero? || options[:include_milliseconds] == false
      ms_string = ""
    else
      ms_string = ".%03d" % [ms]
    end

    if hours > 0
      "%d:%02d:%02d%s" % [hours, minutes, seconds, ms_string]
    else
      "%d:%02d%s" % [minutes, seconds, ms_string]
    end
  end

  # Helper method to parse a string like "1:03:56.555" and return the number of
  # milliseconds that time length represents.
  def parse_time(string)
    parts = string.split(":").map(&:to_f)
    parts = [0] + parts if parts.length == 2
    hours, minutes, seconds = parts
    seconds = hours * 3600 + minutes * 60 + seconds
    milliseconds = seconds * 1000
    milliseconds.to_i
  end

It's written for milliseconds, and would be a lot simpler if it was changed to work with seconds.

Paige Ruten
  • 172,675
  • 36
  • 177
  • 197
  • Thanks. You're right that the code doesn't look too bad. But how about on the form side? I'm not sure that my users could reliably enter the data in a timecode format. I'm pretty sure they would much prefer a dropdown style. – richard Dec 19 '12 at 23:13
  • Hmm, right. I think you could use [virtual attributes](http://railscasts.com/episodes/16-virtual-attributes) to use the time helper on your form to send the two times to your virtual attribute setters, which would do the conversion and set the actual numeric fields to the number of seconds. But maybe at that point you're better off just storing them as Times to begin with, I dunno. BTW, I vaguely remember trying to store times in datetime fields in Rails, and running into lots of problems with it converting to a different timezone, so be careful of that... – Paige Ruten Dec 19 '12 at 23:29
  • Thanks for the help. Your answer got me thinking and I have decided to store everything as Time values with the proviso that I initialise all of them with `Time.utc(0)` to ensure that they all start on a common date. Even though the date needs is discarded in the display, the duration calculation still has to take it into account. The duration can then be converted into a Time also with `Time.utc(0) + duration`. I can then use a simple `strftime` call to format both times and duration in a timecode format. – richard Dec 19 '12 at 23:49