我正在尋找一種方法來查找在Python中的音頻文件(.wav)的持續時間。到目前爲止,我看了一下python wave
庫,mutagen
,pymedia
,pymad
我無法獲得wav文件的持續時間。 Pymad
給了我持續時間,但它不一致。獲取.wav文件的長度或短語
在此先感謝。
我正在尋找一種方法來查找在Python中的音頻文件(.wav)的持續時間。到目前爲止,我看了一下python wave
庫,mutagen
,pymedia
,pymad
我無法獲得wav文件的持續時間。 Pymad
給了我持續時間,但它不一致。獲取.wav文件的長度或短語
在此先感謝。
的持續時間等於由幀率除以幀的數量(幀每秒):
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'評論,這裏是一些代碼,以產生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()
如果您在音頻播放器中播放結果文件,則會發現持續時間爲40秒。如果你運行上面的代碼,它也會計算持續時間爲40秒。所以我相信幀的數量不受通道數量的影響,上面的公式是正確的。
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()
一個更安全的方法來處理沒有byteRate循環的文件的二進制內容可能是: from struct import unpack_from rate,= unpack_from('
小錯誤:'os.path.getsize路徑)'應該是'os.path.getsize(f)'。 – Lewistrick
另一個小錯誤:'ms =((fileSize-44)* 1000)/ byteRate'但是這很好,因爲即使你的WAV不是PCM,它也能工作。 – Jamie
我們可以使用ffmpeg來獲取任何視頻或音頻文件的持續時間。
要安裝的ffmpeg按照這個link
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']
我得到這個錯誤「不能在類似字節的對象上使用字符串模式」。所以我用「stdout.decode()」替換了「stdout」的調用 – AvielNiego
一個非常簡單的方法是使用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))
輸出對於那個特定的文件是:
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
我看了一下所有的'wave'庫函數,但我忽略了簡單的邏輯'將爲nframes/frame_rate'。謝謝你的方法和代碼:) – Pannu
這是不完全正確的...有一個幀寫入每個通道,所以'duration = frames/float(rate * f.getnchannels())' – edward
@edward :我已經添加了一些代碼,創建一個2通道波形文件。在我的答案中發佈的公式計算出的持續時間爲40秒,這與我在播放.wav文件時看到的一致。所以在我看來,使用雙聲道時幀數不會增加一倍,而且我的原始公式是正確的。 – unutbu