5

I am trying to edit length of wav files using the wave module. However it seems that I can't get anywhere because i keep getting the same error that number of channels is not specified. Still, when i write something to see the number of channels i still get that error or when i try to set the number of channels as seen here:

def editLength(wavFile):
   file = wave.open(wavFile, 'w')
   file.setnchannels(file.getnchannels())
   x = file.getnchannels()
   print (x)
Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
j.doe
  • 51
  • 1
  • 3

2 Answers2

0

from https://docs.python.org/3.7/library/wave.html#wave.open

wave.open(file, mode=None)

If file is a string, open the file by that name, otherwise treat it as a file-like
object.

mode can be:
'rb'    Read only mode.
'wb'    Write only mode.

Note that it does not allow read/write WAV files.

You attempt to read and write from a WAV file, the file object has at the time of the first file.getnchannels() not specified the number of channels.

def editLength(wavFile):
    with open(wavFile, "rb") as file:
        x = file.getnchannels()
        print(x)

if you want to edit the file you should first read from the original file and write to a temporary file. then copy the temporary file over the original file.

steviestickman
  • 1,132
  • 6
  • 17
0

It's maybe not super obvious from the docs: https://docs.python.org/3/library/wave.html

The Wave_write object expects you to explicitly set all params for the object.

After a little trial and error I was able to read my wav file and write a specific duration to disk.

For example if I have a 44.1k sample rate wav file with 2 channels...

import wave

with wave.open("some_wavfile.wav", "rb") as handle:
    params = handle.getparams()
    # only read the first 10 seconds of audio
    frames = handle.readframes(441000)
    print(handle.tell())

print(params)
params = list(params)
params[3] = len(frames)
print(params)

with wave.open("output_wavfile.wav", "wb") as handle:
    handle.setparams(params)
    handle.writeframes(frames)

This should leave you with an stdout looking something like this.

441000
_wave_params(nchannels=2, sampwidth=2, framerate=44100, nframes=10348480, comptype='NONE', compname='not compressed')
[2, 2, 44100, 1764000, 'NONE', 'not compressed']

nframes here is 1764000 probably because nchannels=2 and sampwidth=2, so 1764000/4=441000 (I guess) Oddly enough, setparams was able to accept a list instead of a tuple. ffprobe shows exactly 10 seconds of audio for the output file and sounds perfect to me.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Seth
  • 3
  • 1