audiolab icon indicating copy to clipboard operation
audiolab copied to clipboard

Can't read data from file with unknown number of frames

Open njsmith opened this issue 11 years ago • 2 comments

I want to read the audio out of a .mov file, so I'm doing

child = subprocess.Popen(["avconv", "-i", "myfile.mov", "-f", "au", "-"], stdout=subprocess.PIPE)
my_sndfile = Sndfile(child.stdout.fileno())

This calls avconv (from ffmpeg) to feed the data directly into my process (no need for temporary files), and that's great. But:

  • my_sndfile.nframes contains nonsense: Okay, so I don't know how many frames to read, not a surprise given it's coming from a pipe. (It would be nice if nframes in this situation were None or -1 or something; instead I'm getting 2305843009213693945L.)
  • If I just call read_frames with a large value, hoping to get all the frames, I get:
In [76]: d = s.read_frames(10000000)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-76-cb9a61676b12> in <module>()
----> 1 d = s.read_frames(10000000)

/home/njs/.user-python2.7-64bit/local/lib/python2.7/site-packages/scikits.audiolab-0.11.0-py2.7-linux-x86_64.egg/scikits/audiolab/pysndfile/_sndfile.so in scikits.audiolab.pysndfile._sndfile.Sndfile.read_frames (scikits/audiolab/pysndfile/_sndfile.c:5361)()

/home/njs/.user-python2.7-64bit/local/lib/python2.7/site-packages/scikits.audiolab-0.11.0-py2.7-linux-x86_64.egg/scikits/audiolab/pysndfile/_sndfile.so in scikits.audiolab.pysndfile._sndfile.Sndfile.read_frames_double (scikits/audiolab/pysndfile/_sndfile.c:5749)()

RuntimeError: Asked 10000000 frames, read 573440

Sort of frustrating... it's telling me it managed to read the frames, but... then it threw them away and raised an exception. So the frames are there, but it's impossible for me to get at them. I expected this to allow for a shorter return value, like POSIX read or Python file.read.

The only solution I can see is to call read_frames(1) in a loop, which is silly, but there you go.

njsmith avatar Jan 03 '13 21:01 njsmith

libsndfile has some facility to read from a PIPE (http://www.mega-nerd.com/libsndfile/FAQ.html#Q017), but I have never tried it. There may be a way to make this more friendly in python.

cournape avatar Jan 16 '13 15:01 cournape

Right, the libsndfile part is fine, the problem is that the python wrapper api has no way to say " please give me N frames... or if the file ends before you've read N frames, then just give me what you got". The wrapper considers it a hard error if the file ends before all N frames are read.

(Compare the length argument to file.read, which is just an upper bound and you may get fewer bytes than requested.) On 16 Jan 2013 07:55, "David Cournapeau" [email protected] wrote:

libsndfile has some facility to read from a PIPE ( http://www.mega-nerd.com/libsndfile/FAQ.html#Q017), but I have never tried it. There may be a way to make this more friendly in python.

— Reply to this email directly or view it on GitHubhttps://github.com/cournape/audiolab/issues/14#issuecomment-12324696.

njsmith avatar Jan 17 '13 06:01 njsmith