【问题标题】:Java/JAudiotagger: Mp3 wrong ID3 tag sizeJava/JAudiotagger:Mp3 错误 ID3 标签大小
【发布时间】:2012-10-02 05:30:23
【问题描述】:

我正在使用JAudiotagger 库构建一个mp3 标记应用程序。我的应用程序可以很好地读取 mp3 元数据,并且也可以很好地写入元数据,除了艺术品。所以我的问题如下:

当我在 mp3 文件中添加一些艺术作品并保存时,文件变得越来越大,这是有道理的。 但是当我删除一件或所有艺术品时,文件大小并没有变小

实际问题在于我的 mp3 文件的 ID3v2 标签。当我移除艺术品时,它实际上是从标签中移除的,但标签大小本身并没有缩小。

我在删除艺术品时使用的方法是这样的:

    // Get the artworkList from the parentFrame.
    List<Artwork> list = parentFrame.getArtworkList();

    // Get the tag from the parentFrame's mp3File.
    AbstractID3v2Tag tag = parentFrame.getTag();

   // Get the index of the artwork the user is currently looking at (and
   // wants to delete too).
   int visibleArtworkIndex = parentFrame.getVisibleArtworkIndex();

   // Remove it from the list.
   list.remove(visibleArtworkIndex);

   // Update the parentFrame's copy of the artworkList.
   parentFrame.setArtworkList(list);

   // Update the tag (delete its whole artwork field).
   tag.deleteArtworkField();

   // If the list has more artworks left, add them to the tag.
   if (!list.isEmpty()) {
       Iterator<Artwork> iterator = list.iterator();
       while (iterator.hasNext()) {
           try {
               tag.addField(iterator.next());
           } catch (FieldDataInvalidException e1) {
               e1.printStackTrace();
           }
       }
   }

,它实际上从列表中删除了一个艺术作品,然后通过删除所有艺术作品并从更新的列表中重新复制它们来更新标签本身。

我对解决方案的尝试是:

  • 从更新的旧标签创建新标签(调用tag.deleteArtworkField()后),然后将艺术品添加到新标签,但新标签的大小与旧标签相同。

  • 在保存前使用tag.adjustPadding(File fileToBeTrimmed, int sizeToStoreTagBeforeAudioInBytes, long audioStartByte) 修剪mp3 文件,这会调整MP3 文件开头的填充长度。
    这里的问题是我只知道错误的标签大小而不是正确的标签大小,所以我无法正确修剪 mp3 并最终丢失音频数据。

为了更好地说明问题,我添加了一些图片:

之前的mp3文件:

移除一幅作品后的 mp3 文件。请注意,尽管艺术品较少,但标签仍保持其先前的大小:

文件应该是怎样的:

我希望任何人有任何想法。提前致谢。

【问题讨论】:

    标签: java mp3 id3 id3-tag id3v2


    【解决方案1】:

    今天已修复。

    默认情况下,当您缩小元数据时,jaudiotagger 不会回收空间,但现在如果您设置了

    TagOptionSingleton.getInstance().setId3v2PaddingWillShorten(true);
    

    在保存更改之前,它将回收不必要的填充以尽可能减小文件大小。

    【讨论】:

      【解决方案2】:

      方法

      TagOptionSingleton.getInstance().setId3v2PaddingWillShorten(true);
      TagOptionSingleton.getInstance().setOriginalSavedAfterAdjustingID3v2Padding(true);
      

      似乎没有完全实施(截至 2018 年 1 月)。例如检查http://www.jthink.net/jaudiotagger/maven/apidocs/org/jaudiotagger/tag/mp4/Mp4TagCreator.html 查看 Mp4TagCreator 类在将元数据转换为原始数据时没有实现填充:

      padding - 当前忽略的 TODO 填充参数

      对于 mp3 文件,我有一个解决方法,使用库 mp3agic https://github.com/mpatric/mp3agic。与上次更新于 2015 年的 jaudiotagger 不同,它仍在更新。在android上你需要使用0.9.0版本,因为0.9.1使用java.nio.file-classes,android不支持,https://github.com/mpatric/mp3agic/issues/141

      解决方法是简单地创建一个新标签并复制标签数据,然后将其写入一个新文件。如果成功,将旧文件替换为新文件。如果不复制封面图像,新文件将比原始文件小。我相信 jaudiotagger 也应该可以做到这一点,但没能做到。以下是 mp3agic 的用法:

                              try {
                              Mp3File song = new Mp3File(location,false);
      
                              if (song.hasId3v2Tag()){
                                  ID3v2 oritag=song.getId3v2Tag();
                                  byte[] image=oritag.getAlbumImage();
                                  if(image!=null){
                                      if (image.length > 10) {
                                          song = new Mp3File(location, true);
                                          oritag=song.getId3v2Tag();
                                          ID3v24Tag newtag = new ID3v24Tag();
      
                                          // copy metadata
      
                                          newtag.setArtist(oritag.getArtist());
                                          newtag.setArtistUrl(oritag.getArtistUrl());
                                          newtag.setOriginalArtist(oritag.getOriginalArtist());
                                          newtag.setArtistUrl(oritag.getArtistUrl());
      
                                          newtag.setAlbum(oritag.getAlbum());
                                          newtag.setAlbumArtist(oritag.getAlbumArtist());
      
                                          newtag.setAudiofileUrl(oritag.getAudiofileUrl());
                                          newtag.setAudioSourceUrl(oritag.getAudioSourceUrl());
                                          newtag.setUrl(oritag.getUrl());
      
                                          newtag.setGenre(oritag.getGenre());
                                          newtag.setGrouping(oritag.getGrouping());
      
                                          newtag.setTitle(oritag.getTitle());
                                          newtag.setTrack(oritag.getTrack());
      
                                          newtag.setPublisher(oritag.getPublisher());
                                          newtag.setPublisherUrl(oritag.getPublisherUrl());
                                          newtag.setCopyright(oritag.getCopyright());
                                          newtag.setCopyrightUrl(oritag.getCopyrightUrl());
                                          newtag.setComposer(oritag.getComposer());
                                          newtag.setCommercialUrl(oritag.getCommercialUrl());
                                          newtag.setComment(oritag.getComment());
                                          newtag.setYear(oritag.getYear());
                                          newtag.setKey(oritag.getKey());
                                          newtag.setRadiostationUrl(oritag.getRadiostationUrl());
                                          newtag.setPaymentUrl(oritag.getPaymentUrl());
      
                                          song.setId3v2Tag(newtag);
      
      
                                          try {
                                              song.save(location + "intermed");
      
                                              File from = new File(location + "intermed");
      // if successfull then replace old file with new file
                                              if(from.exists()) {
                                                  File file = new File(location);
                                                  long sizeold = file.length();
                                                  file.delete();
                                                  File to = new File(location);
                                                  long sizenew = from.length();
                                                  from.renameTo(to);
                                                  freedspace += sizeold - sizenew;
                                                  }
      
                                          } catch (IOException | NotSupportedException e) {
                                              e.printStackTrace();
      
                                          }
                                      }
                                  }
                              }
      
                          } catch (IOException | UnsupportedTagException | InvalidDataException e) {
                              e.printStackTrace();
                          }
      

      备注:我在我的 AudioCleanup-App https://play.google.com/store/apps/details?id=com.gluege.audiocleanup&hl=en 中实现了这个,它适用于 mp3 文件。我没有设法删除其他文件类型的专辑封面。如果有人有解决方案,请分享。

      我不喜欢 Id3 标准,尤其是填充。这是对智能手机宝贵空间的浪费。我看过专辑中每首歌都包含相同的 1MB 封面图片。

      【讨论】:

        【解决方案3】:

        这实际上是预期的行为,这是一种优化。

        当你给ID3v2标签添加数据而空间不足时,需要重写整个文件以腾出足够的空间。当您删除数据时,ID3v2 只是更新为包含数据,未使用的空间只是简单地标记为空闲(当您再次添加更多数据时,它会被回收)。

        在您的库中查找“释放标签中未使用的空间”调用。您需要明确告诉它应该释放可用空间。

        编辑:查看 Javadoc,我相信您需要在处理文件之前设置此选项:

        TagOptionSingleton.getInstance().setId3v2PaddingWillShorten(true);
        

        【讨论】:

        • 我已经尝试过你的建议 Durandal 但不幸的是它没有奏效。也许这是一个api错误。我会继续努力。
        • 我也尝试了TagOptionSingleton 的其他选项,但无济于事。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-19
        • 2015-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多