Search code examples
pythonaws-lambdascipywavaudio-processing

Scipy wavfile to samples [time limit err] on AWS Lambda. Why?


I'm running some Python (3.8) code inside AWS Lambda function using scipy lib. First, I read wavfile into variable:

source = scipy.io.wavfile.read('/tmp/letov.wav')

It seems to work fine, getsizeof(source) returns 56, as I understand it means that variable has some data in it.

Then this line runs and script hangs infinitely:

audio_samples = source[1].tolist()

Why?

When I run this on local machine it works alright (few seconds).

But in Lambda it reaches up to 300s time limit. I've also tried to increase Lambda memory from 128mb to 512mb, to make sure it is not computing power issue, no luck. Audio file is the same in both environments.


Solution

  • From the information provided in the comments, we know that source[1] is a numpy array of 16 bit integers with shape (2219729, 2). The memory required to hold the actual array of integers is 2219729*2*2 = 8878916, or about 8.5 mb. As you said, reading the file works, and you have sufficient RAM to hold the data in memory.

    The problem occurs when you call the .tolist() method on the array. This converts the array data structure to a pure Python nested list of lists. That is, when you execute audio_samples = source[1].tolist(), audio_samples will be a Python list of length 2219729, and each element in that list will be a Python list of length 2, and each element in the inner list will be a Python integer (not a 16 bit NumPy integer). A single Python integer requires 28 bytes (i.e. getsizeof(1) returns 28). So just to store all those Python integers (without taking into account the list data structure), you will need 2219729 * 2 * 28 = 124304824 bytes, or about 124mb. In addition, the outermost list will require about 17.8mb, and each inner list will require 72 bytes, so the combined Python list data structure will require about 178mb. Combine that with the memory required for all the Python integers contained in those lists, and you get a total memory requirement of about 302mb.

    My advice: don't convert your samples to a pure Python data structure with the tolist() method. Stick with the NumPy array in source[1]. That is, use

    audio_samples = source[1]
    

    and then use the NumPy array audio_samples in your subsequent calculations.