Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>which Ruby version are you using?</strong></p> <p><strong>which ID3 Tag version are you trying to read?</strong></p> <p><strong>ID3v1 tags</strong> are at the end of a file, in the last 128 bytes. With Net::HTTP it doesn't seem to be possible to seek forward towards the end of the file and read only the last N bytes. If you try that, using <code>headers = {"Range" =&gt; "bytes=128-"}</code> , it always seems to download the complete file. <code>resp.body.size =&gt; file-size</code> . But no big loss, because <strong>ID3 version 1 is pretty much outdated at this point</strong> because of it's limitations, such as fixed length format, only ASCII text, ...). iTunes uses ID3 version 2.2.0.</p> <p><strong>ID3v2 tags</strong> are at the beginning of a file - to support streaming - you can download the initial part of the MP3 file, which contains the ID3v2 header, via HTTP protocol >= 1.1</p> <p><strong>The short answer:</strong></p> <pre><code>require 'net/http' require 'uri' require 'id3' # id3 RUby library require 'hexdump' file_url = 'http://example.com/filename.mp3' uri = URI(file_url) size = 1000 # ID3v2 tags can be considerably larger, because of embedded album pictures Net::HTTP.version_1_2 # make sure we use higher HTTP protocol version than 1.0 http = Net::HTTP.new(uri.host, uri.port) resp = http.get( file_url , {'Range' =&gt; "bytes=0-#{size}"} ) # should check the response status codes here.. if resp.body =~ /^ID3/ # we most likely only read a small portion of the ID3v2 tag.. # file has ID3v2 tag puts resp.body.hexdump tag2 = ID3::Tag2.new tag2.read_from_buffer( resp.body ) @id3_tag_size = tag2.ID3v2tag_size # that's the size of the whole ID3v2 tag # we should now re-fetch the tag with the correct / known size # ... end </code></pre> <p>e.g.:</p> <pre><code> index 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 ["49443302"] ["00000000"] ["11015454"] ["3200000d"] ID3.......TT2... 00000010 ["004b6167"] ["75796120"] ["48696d65"] ["00545031"] .Kaguya Hime.TP1 00000020 ["00000e00"] ["4a756e6f"] ["20726561"] ["63746f72"] ....Juno reactor 00000030 ["0054414c"] ["00001100"] ["4269626c"] ["65206f66"] .TAL....Bible of 00000040 ["20447265"] ["616d7300"] ["54524b00"] ["00050036"] Dreams.TRK....6 00000050 ["2f390054"] ["59450000"] ["06003139"] ["39370054"] /9.TYE....1997.T 00000060 ["434f0000"] ["1300456c"] ["65637472"] ["6f6e6963"] CO....Electronic 00000070 ["612f4461"] ["6e636500"] ["54454e00"] ["000d0069"] a/Dance.TEN....i 00000080 ["54756e65"] ["73207632"] ["2e300043"] ["4f4d0000"] Tunes v2.0.COM.. 00000090 ["3e00656e"] ["67695475"] ["6e65735f"] ["43444442"] &gt;.engiTunes_CDDB 000000a0 ["5f494473"] ["00392b36"] ["34374334"] ["36373436"] _IDs.9+647C46746 000000b0 ["38413234"] ["38313733"] ["41344132"] ["30334544"] 8A248173A4A203ED 000000c0 ["32323034"] ["4341422b"] ["31363333"] ["39390000"] 2204CAB+163399.. 000000d0 ["00000000"] ["00000000"] ["00000000"] ["00000000"] ................ </code></pre> <p><strong>The long answer looks something like this:</strong> (you'll need id3 library version 1.0.0_pre or newer)</p> <pre><code>require 'net/http' require 'uri' require 'id3' # id3 RUby library require 'hexdump' file_url = 'http://example.com/filename.mp3' def get_remote_id3v2_tag( file_url ) # you would call this.. id3v2tag_size = get_remote_id3v2_tag_size( file_url ) if id3v2tag_size &gt; 0 buffer = get_remote_bytes(file_url, id3v2tag_size ) tag2 = ID3::Tag2.new tag2.read_from_buffer( buffer ) return tag2 else return nil end end private def get_remote_id3v2_tag_size( file_url ) buffer = get_remote_bytes( file_url, 100 ) if buffer.bytesize &gt; 0 return buffer.ID3v2tag_size else return 0 end end private def get_remote_bytes( file_url, n) uri = URI(file_url) size = n # ID3v2 tags can be considerably larger, because of embedded album pictures Net::HTTP.version_1_2 # make sure we use higher HTTP protocol version than 1.0 http = Net::HTTP.new(uri.host, uri.port) resp = http.get( file_url , {'Range' =&gt; "bytes=0-#{size-1}"} ) resp_code = resp.code.to_i if (resp_code &gt;= 200 &amp;&amp; resp_code &lt; 300) then return resp.body else return '' end end get_remote_id3v2_tag_size( file_url ) =&gt; 2262 </code></pre> <p>See:</p> <p><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35" rel="nofollow noreferrer">http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35</a></p> <p><a href="http://en.wikipedia.org/wiki/Byte_serving" rel="nofollow noreferrer">http://en.wikipedia.org/wiki/Byte_serving</a></p> <p><strong>some examples how to download in parts files can be found here:</strong></p> <p>but please note that there seems to be no way to start downloading "in the middle"</p> <p><a href="https://stackoverflow.com/questions/2263540/how-do-i-download-a-binary-file-over-http-using-ruby">How do I download a binary file over HTTP?</a></p> <p><a href="http://unixgods.org/~tilo/Ruby/ID3/docs/index.html" rel="nofollow noreferrer">http://unixgods.org/~tilo/Ruby/ID3/docs/index.html</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload