Search code examples
rubymp3id3

Use ruby mp3info to read mp3 ID3 from external site (without loading whole file)


I have a list of files on a server and would like to load and parse only the ID3 from each file.

The code below loads the entire file, which is (obviously) very time consuming when batched.

require 'mp3info'
require 'open-uri'

uri = "http://blah.com/blah.mp3"

Mp3Info.open(open(uri)) do |mp3|
    puts mp3.tag.title   
    puts mp3.tag.artist   
    puts mp3.tag.album
    puts mp3.tag.tracknum
end

Solution

  • Well this solution works for id3v2 (the current standard). ID3V1 doesn't have the metadata at the beginning of the file, so it wouldn't work in those cases.

    This reads the first 4096 bytes of the file, which is arbitrary. As far as I could tell from the ID3 documentation, there is no limit to the size, but 4kb was when I stopped getting parsing errors in my library.

    I was able to build a simple dropbox audio player, which can be seen here: soundstash.heroku.com

    and open-sourced the code here: github.com/miketucker/Dropbox-Audio-Player

    require 'open-uri'
    require 'stringio'
    require 'net/http'
    require 'uri'
    require 'mp3info'
    
    url = URI.parse('http://example.com/filename.mp3') # turn the string into a URI
    http = Net::HTTP.new(url.host, url.port) 
    req = Net::HTTP::Get.new(url.path) # init a request with the url
    req.range = (0..4096) # limit the load to only 4096 bytes
    res = http.request(req) # load the mp3 file
    child = {} # prepare an empty array to store the metadata we grab
    Mp3Info.open( StringIO.open(res.body) ) do |m|  #do the parsing
        child['title'] = m.tag.title 
        child['album'] = m.tag.album 
        child['artist'] = m.tag.artist
        child['length'] = m.length 
    end