I'm looking for a way to find out the duration of a audio file (.wav) in python. So far i had a look at python wave
library, mutagen
, pymedia
, pymad
i was not able to get the duration of the wav file. Pymad
gave me the duration but its not consistent.
10 Answers
The duration is equal to the number of frames divided by the framerate (frames per second):
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)
Regarding @edwards' comment, here is some code to produce a 2-channel wave file:
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()
If you play the resultant file in an audio player, you'll find that is 40 seconds in duration. If you run the code above it also computes the duration to be 40 seconds. So I believe the number of frames is not influenced by the number of channels and the formula above is correct.
-
I had a look at all the `wave` library function but i overlooked simple logic `nframes/frame_rate`. Thank you for both the method and the code :) – Pannu Oct 20 '11 at 09:48
-
4This is not quite correct ... there is a frame written for each channel, and so `duration=frames/float(rate*f.getnchannels())` – edward Sep 24 '13 at 22:18
-
1@edward: I've added some code above which creates a 2-channel wave file. The formula posted in my answer computes the duration to be 40s, which jibes with what I see when I play the .wav file. So it appears to me that the number of frames does not double when you use 2-channels, and my original formula is correct. – unutbu Sep 25 '13 at 01:21
-
3The contextlib stuff is not needed any more. From version 2.7 on, the `with` statement does that for you. – Lewistrick Dec 04 '13 at 11:17
-
6@Lewistrick: I see `wave.open` supports the `with` statement as of [revision 84932](http://hg.python.org/cpython/rev/8327780d3841). That change affects Python3.4, but not Python2.7. As far as I can tell, [the 2.7 branch](http://hg.python.org/cpython/file/ae9fb85ab4e0/Lib/wave.py#l95) does not support the `with` statement. – unutbu Dec 04 '13 at 13:01
-
2Sorry, my mistake. This was about `open`, not `wave.open`. – Lewistrick Dec 04 '13 at 15:25
-
Awesome answer yet again. – ryanjdillon Sep 29 '16 at 14:21
-
Running this code on a raspberry pi, ate up the CPU hard, would love to just be able to get the duration, then dump the info instead of holding it. – Typewar Jul 26 '17 at 21:12
the librosa library can do this: librosa
import librosa
librosa.get_duration(filename='my.wav')
-
4
-
2Note that this avoids loading the contents into memory, and is therefore useful for querying the duration of long files. (quoted from librosa) – alsaleem Sep 08 '21 at 21:14
-
1For what it's worth, this (and many other answers) requires `libsndfile1` to be installed on the system, which may or may not be an option (say, for a webapp, it'll depend on your host; e.g. here is [how to get libsndfile1 working on Heroku](https://stackoverflow.com/a/57746160/1717535).) – Fabien Snauwaert Jul 06 '22 at 07:36
-
The librosa-link has expired, here's the current one: https://librosa.org/ – Bernhard Wagner Nov 24 '22 at 19:06
A very simple method is to use soundfile (formerly pysoundfile).
Here's some example code of how to do this:
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))
The output for that particular file is:
samples = 232569
sample rate = 16000
seconds = 14.5355625
This aligns with 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

- 1,344
- 14
- 14
-
3For me, this is really the best answer, as it removes a lot of the complexity of the answers above. Keeping it simple! – Saelyth Mar 27 '18 at 22:37
-
3Yup. And it does rely on a 3rd party library, but that 3rd party library is a simple wrapper for a well-known C library, libsndfile. And pysoundfile integrates with numpy. Win, win, win. – Dave C May 11 '20 at 17:09
-
@Airenas That's a great question: it should because `SoundFile.len()` returns `self.frames` where 1 frame contains an audio sample for every single channel. That said, I noticed that `len` API will may be deprecated: https://github.com/bastibe/python-soundfile/issues/199 Instead of `len(f)`, I would use `f.frames` per the lambda function here: https://github.com/bastibe/python-soundfile/blob/master/soundfile.py#L642 It's more clear that way. – Dave C Aug 24 '21 at 18:57
-
@Airenas I updated the answer with my suggested change per your question. I hope that clears things up. – Dave C Aug 24 '21 at 19:00
-
1
we can use ffmpeg to get the duration of any video or audio files.
To install ffmpeg follow this 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.decode(), re.DOTALL).groupdict()
print(matches['hours'])
print(matches['minutes'])
print(matches['seconds'])

- 3,340
- 2
- 10
- 32

- 201
- 2
- 4
-
2I got this error "cannot use a string pattern on a bytes-like object". So I replaced the call to "stdout" with "stdout.decode()" – AvielNiego Jan 13 '18 at 17:50
-
Also for Python 3 users, don't forget to have parenthesis on the print statements and as @AvielNiego pointed, use stdout.decode() than stdout. – Menilik Belay Woldeyes Aug 15 '19 at 07:33
-
Often ffprobe is available as well. It can format result output much more customized to any particular use. A bash line I use: d=$(ffprobe -i "${1}" 2>&1 | grep 'Duration') yields: "Duration: 01:06:10.61, start: 0.000000, bitrate: 787 kb/s" – Chris Reid Jan 09 '20 at 21:25
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()
-
A safer approach to deal with the binary contents of the file without the byteRate loop could be: from struct import unpack_from rate, = unpack_from('
– edrabc Apr 04 '13 at 13:08 -
Small mistake: `os.path.getsize(path)` should be `os.path.getsize(f)`. – Lewistrick May 14 '14 at 14:55
-
1Another small mistake: `ms=((fileSize-44)*1000)/byteRate` But this is excellent because it works even if your WAV is not PCM. – Jamie Oct 06 '15 at 06:56
-
1This doesn't seem to work for Python3, because open() uses encoding="utf-8" by default. Instead, use `f=open(path, encoding="latin-1")` (you don't need `"r"` because that's the default open mode). – Lewistrick Jun 20 '18 at 12:43
Let,T be the duration between 2 consecutive samples. So, we can write t = nT or t = n/Fs.
from scipy.io import wavfile
Fs, data = wavfile.read('filename.wav')
n = data.size
t = n / Fs

- 794
- 7
- 13
-
1in two channel wave file, this method will give double the actual answer. Use ```len(data)``` instead of ```data.size```. – Ritwik Dec 16 '20 at 09:53
I was trying to get the length of different format of an audio file other than '.wav' and I tried a few of the above solution but didn't work for me
This is what worked for me :
from pydub.utils import mediainfo
mediainfo('audiofile')['duration']

- 12,007
- 7
- 50
- 88
To find length of music file, audioread module can be used,
install audioread: pip install audioread
then use this code:
import audioread
with audioread.audio_open(filepath) as f:
totalsec = f.duration
min,sec = divmod(totalsec,60) # divides total time in minute and second
#and store it in min and sec variable respectively
Another solution with pydub:
import pydub
audio_seg = AudioSegment.from_wav('mywav.wav')
total_in_ms = len(audio_seg)

- 364
- 1
- 5
This is short and needs no modules, works with all operating systems:
import os
os.chdir(foo) # Get into the dir with sound
statbuf = os.stat('Sound.wav')
mbytes = statbuf.st_size / 1024
duration = mbytes / 200

- 79
- 11
-
1Will not work in general. Assumes a particular number of bytes per sample, and a particular sample-rate. Ignores the header size. – Jon Nordby Apr 04 '21 at 14:32