Sometimes we get data that resembles an opened file and we can't handle it easily. An example of this is if you download a wav
audio file directly into memory, so that the binary
contents of the file are already stored in an object.
One way to handle it is to write the binary contents to an actual file on disk. However, this is inefficient.
Another way is to create a file-like object that can be dealt with as normal files.
In this example, we have the binary contents of a wav audio file and we would like to decode it to extract the audio array and sampling rate. We want to do this all in-memory without writing to disk.
We will be doing this using python
.
We will need two dependencies:
io
libraries for creating file-like objectssoundfile
for decoding the data into audio array
import soundfile as sf
import io
Let's say we have a python object named binary_contents
that contain the binary contents of the audio file.
One way to obtain this object is:
with open('avc.wav', 'rb') as audio_file:
bytes_data = audio_file.read()
print(type(bytes_data))
# <class 'bytes'>
print(bytes_data)
# b'RIFF2m\x0b\x00WAVEfmt \x12\x00\x00\x00\x03\x0 ...
We see that binary_contens
is of type <class 'bytes'>
To decode these contents, we can do:
file_like_object = io.BytesIO(bytes_data)
audio_array, sr = sf.read(file_like_object)
print(sr)
# 16000
print(audio_array)
# [0.0, 0.0, 0.0, 5.960464477539063e-08, -5.96, ...]
We've now obtained the audio array as well as the sampling rate.
We can do this efficiently using the following function:
def read_audio_bytes(bytes_data):
file_like_object = io.BytesIO(bytes_data)
audio_array, sr = sf.read(file_like_object)
return {'array': audio_array, 'sampling_rate': sr}
# We can use this in pandas or polars dataframe:
res = read_audio_bytes(bytes_data)
df['audio_array'] = res['array']
df['audio_sampling_rate'] = res['sampling_rate']