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