【问题标题】:Reading Remote MP3 File's ID3 Tags using Java使用 Java 读取远程 MP3 文件的 ID3 标签
【发布时间】:2011-05-02 14:30:52
【问题描述】:

我正在寻找一种方法来从远程服务器上的 MP3 文件中读取 ID3 标签,而无需实际下载文件。我见过像 JAudioTagger 和 Entagged 这样的库,但它们似乎都需要一个文件对象而不是 URL 或 InputStream,我知道如何获取远程文件。是否有另一个图书馆可以做到这一点?或者有没有办法让正确的对象使用 URL 与这些类进行交互?

【问题讨论】:

    标签: java stream mp3 id3


    【解决方案1】:
        String tmp="";
        int bytes_read;
    
        try{
            //RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/Music/6 am (reggaeton).mp3", "r");
            RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/Music/Jorge Vercilo - Final feliz.mp3", "r");
    
            long fsize=file.length();
            System.out.println("Abriu arquivo");
            byte[] buf = new byte[1024];
            bytes_read = file.read(buf, 0, 10);
            System.out.println("Leu "+String.valueOf(bytes_read));
            if(bytes_read==10){
                if(buf[0] == 'I' &&buf[1] == 'D' && buf[2] == '3') {
                    System.out.println("É ID3");
                    int version = (buf[4]<<8) + (buf[3] & 0xff);
                    System.out.println("Versão: "+String.valueOf(version));
                    if(buf[5] == 0x00) System.out.println("Clear flags");
                    long size = ((buf[9] & 0xFF) <<  0) |
                                ((buf[8] & 0xFF) <<  8) |
                                ((buf[7] & 0xFF) << 16) |
                                ((buf[6] & 0xFF) << 24);
                    System.out.println("Size: "+String.valueOf(size));
    
                    long p = 10;
                    long frame_size;
                    String encoding="";
                    while(p<fsize){
                        file.seek(p);
                        bytes_read = file.read(buf, 0, 10);
                        if(bytes_read==10){
                            frame_size = ((buf[7] & 0xFF) <<  0) |
                                ((buf[6] & 0xFF) <<  8) |
                                ((buf[5] & 0xFF) << 16) |
                                ((buf[4] & 0xFF) << 24);
                            System.out.println("Frame size: "+String.valueOf(frame_size));
                            tmp = new String(buf,0,4);
                            System.out.println("Frame type: "+tmp);
    
                            if(buf[0] == 'T' && buf[1] == 'P' && buf[2] == 'E' && buf[3] == '1') {// artist
                                p+=10;
                                file.seek(p);
                                if(file.read(buf, 0, (int)frame_size)==frame_size){
                                    if(buf[0]==0x01) encoding="UTF-16";
                                    else if(buf[0]==0x02) encoding="UTF-16BE";
                                    else if(buf[0]==0x03) encoding="UTF-8";
                                    if(buf[0]==0x00) tmp = new String(buf,1,(int)frame_size-1);
                                    else tmp = new String(buf,1,(int)frame_size-1,encoding);
                                    System.out.println("Artist: "+tmp);
                                }
                                p+=frame_size;
                            }
                            else if(buf[0] == 'T' && buf[1] == 'I' && buf[2] == 'T' && buf[3] == '2') {// title
                                p+=10;
                                file.seek(p);
                                if(file.read(buf, 0, (int)frame_size)==frame_size){
                                    if(buf[0]==0x01) encoding="UTF-16";
                                    else if(buf[0]==0x02) encoding="UTF-16BE";
                                    else if(buf[0]==0x03) encoding="UTF-8";
                                    if(buf[0]==0x00) tmp = new String(buf,1,(int)frame_size-1);
                                    else tmp = new String(buf,1,(int)frame_size-1,encoding);
                                    System.out.println("title: "+tmp);
                                }
                                p+=frame_size;
                            }
                            else if(buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x00 && buf[3] == 0x00) {// END OF HEADER
                                break;
                            }
                            else p+= frame_size+10;
                        }
                        //checar se ja pegou o title e o artist
                    }
                }
            }
    
            if(file!=null)  file.close();
        }catch(Exception e){
            System.out.println("ERROOOOOOOOO!");
            e.printStackTrace();
        }   
    

    【讨论】:

      【解决方案2】:

      本页介绍如何获取 ID3 V。 1 MP3 文件的标签。 http://willcode4beer.com/parsing.jsp?set=mp3ID3

      它提供了一个..

      public Tag readTag(InputStream in, long start) throws ..
      

      .. 远程 URL 所需的方法。基本思想是获取一个 URLConnection 并查询它以获取 MP3 中数据的长度,然后从该数字中减去 128 并将其用作开始参数(否则它将非常慢) .

      【讨论】:

      • 我最终使用了此代码的改编版来实现我想要的。我首先打开了一个 URLConnection 来获取文件的长度。然后我打开另一个 URLConnection 并将 setRequestProperty 的范围设置为 size-128。这最终比从 URLConnection 打开 InputStream 然后跳过 size-128 快得多。
      【解决方案3】:

      ID3 标签位于文件的最后 128(如果使用扩展标签,则为 355)字节,因此您至少必须下载文件的一部分。由于 HTTP 支持特定范围的文件访问,因此理论上应该可以做到这一点(尽管我不知道有任何库可以为您做到这一点)。

      基本上需要做的是执行 HEAD 请求以获取文件长度(以字节为单位),然后对范围为 length-355 的文件执行 GET 到文件末尾。这将返回必要的元数据。 This 很好地了解了远程请求的外观。

      很抱歉,虽然我不知道有任何库会自动执行此操作,但设置 getter 并不是一项特别困难的任务。从那里可以将元数据写入临时文件并由您的 ID3 解析器解析。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-01
        • 2011-09-12
        • 1970-01-01
        • 2011-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多