【问题标题】:How to retrieve duration of MP3 in .NET?如何在 .NET 中检索 MP3 的持续时间?
【发布时间】:2010-09-27 20:15:44
【问题描述】:

我已经构建了一个 WPF 应用程序,用户可以在其中将 MP3 文件拖放到列表框上。我需要一种方法来计算播放列表的总时长。

我应该使用哪些库?或者是否可以只使用 .NET 框架?

【问题讨论】:

标签: .net audio mp3


【解决方案1】:

几年前,我最终为此编写了自己的文章。您可以使用闪存编写一个有效的客户端。我记得的关键点是:

  1. 你不能依赖 MP3 标题来准确,所以不要只阅读它来获得持续时间
  2. 在闪存中,寻找到 MP3 的末尾,然后读取当前位置。这将为您提供持续时间。

编辑:我知道你想用 .Net 来做这件事,但实际上在你将文件上传到服务器之前了解客户端可能更有用,就好像你想对文件长度施加限制一样,你可以这样做在这个过程的早期阶段。

【讨论】:

  • flash 的提示将来会派上用场,因为我过去不得不处理它,我确实遇到了错误的持续时间读数,这会弄乱洗涤器。谢谢!
【解决方案2】:

[我自己的解决方案]

我添加了第二个 mediaelement 控件,用于打开列表框中的每个 mp3 文件并获取它的 NaturalDuration。打开和关闭列表中的每个文件并对所有值求和。

正如其他人所说,mp3 标题不准确。 mediaelement 提供了正确的持续时间。

这可能不是最快的方法,但在我的例子中是最简单的(它不依赖于其他库)。

【讨论】:

    【解决方案3】:

    我包装了 mp3 解码器库,并将其提供给 .net 开发人员。你可以在这里找到它:

    http://sourceforge.net/projects/mpg123net/

    包括将 mp3 文件转换为 PCM 和读取 ID3 标签的示例。

    我猜它可以用来正确计算 mp3 文件的时长。

    【讨论】:

      【解决方案4】:

      经过大量的理论研究,我找到了一种正确且无可争议地计算 mp3 文件时长的方法。

      让我首先重申一下为什么上面的标准方法不起作用:

      ID3 方法:并非所有文件都有 id3 标签,如果有,可能没有设置时长字段。

      通过读取一帧 * 文件大小进行估计:不适用于 VBR 文件。

      Xing 标头:并非所有文件都有它。

      解码并通过 PCM 大小确定:我有 3 GB 以上的文件,我不会等到它解码。

      我到处阅读,一切都指向 NAudio。马克,感谢您的努力和干净的来源!然而,NAudio 最常用的一种方法是使用 Mp3FileReader 读取文件并获取所有帧。问题:Mp3FileReader 在开始时会创建一个 TOC,这需要很长时间,即使对于只有一天的小文件也是如此 :)

      Mark 建议我删除 TOC 创建,因为源可用,并且在执行此操作时,我发现了更简单的方法。这里是;不言自明:

          double GetMediaDuration(string MediaFilename)
          {
              double duration = 0.0;
              using (FileStream fs = File.OpenRead(MediaFilename))
              {
                  Mp3Frame frame = Mp3Frame.LoadFromStream(fs);
                  if (frame != null)
                  {
                      _sampleFrequency = (uint)frame.SampleRate;
                  }
                  while (frame != null)
                  {
                      if (frame.ChannelMode == ChannelMode.Mono)
                      {
                          duration += (double)frame.SampleCount * 2.0 / (double)frame.SampleRate;
                      }
                      else
                      {
                          duration += (double)frame.SampleCount * 4.0 / (double)frame.SampleRate;
                      }
                      frame = Mp3Frame.LoadFromStream(fs);
                  }
              }
              return duration;
          }
      

      【讨论】:

      • 顺便说一句,它在不到一分钟的时间内计算了 9 天 18 小时长的文件的确切持续时间(实际上它会尽可能快地读取文件,因为它使用非常少CPU)。
      • 在我的例子中,计算出的持续时间是我正在使用的所有文件的实际持续时间的四倍(顺便说一句,它们都是立体声文件)。自从这个答案以来,NAudio 中可能发生了一些变化,但我不确定 * 4.0 是否必要,至少在我正在测试的文件的情况下。不过,我很感激这个答案,它让我成功了 99%。
      • @JaredPhelps 你只做了几分钟的实验,然后就离开了 :)
      • 我认为@JaredPhelps 是正确的,不需要将 SampleCount 乘以 2 或 4。至少对于我测试的文件,当我删除它时,持续时间是正确的。
      • 嗨@DanielMošmondor我可以知道“_sampleFrequency”的类型它给我一个错误。
      猜你喜欢
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-03
      • 2013-05-12
      相关资源
      最近更新 更多