获取.wav文件长度或持续时间

Pan*_*nnu 28 python audio

我正在寻找一种方法来找出python中音频文件(.wav)的持续时间.到目前为止,我看了一下蟒蛇wavemutagen,pymedia,pymad我没能得到wav文件的时间.Pymad给了我持续时间,但不一致.

提前致谢.

unu*_*tbu 45

持续时间等于帧数除以帧速率(每秒帧数):

import wave
import contextlib
fname = '/tmp/test.wav'
with contextlib.closing(wave.open(fname,'r')) as f:
    frames = f.getnframes()
    rate = f.getframerate()
    duration = frames / float(rate)
    print(duration)
Run Code Online (Sandbox Code Playgroud)

关于@edwards的评论,这里有一些产生2通道波形文件的代码:

import math
import wave
import struct
FILENAME = "/tmp/test.wav"
freq = 440.0
data_size = 40000
frate = 1000.0
amp = 64000.0
nchannels = 2
sampwidth = 2
framerate = int(frate)
nframes = data_size
comptype = "NONE"
compname = "not compressed"
data = [(math.sin(2 * math.pi * freq * (x / frate)),
        math.cos(2 * math.pi * freq * (x / frate))) for x in range(data_size)]
try:
    wav_file = wave.open(FILENAME, 'w')
    wav_file.setparams(
        (nchannels, sampwidth, framerate, nframes, comptype, compname))
    for values in data:
        for v in values:
            wav_file.writeframes(struct.pack('h', int(v * amp / 2)))
finally:
    wav_file.close()
Run Code Online (Sandbox Code Playgroud)

如果您在音频播放器中播放结果文件,您将发现持续时间为40秒.如果您运行上面的代码,它还会将持续时间计算为40秒.所以我认为帧数不受通道数量的影响,上面的公式是正确的.

  • @Lewistrick:我看到`wave.open`在[修订版84932](http://hg.python.org/cpython/rev/8327780d3841)中支持`with`语句.这种变化会影响Python3.4,但不会影响Python2.7.据我所知,[2.7分支](http://hg.python.org/cpython/file/ae9fb85ab4e0/Lib/wave.py#l95)不支持`with`语句. (4认同)
  • 这不太正确......每个通道都有一个框架,所以`duration = frames/float(rate*f.getnchannels())` (2认同)
  • 不再需要contextlib的东西.从版本2.7开始,`with`语句就是为你做的. (2认同)
  • 抱歉,是我的错.这是关于`open`,而不是`wave.open`. (2认同)

Dav*_*e C 11

一个非常简单的方法是使用pysoundfile,https://github.com/bastibe/PySoundFile

以下是如何执行此操作的示例代码:

import soundfile as sf
f = sf.SoundFile('447c040d.wav')
print('samples = {}'.format(len(f)))
print('sample rate = {}'.format(f.samplerate))
print('seconds = {}'.format(len(f) / f.samplerate))
Run Code Online (Sandbox Code Playgroud)

该特定文件的输出是:

samples = 232569
sample rate = 16000
seconds = 14.5355625
Run Code Online (Sandbox Code Playgroud)

这与soxi一致:

Input File     : '447c040d.wav'
Channels       : 1
Sample Rate    : 16000
Precision      : 16-bit
Duration       : 00:00:14.54 = 232569 samples ~ 1090.17 CDDA sectors
File Size      : 465k
Bit Rate       : 256k
Sample Encoding: 16-bit Signed Integer PCM
Run Code Online (Sandbox Code Playgroud)

  • 是的。它确实依赖于第 3 方库,但第 3 方库是著名 C 库 libsndfile 的简单包装。pysoundfile 与 numpy 集成。赢,赢,赢。 (3认同)
  • 对我来说,这确实是最好的答案,因为它消除了上述答案的很多复杂性.保持简单! (2认同)

小智 9

我们可以使用ffmpeg来获取任何视频或音频文件的持续时间.

要安装ffmpeg,请点击此链接

import subprocess
import re

process = subprocess.Popen(['ffmpeg',  '-i', path_of_wav_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = process.communicate()
matches = re.search(r"Duration:\s{1}(?P<hours>\d+?):(?P<minutes>\d+?):(?P<seconds>\d+\.\d+?),", stdout, re.DOTALL).groupdict()

print(matches['hours'])
print(matches['minutes'])
print(matches['seconds'])
Run Code Online (Sandbox Code Playgroud)

  • 我收到此错误“无法在类似字节的对象上使用字符串模式”。所以我用“stdout.decode()”替换了对“stdout”的调用 (2认同)

小智 7

import os
path="c:\\windows\\system32\\loopymusic.wav"
f=open(path,"r")

#read the ByteRate field from file (see the Microsoft RIFF WAVE file format)
#https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
#ByteRate is located at the first 28th byte
f.seek(28)
a=f.read(4)

#convert string a into integer/longint value
#a is little endian, so proper conversion is required
byteRate=0
for i in range(4):
    byteRate=byteRate + ord(a[i])*pow(256,i)

#get the file size in bytes
fileSize=os.path.getsize(path)  

#the duration of the data, in milliseconds, is given by
ms=((fileSize-44)*1000)/byteRate

print "File duration in miliseconds : " % ms
print "File duration in H,M,S,mS : " % ms/(3600*1000) % "," % ms/(60*1000) % "," % ms/1000 % "," ms%1000
print "Actual sound data (in bytes) : " % fileSize-44  
f.close()
Run Code Online (Sandbox Code Playgroud)


Raj*_*aju 6

让,T 是 2 个连续样本之间的持续时间。因此,我们可以写成 t = nT 或 t = n/Fs。

from scipy.io import wavfile
Fs, data = wavfile.read('filename.wav')
n = data.size
t = n / Fs
Run Code Online (Sandbox Code Playgroud)


Aad*_*Ura 6

我试图获取“.wav”以外的不同格式的音频文件的长度,我尝试了上面的一些解决方案,但对我不起作用

这对我有用:

from pydub.utils import mediainfo
mediainfo('audiofile')['duration']
Run Code Online (Sandbox Code Playgroud)


小智 5

librosa库可以做到这一点:librosa

import librosa
librosa.get_duration(filename='my.wav')
Run Code Online (Sandbox Code Playgroud)

  • 简洁的!它给出了“第二个”度量(浮动)。谢谢。 (2认同)
  • 请注意,这可以避免将内容加载到内存中,因此对于查询长文件的持续时间很有用。(引自 librosa) (2认同)