Skip to content

Instantly share code, notes, and snippets.

@peterc
Created February 3, 2018 03:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterc/d4446563904bcae8796b282ab9fdaee9 to your computer and use it in GitHub Desktop.
Save peterc/d4446563904bcae8796b282ab9fdaee9 to your computer and use it in GitHub Desktop.
Quickly get the duration of a remote MP3 without fetching the whole thing
require 'uri'
require 'net/http'
require 'mp3info'
# This works, but is flawed and needs work.
# Why? An ID3v2 tag is not always going to
# be within the first 8K of a file! It can
# be up to 256MB in length apparently.. so
# we need to flexibly scale. But this works
# 99% of the time..
def get_mp3_length(url)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
# Make a request for only the first 8K of the MP3
request = Net::HTTP::Get.new(uri.path)
request['Range'] = 'bytes=0-8192'
response = http.request(request)
# Grab out the full length of the remote file
bytes = response.to_hash['content-range'].first[/0-\d+\/(\d+)/, 1].to_i
# Open the MP3 chunk we have and get the bitrate info
mp3 = Mp3Info.open(StringIO.new(response.body))
bitrate = mp3.bitrate * 1000 / 8
mp3.close
# File size divided by bitrate equals approximate length
# Obviously, VBR can throw things off slightly
bytes.to_f / bitrate
end
puts get_mp3_length(ARGV.first)
@peterc
Copy link
Author

peterc commented Feb 3, 2018

Hmm, seems this only works with straightforward setups, and not servers going heavy on the chunking..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment