How To save file_uploaded .mp3 and wav files using streamlit?

I’ve built a streamlit app for classification of music genre. It’s working good on wav format audio so how to make prediction using MP3 files. Also how to save the uploaded audio file using streamlit for further use.

1 Like

Hi @harish_natarajan
To convert mp3 to wav use the following code,

from pydub import AudioSegment
sound = AudioSegment.from_mp3("/path/to/file.mp3")
sound.export("/output/path/file.wav", format="wav")

Hope this helps.

1 Like

Thanks @sree369nidhi it worked I saved the audio file in wav format gave the path to that model and then deleted the file using os library. Thanks for your help. I’ll share the link of my deployed app soon.

Regards
Harish

2 Likes

Hi everyone! I’m having the same issue, but I’m having trouble saving the uploaded file from streamlit so I can pass it to AudioSegment. It looks like AudioSegment/ ffmpeg cannot interpret the UploadedFile object, so variations of this code don’t seem to work. It’s my first time working with audio and with the file uploader from streamlit, I am also having trouble saving the uploaded file from streamlit so I can get it’s path. Could you guys give me some tips on how to do that?

uploaded_file = st.file_uploader(“Upload File”)
test = AudioSegment.from_ogg(uploaded_file)

Best regards

1 Like

Hey @JLiporace

Can you provide link to your GitHub repo so that it would be easier to resolve your query?

1 Like

Hi @harish_natarajan!

Thanks for the reply. Actually I have just started this specific application and as this uploading step was the very first I was just doing some concept proofs locally. I can create a repo and link here soon, but the test code I was using was just the following snippet for now:

import streamlit as st
from pydub import AudioSegment

uploaded_file = st.file_uploader(“Upload File”)

if uploaded_file is not None:
test = AudioSegment.from_ogg(uploaded_file)

1 Like

I also tried saving the uploaded_file locally so I could them pass the path to AudioSegment, but I’m getting this error:

import streamlit as st
from pydub import AudioSegment
uploaded_file = st.file_uploader("Insert File")

with open('myfile.wav', mode='bx') as f:
    f.write(uploaded_file)

image

I thought UploadedFile was already a bytes-like object, so I’m having some trouble in that sense.

2 Likes

@Hey JLiporace

You could try to use

file_var = AudioSegment.from_ogg(uploaded_file) 

file_var.export('filename.wav', format='wav')

Instead of using context manager (with statement)

Also there is a type parameter for file_uploader so you could specify the extension such as ‘ogg’, ‘mp3’ inside a list

Happy streamliting!

1 Like

@sree369nidhi @harish_natarajan
I did see your app. Great work!

I am uploading mp3 files on my app

st.subheader("Choose a mp3 file that you extracted from the work site")
uploaded_file = st.file_uploader("Select file from your directory")
if uploaded_file is not None:
    audio_bytes = uploaded_file.read()
    st.audio(audio_bytes, format='audio/mp3')

I want to convert this mp3 to wav which I can using pydub but how do I find the name of the mp3 or the path from the ‘uploaded_file’ object?

1 Like

@Prashant_Mudgal,

I think there you can use uploaded_file.name to get name of the uploaded file. I guess it’s there since July 2020 update of streamlit. You can try this out and let me know if it works

Happy streamliting

1 Like

@harish_natarajan Thanks! That works!
My other problem is when I would be deploying my app on heroku or EC2, I would need to create the .wav file from .mp3 on the file and keep the .wav file somewhere till I read in librosa.

Is there a way that can be accomplished?

e.g. in your app as well, you are reading the mp3 file and then creating a spectrogram(maybe through librosa), from where did you read this wav file?

Right now the code looks like:

datapath = ‘/Users/prashantmudgal/Documents/Sound_app/data/’
def identify():
st.set_option(‘deprecation.showfileUploaderEncoding’, False)
st.subheader(“Choose a mp3 file that you extracted from the work site”)
uploaded_file = st.file_uploader(“Select”)
if uploaded_file is not None:
audio_bytes = uploaded_file.read()
st.audio(audio_bytes, format=‘audio/mp3’)
sound = AudioSegment.from_mp3(datapath+uploaded_file.name)
sound.export(datapath+uploaded_file.name[:-4]+’.wav’, format=“wav”)
wav_file = datapath+uploaded_file.name[:-4]+’.wav’
y, sr = librosa.load(wav_file)

When the app would be deployed then the datapath would change.

1 Like

@Prashant_Mudgal,

I’m glad that worked for you. For my application I stored the file in the same directory where my app resides. So even when I deployed the app it would work.

Regards
Harish

1 Like

I am trying to download uploaded tif files, but it keeps giving saying that it can’t accept the UploadedFile type. Does anyone know what might be the problem?

1 Like

@Sarang_Goel Are you working with Geospatial data? TIFF files are generally huge.

1 Like

oh i had this problem a very long time ago and for some reason i did something and it worked, so I dont really have this problem anymore.

1 Like

example of upload and save wav/mp3 file

import pydub
from pathlib import Path

def upload_and_save_wavfiles(save_dir: str) -> List[Path]:
    """ limited 200MB, you could increase by `streamlit run foo.py --server.maxUploadSize=1024` """
    uploaded_files = st.file_uploader("upload", type=['wav', 'mp3'] accept_multiple_files=True)
    save_paths = []
    for uploaded_file in uploaded_files:
        if uploaded_file is not None:
            if uploaded_file.name.endswith('wav'):
                audio = pydub.AudioSegment.from_wav(uploaded_file)
                file_type = 'wav'
            elif uploaded_file.name.endswith('mp3'):
                audio = pydub.AudioSegment.from_mp3(uploaded_file)
                file_type = 'mp3'

            save_path = Path(save_dir) / uploaded_file.name
            save_paths.append(save_path)
            audio.export(save_path, format=file_type)
    return save_paths

def display_wavfile(wavpath):
    audio_bytes = open(wavpath, 'rb').read()
    file_type = Path(wavpath).suffix
    st.audio(audio_bytes, format=f'audio/{file_type}', start_time=0)


files = upload_and_save_wavfiles('temp')

for wavpath in files:
    display_wavfile(wavpath)
1 Like

hey harish can you tell me how did u take a wav file as a input and convert it to a tensor?

1 Like

simpler one

def upload_and_save_wavfiles(save_dir: Path) -> List[Path]:
    """ limited 200MB, you could increase by `streamlit run foo.py --server.maxUploadSize=1024` """
    uploaded_files = st.file_uploader("upload", type=['wav', 'mp3'], accept_multiple_files=True)
    save_paths = []
    for uploaded_file in uploaded_files:
        with open(save_dir / uploaded_file.name, 'wb') as f:
            f.write(uploaded_file.getbuffer())
        save_paths.append(save_dir / uploaded_file.name)
    return save_paths
1 Like