web-dev-qa-db-fra.com

Obtenir la longueur ou la durée du fichier .wav

Je cherche un moyen de connaître la durée d'un fichier audio (.wav) en python. Jusqu'ici, j'ai jeté un œil à la bibliothèque wave de python, mutagen, pymedia, pymad. Pymad m'a donné la durée mais ce n'est pas cohérent. 

Merci d'avance. 

24
Pannu

La durée est égale au nombre d'images divisé par le nombre d'images par seconde:

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)

En ce qui concerne le commentaire de @edwards, voici un code pour produire un fichier wave à 2 canaux:

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

Si vous lisez le fichier résultant dans un lecteur audio, vous constaterez qu'il dure 40 secondes. Si vous exécutez le code ci-dessus, la durée sera également de 40 secondes. Donc, je crois que le nombre d'images n'est pas influencé par le nombre de canaux et que la formule ci-dessus est correcte. 

40
unutbu

Une méthode très simple consiste à utiliser pysoundfile, https://github.com/bastibe/PySoundFile

Voici un exemple de code expliquant comment faire cela:

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

La sortie pour ce fichier particulier est:

samples = 232569
sample rate = 16000
seconds = 14.5355625

Cela correspond à 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
6
Dave C

nous pouvons utiliser ffmpeg pour obtenir la durée de tout fichier vidéo ou audio.

Pour installer ffmpeg, suivez ceci 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']
6
Vishwanath Hiremath
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()
4
deAngel

la bibliothèque librosa peut faire ceci: librosa

import librosa
librosa.get_duration(filename='my.wav')
1
Max

C'est court et ne nécessite aucun module, fonctionne avec tous les systèmes d'exploitation:

import os
os.chdir(foo) # Get into the dir with sound
statbuf = os.stat('Sound.wav')
mbytes = statbuf.st_size / 1024
duration = mbytes / 200
0
user9311010