【问题标题】:time length of an mp3 filemp3文件的时间长度
【发布时间】:2010-09-12 06:36:08
【问题描述】:

不使用外部库,确定给定 mp3 文件长度(以秒为单位)的最简单方法是什么? (python源码高度赞赏)

【问题讨论】:

  • 在资源管理器中打开包含文件夹,调出播放时间栏、屏幕截图、ORC、文本搜索.... 提交给 The Daily WTF /joke

标签: python mp3 media duration


【解决方案1】:

只需使用mutagen

$pip install mutagen

在 python shell 中使用它:

from mutagen.mp3 import MP3
audio = MP3(file_path)
print audio.info.length

【讨论】:

  • 最佳答案。使用 PIP 轻松安装,没有其他要求,它只是提供存储在文件元数据中的信息
【解决方案2】:

简单,解析 MP3 二进制 blob 以计算某些东西,在 Python 中

这听起来是一个很高的要求。我不懂 Python,但这里有一些代码是我从我曾经尝试编写的另一个程序中重构出来的。

注意:它是用 C++ 编写的(抱歉,这是我所拥有的)。此外,它只处理恒定比特率的 MPEG 1 Audio Layer 3 文件。 应该涵盖大部分内容,但我不能保证它在所有情况下都能正常工作。希望这能满足您的需求,并希望将其重构为 Python 比从头开始更容易。

// determines the duration, in seconds, of an MP3;
// assumes MPEG 1 (not 2 or 2.5) Audio Layer 3 (not 1 or 2)
// constant bit rate (not variable)

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

//Bitrates, assuming MPEG 1 Audio Layer 3
const int bitrates[16] = {
         0,  32000,  40000,  48000,  56000,  64000,  80000,   96000,
    112000, 128000, 160000, 192000, 224000, 256000, 320000,       0
  };


//Intel processors are little-endian;
//search Google or see: http://en.wikipedia.org/wiki/Endian
int reverse(int i)
{
    int toReturn = 0;
    toReturn |= ((i & 0x000000FF) << 24);
    toReturn |= ((i & 0x0000FF00) << 8);
    toReturn |= ((i & 0x00FF0000) >> 8);
    toReturn |= ((i & 0xFF000000) >> 24);
    return toReturn;
}

//In short, data in ID3v2 tags are stored as
//"syncsafe integers". This is so the tag info
//isn't mistaken for audio data, and attempted to
//be "played". For more info, have fun Googling it.
int syncsafe(int i)
{
 int toReturn = 0;
 toReturn |= ((i & 0x7F000000) >> 24);
 toReturn |= ((i & 0x007F0000) >>  9);
 toReturn |= ((i & 0x00007F00) <<  6);
 toReturn |= ((i & 0x0000007F) << 21);
 return toReturn;     
}

//How much room does ID3 version 1 tag info
//take up at the end of this file (if any)?
int id3v1size(ifstream& infile)
{
   streampos savePos = infile.tellg(); 

   //get to 128 bytes from file end
   infile.seekg(0, ios::end);
   streampos length = infile.tellg() - (streampos)128;
   infile.seekg(length);

   int size;
   char buffer[3] = {0};
   infile.read(buffer, 3);
   if( buffer[0] == 'T' && buffer[1] == 'A' && buffer[2] == 'G' )
     size = 128; //found tag data
   else
     size = 0; //nothing there

   infile.seekg(savePos);

   return size;

}

//how much room does ID3 version 2 tag info
//take up at the beginning of this file (if any)
int id3v2size(ifstream& infile)
{
   streampos savePos = infile.tellg(); 
   infile.seekg(0, ios::beg);

   char buffer[6] = {0};
   infile.read(buffer, 6);
   if( buffer[0] != 'I' || buffer[1] != 'D' || buffer[2] != '3' )
   {   
       //no tag data
       infile.seekg(savePos);
       return 0;
   }

   int size = 0;
   infile.read(reinterpret_cast<char*>(&size), sizeof(size));
   size = syncsafe(size);

   infile.seekg(savePos);
   //"size" doesn't include the 10 byte ID3v2 header
   return size + 10;
}

int main(int argCount, char* argValues[])
{
  //you'll have to change this
  ifstream infile("C:/Music/Bush - Comedown.mp3", ios::binary);

  if(!infile.is_open())
  {
   infile.close();
   cout << "Error opening file" << endl;
   system("PAUSE");
   return 0;
  }

  //determine beginning and end of primary frame data (not ID3 tags)
  infile.seekg(0, ios::end);
  streampos dataEnd = infile.tellg();

  infile.seekg(0, ios::beg);
  streampos dataBegin = 0;

  dataEnd -= id3v1size(infile);
  dataBegin += id3v2size(infile);

  infile.seekg(dataBegin,ios::beg);

  //determine bitrate based on header for first frame of audio data
  int headerBytes = 0;
  infile.read(reinterpret_cast<char*>(&headerBytes),sizeof(headerBytes));

  headerBytes = reverse(headerBytes);
  int bitrate = bitrates[(int)((headerBytes >> 12) & 0xF)];

  //calculate duration, in seconds
  int duration = (dataEnd - dataBegin)/(bitrate/8);

  infile.close();

  //print duration in minutes : seconds
  cout << duration/60 << ":" << duration%60 << endl;

  system("PAUSE");
  return 0;
}

【讨论】:

  • 这非常适合我现在正在构建的东西,因为我不需要 VBR 支持。我需要更改的只是比特率,因为当文件为 32k(从 LAME 输出)时,它假设为 56k。
【解决方案3】:

还可以看看 audioread(包括 ubuntu 在内的一些 linux 发行版有软件包),https://github.com/sampsyo/audioread

audio = audioread.audio_open('/path/to/mp3')
print audio.channels, audio.samplerate, audio.duration

【讨论】:

    【解决方案4】:

    为了谷歌追随者,这里还有一些外部库:

    mpg321 -t

    ffmpeg -i

    midentify(基本上是mplayer)见Using mplayer to determine length of audio/video file

    mencoder(传递给它无效的参数,它会吐出一条错误消息,但也会为您提供有关文件的信息,例如 $ mencoder inputfile.mp3 -o fake)

    媒体资讯节目http://mediainfo.sourceforge.net/en

    exiftool

    linux“文件”命令

    mp3信息

    母狗

    参考: https://superuser.com/questions/36871/linux-command-line-utility-to-determine-mp3-bitrate

    http://www.ruby-forum.com/topic/139468

    mp3 length in milliseconds

    (使其成为供其他人添加的 wiki)。

    和库:.net:naudio,java:jlayer,c:libmad

    干杯!

    【讨论】:

    • 这些 ffmpeg 和 mpg321 也将 http 链接作为文件位置处理,不幸的是后者会自动播放文件,但我对 ffmpeg 非常满意 :)
    【解决方案5】:

    您可以使用pymad。它是一个外部库,但不要落入 Not Invented Here 陷阱。您不想要任何外部库的任何特殊原因?

    import mad
    
    mf = mad.MadFile("foo.mp3")
    track_length_in_milliseconds = mf.total_time()    
    

    发现here

    --

    如果您真的不想使用外部库,请查看 here 并了解他是如何做到的。警告:这很复杂。

    【讨论】:

    • 我同意推荐外部库。我没有使用过它(或者 Python)。但是我曾经尝试用 C++ 编写一个可以简单地播放 MP3 的程序。这并没有成功,但我确实走得足够远来确定文件的持续时间。我考虑将代码重构为 ...
    • ... 在这里发帖,但它非常复杂。 (在 C++ 中,而不是 Python 中)。甚至一点都不简单。
    • 请注意,在我看来它只适用于某些平台。最新版本在安装时崩溃,因为它缺少自己的安装文件之一,它建议我通过运行包含 linux 命令的第二个文件来生成该文件。
    【解决方案6】:

    您可以计算文件中的帧数。每个帧都有一个起始码,虽然我不记得起始码的确切值,而且我没有 MPEG 规范。每帧都有一定的长度,MPEG1 layer II 大约为 40ms。

    这种方法适用于 CBR 文件(恒定比特率),而 VBR 文件的工作方式则完全不同。

    来自以下文档:

    对于第 I 层文件我们这个公式:

    FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4

    对于第 II 层和第 III 层文件,请使用以下公式:

    FrameLengthInBytes = 144 * 比特率 / 采样率 + 填充

    Information about MPEG Audio Frame Header

    【讨论】:

    • 我相信长度是26ms。
    猜你喜欢
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    • 2016-05-19
    相关资源
    最近更新 更多