Skip to content

Instantly share code, notes, and snippets.

@AmgadHasan
Created December 25, 2023 13:29
Show Gist options
  • Save AmgadHasan/21ae4d2d98f68e321679476df691a078 to your computer and use it in GitHub Desktop.
Save AmgadHasan/21ae4d2d98f68e321679476df691a078 to your computer and use it in GitHub Desktop.
Decode Audio from File Bytes

Overview

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.

1. Dependencies

We will be doing this using python. We will need two dependencies:

  1. io libraries for creating file-like objects
  2. soundfile for decoding the data into audio array
import soundfile as sf
import io

2. One example

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.

3. Modularization

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']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment