Hello!
I’m working on a school project about visualizing sound. I’ve made a matplotlib animation that takes the sound input from a device and plots the frequency spectrum and the amplitudes of the frequencies. I would like to be able to import the animation into streamlit to make a ‘UI’ of sorts for the project, but can’t seem to get it to work.
Here is the code I have right now:
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import pyaudio
import streamlit.components.v1 as components
# Initialize PyAudio
p = pyaudio.PyAudio()
# Choose input mode
input_mode = True
# Set parameters for PyAudio
if input_mode:
DEVICE_INDEX = 1
else:
DEVICE_INDEX = 18
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = int(p.get_device_info_by_index(DEVICE_INDEX)['maxInputChannels'])
RATE = int(p.get_device_info_by_index(DEVICE_INDEX)['defaultSampleRate'])
# Open an audio stream from the audio device
def open_stream():
global stream
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK,
input_device_index=DEVICE_INDEX)
# Function to plot the frequency spectrum in real-time with amplitude on the y-axis
def FrequencyAmplitudePlot():
# Create window and axis for matplotlib
fig, ax = plt.subplots()
plt.close(fig) # Close the figure to prevent it from being shown initially
# Calculate frequencies for each point on the x-axis (frequencies from 20 Hz to RATE with CHUNK points)
xf = np.linspace(20, RATE, CHUNK)
# Create a line in matplotlib for the animation
line, = ax.plot(xf, np.random.rand(CHUNK))
# Set axis limits
ax.set_ylim(0, 5)
ax.set_xlim(20, RATE / 2)
# Function to update the plot with new data in real-time
def animate(frame):
# Record audio from the audio device
data = np.frombuffer(stream.read(CHUNK), dtype=np.int16)
# Apply a Fourier transformation on the data to find the frequency spectrum
y = np.fft.fft(data)
y = np.abs(y[0:CHUNK]) * 2 / (256 * CHUNK)
# Update the plot with the new data
line.set_ydata(y)
return line,
# Open the audio stream
open_stream()
# Start the animation
ani = FuncAnimation(fig, animate, blit=True, interval=20, frames=100)
st.title('Frequency/Amplitude Plot')
components.html(ani.to_jshtml(), height=500)
if __name__ == '__main__':
FrequencyAmplitudePlot()
When running it through Streamlit, I get an application with some frames from the audio visualizer, but it doesn’t work in real-time. Any help is appreciated