获取 .wav 文件长度或时长

75 投票
12 回答
141573 浏览
提问于 2025-04-17 04:41

我想知道怎么在Python中获取一个音频文件(.wav格式)的时长。到目前为止,我查看了Python的wave库、mutagenpymediapymad,但是都没能成功获取到wav文件的时长。Pymad虽然给了我时长,但结果不太稳定。

12 个回答

39

一个非常简单的方法是使用 soundfile(之前叫 pysoundfile)。

下面是一些示例代码,教你怎么做:

import soundfile as sf
f = sf.SoundFile('447c040d.wav')
print('samples = {}'.format(f.frames))
print('sample rate = {}'.format(f.samplerate))
print('seconds = {}'.format(f.frames / f.samplerate))

对于那个特定的文件,输出结果是:

samples = 232569
sample rate = 16000
seconds = 14.5355625

这和 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
65

librosa这个库可以做到这一点:librosa

import librosa
librosa.get_duration(filename='my.wav')
89

时长等于帧数除以帧率(每秒帧数):

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)

关于@edwards的评论,这里有一些代码可以生成一个双声道的波形文件:

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()

如果你在音频播放器中播放生成的文件,你会发现它的时长是40秒。如果你运行上面的代码,它也会计算出时长是40秒。所以我认为帧数不受声道数量的影响,上面的公式是正确的。

撰写回答