使用原生Chrome Javascript / FileReader / DataView读取id3 v2.4标签 [英] Read id3 v2.4 tags with native Chrome Javascript/FileReader/DataView

查看:154
本文介绍了使用原生Chrome Javascript / FileReader / DataView读取id3 v2.4标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 ebidel 的答案,可以使用 jDataView

Based on the answer of ebidel, one can read id3v1 tags by using jDataView:

document.querySelector('input[type="file"]').onchange = function (e) {
    var reader = new FileReader();

    reader.onload = function (e) {
        var dv = new jDataView(this.result);

        // "TAG" starts at byte -128 from EOF.
        // See http://en.wikipedia.org/wiki/ID3
        if (dv.getString(3, dv.byteLength - 128) == 'TAG') {
            var title = dv.getString(30, dv.tell());
            var artist = dv.getString(30, dv.tell());
            var album = dv.getString(30, dv.tell());
            var year = dv.getString(4, dv.tell());
        } else {
            // no ID3v1 data found.
        }
    };

    reader.readAsArrayBuffer(this.files[0]);
};

Chrome和其他浏览器现已实施DataView(我只对Chrome感兴趣)。我很好奇,如果有人知道如何:

Chrome and other browsers have now implemented DataView (I'm interested only in Chrome). I'm curious if someone knows how to:


  1. 使用原生DataView读取标签

  2. 阅读id3 v2.4标签(包括APIC图像'coverart')

重点是我没有二进制文件的经验,完全没有不知道如何跳转到正确的标签位置,或者是什么小端和长端(或其他)。我只需要一个标签的示例 - 让我们说标题, TIT2 标签,我希望能帮助我理解如何跳到正确的位置并阅读其他标签标签还包括:

The point is that I have no experience with binary files, and totally don't know how to jump to the correct tag position, or what little endian and long endian (or whatever) are. I just need an example for one tag - let's say the title, the TIT2 tag, which I hope helps me to understand how to jump to the correct position and to read the other tags also:

function readID3() {
    //https://developer.mozilla.org/en-US/docs/Web/API/DataView
    //and the position
    //http://id3.org/id3v2.4.0-frames
    //var id3={};
    //id3.TIT2=new DataView(this.result,?offset?,?length?)

    /*
     ?
     var a=new DataView(this.result);
     console.dir(String.fromCharCode(a.getUint8(0)));
     ?
    */
}
function readFile() {
    var a = new FileReader();
    a.onload = readID3;
    a.readAsArrayBuffer(this.files[0]);
}
fileBox.addEventListener('change', readFile, false);

这是 JSFiddle

更新

http://jsfiddle.net/s492L/3/

我添加了 getString 所以我可以读取第一行并检查它是否包含ID3。
现在我需要找到第一个标签(TIT2)的位置和该字符串的变量长度&还要检查它是否是版本2.4。

I added getString so I can read the first line and check if it contains ID3. Now I need to find the position of the first tag (TIT2) and the 'variable' length of that string & also check if it's version 2.4.

//Header
//ID3v2/file identifier    "ID3"
//ID3v2 version            $04 00
//ID3v2 flags         (%ab000000 in v2.2, %abc00000 in v2.3, %abcd0000 in v2.4.x)
//ID3v2 size                 4 * %0xxxxxxx






可能的外部来源:


Possible external sources:

https://developer.mozilla.org/en-US / docs / Web / API / DataView

http://id3.org/id3v2.4.0-frames

http://id3.org/id3v2.4.0-structure

http://blog.nihilogic.dk/2008/08/reading-id3-tags -with-javascript.html

http://ericbidelman.tumblr.com/post/8343485440/reading-mp3-id3-tags-in -javascript

https ://github.com/aadsm/JavaScript-ID3-Reader

我现在正在使用PHP getid3 lib ...

I'm using the PHP getid3 lib at the moment...

http://getid3.sourceforge.net/

http:// getid3.sourceforge.net/source2/module.tag.id3v2.phps

推荐答案

使用我在这里找到的代码: http://www.ulduzsoft.com / 2012/07 / parsing-id3v2-tags-in-the-mp3-files / ,我把它翻译成Javascript: http://jsfiddle.net/eb7rrbw4/

Using the code I found here: http://www.ulduzsoft.com/2012/07/parsing-id3v2-tags-in-the-mp3-files/, I translated it into Javascript here: http://jsfiddle.net/eb7rrbw4/

以下是我写的代码那里:

Here is the code as I wrote it there:

DataView.prototype.getChar=function(start) {
    return String.fromCharCode(this.getUint8(start));
};
DataView.prototype.getString=function(start,length) {
    for(var i=0,v='';i<length;++i) {
        v+=this.getChar(start+i);
    }
    return v;
};
DataView.prototype.getInt=function(start) {
    return (this.getUint8(start) << 21) | (this.getUint8(start+1) << 14) | (this.getUint8(start+2) << 7) | this.getUint8(start+3);
};

function readID3(){
    var a=new DataView(this.result);
    // Parse it quickly
    if ( a.getString(0,3)!="ID3" )
    {
        return false;
    }

    // True if the tag is pre-V3 tag (shorter headers)
    var TagVersion = a.getUint8(3);

    // Check the version
    if ( TagVersion < 0 || TagVersion > 4 )
    {
        return false;
    }

    // Get the ID3 tag size and flags; see 3.1
    var tagsize = a.getInt(6)+10;
        //(a.getUint8(9) & 0xFF) | ((a.getUint8(8) & 0xFF) << 7 ) | ((a.getUint8(7) & 0xFF) << 14 ) | ((a.getUint8(6) & 0xFF) << 21 ) + 10;
    var uses_synch = (a.getUint8(5) & 0x80) != 0 ? true : false;
    var has_extended_hdr = (a.getUint8(5) & 0x40) != 0 ? true : false;

    var headersize=0;         
    // Read the extended header length and skip it
    if ( has_extended_hdr )
    {
        var headersize = a.getInt(10);
            //(a.getUint8(10) << 21) | (a.getUint8(11) << 14) | (a.getUint8(12) << 7) | a.getUint8(13); 
    }

    // Read the whole tag
    var buffer=new DataView(a.buffer.slice(10+headersize,tagsize));

    // Prepare to parse the tag
    var length = buffer.byteLength;

    // Recreate the tag if desynchronization is used inside; we need to replace 0xFF 0x00 with 0xFF
    if ( uses_synch )
    {
        var newpos = 0;
        var newbuffer = new DataView(new ArrayBuffer(tagsize));

        for ( var i = 0; i < tagsize; i++ )
        {
            if ( i < tagsize - 1 && (buffer.getUint8(i) & 0xFF) == 0xFF && buffer.getUint8(i+1) == 0 )
            {
                newbuffer.setUint8(newpos++,0xFF);
                i++;
                continue;
            }

            newbuffer.setUint8(newpos++,buffer.getUint8(i));                 
        }

        length = newpos;
        buffer = newbuffer;
    }

    // Set some params
    var pos = 0;
    var ID3FrameSize = TagVersion < 3 ? 6 : 10;
    var m_title;
    var m_artist;

    // Parse the tags
    while ( true )
    {
        var rembytes = length - pos;

        // Do we have the frame header?
        if ( rembytes < ID3FrameSize )
            break;

        // Is there a frame?
        if ( buffer.getChar(pos) < 'A' || buffer.getChar(pos) > 'Z' )
            break;

        // Frame name is 3 chars in pre-ID3v3 and 4 chars after
        var framename;
        var framesize;

        if ( TagVersion < 3 )
        {
            framename = buffer.getString(pos,3);
            framesize = ((buffer.getUint8(pos+5) & 0xFF) << 8 ) | ((buffer.getUint8(pos+4) & 0xFF) << 16 ) | ((buffer.getUint8(pos+3) & 0xFF) << 24 );
        }
        else
        {
            framename = buffer.getString(pos,4);
            framesize = buffer.getInt(pos+4);
                //(buffer.getUint8(pos+7) & 0xFF) | ((buffer.getUint8(pos+6) & 0xFF) << 8 ) | ((buffer.getUint8(pos+5) & 0xFF) << 16 ) | ((buffer.getUint8(pos+4) & 0xFF) << 24 );
        }

        if ( pos + framesize > length )
            break;

        if ( framename== "TPE1"  || framename== "TPE2"  || framename== "TPE3"  || framename== "TPE" )
        {
            if ( m_artist == null )
                m_artist = parseTextField( buffer, pos + ID3FrameSize, framesize );
        }

        if ( framename== "TIT2" || framename== "TIT" )
        {
            if ( m_title == null )
                m_title = parseTextField( buffer, pos + ID3FrameSize, framesize );
        }

        pos += framesize + ID3FrameSize;
        continue;
    }
    console.log(m_title,m_artist);
    return m_title != null || m_artist != null;
}

function parseTextField( buffer, pos, size )
{
    if ( size < 2 )
        return null;

    var charcode = buffer.getUint8(pos); 

    //TODO string decoding         
    /*if ( charcode == 0 )
        charset = Charset.forName( "ISO-8859-1" );
    else if ( charcode == 3 )
        charset = Charset.forName( "UTF-8" );
    else
        charset = Charset.forName( "UTF-16" );

    return charset.decode( ByteBuffer.wrap( buffer, pos + 1, size - 1) ).toString();*/
    return buffer.getString(pos+1,size-1);
}

您应该在控制台日志中看到标题和作者。但是,请查看解析文本函数,其中编码决定了读取字符串的方式。 (搜索TODO)。此外,我还没有使用扩展标头或uses_synch true或标签版本3进行测试。

You should see the title and author in the console log. Look at the parse text function, though, where the encoding determines the way to read the string. (search for TODO). Also I have not tested it with extended headers or uses_synch true or tag version 3.

这篇关于使用原生Chrome Javascript / FileReader / DataView读取id3 v2.4标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆