moumar / ruby-mp3info

ruby-mp3info read low-level informations and manipulate tags on mp3 files.
http://rdoc.info/github/moumar/ruby-mp3info/master/frames
223 stars 57 forks source link

Mp3InfoError: cannot find a valid frame after reading 2000000 bytes #67

Open alexey opened 8 years ago

alexey commented 8 years ago
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:620 in find_next_frame
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:646 in block in parse_mp3
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:645 in times
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:645 in parse_mp3
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:293 in reload
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:230 in initialize
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:300 in new
/gems/ruby-mp3info-0.8.9/lib/mp3info.rb:300 in open
app/models/zip_file.rb:47 in read_mp3_data

On:

Mp3Info.open(filepath) do |mp3|

Rails 4.2.0 Gem 2.2.2 ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-darwin12.0] OSX 10.11 ruby-mp3info (0.8.9)

Attached mp3 file that cause this error.

m.mp3.zip

alexey commented 8 years ago

@theaamanda Thank you for fast reply !

But after "investigating" mp3 file i've found that it was broken, probably during upload.

mergesort commented 6 years ago

I'm experiencing this same issue, but with an m4a as the input. I've tried regenerating the file a few times and still am encountering this error. I don't want to upload the file itself because it is a copyrighted work (with no DRM), but is there any way I could help to identify the issue?

johnlpollard commented 6 years ago

Any resolution or at least workaround to this issue?

alexanderadam commented 3 years ago

Hi folks,

you can simply increase the amount of bytes for raising. Otherwise it will raise on huge files (i.e. on audio books). An ugly but easy fix is to monkey patch the method.

Put something like this wherever you want:

Mp3Info.class_eval do
  ### reads through @io from current pos until it finds a valid MPEG header
  ### returns the MPEG header as FixNum
  def find_next_frame
    # @io will now be sitting at the best guess for where the MPEG frame is.
    # It should be at byte 0 when there's no id3v2 tag.
    # It should be at the end of the id3v2 tag or the zero padding if there
    #   is a id3v2 tag.
    #dummyproof = @io.stat.size - @io.pos => WAS TOO MUCH

    dummyproof = [ @io_size - @io.pos, 39_000_000 ].min
    dummyproof.times do |i|
      if @io.getbyte == 0xff
        data = @io.read(3)
        raise Mp3InfoEOFError if @io.eof?
        head = 0xff000000 + (data.getbyte(0) << 16) + (data.getbyte(1) << 8) + data.getbyte(2)
        begin
          return Mp3Info.get_frames_infos(head)
        rescue Mp3InfoInternalError
          @io.seek(-3, IO::SEEK_CUR)
        end
      end
    end
    if @io.eof?
      raise Mp3InfoEOFError
    else
      raise Mp3InfoError, "cannot find a valid frame after reading #{dummyproof} bytes"
    end
  end
end