The Problem:
I am currently deploying a Python Flask App using a Dockerfile on a PaaS (Heroku like). The User Story is as follows:
I had some NotImplemented
: no such file or dir... errors which have gone away since I added some install lines to my Dockerfile. Alas, I am stuck at this ALSA error:
pygame.error: ALSA: Couldn't open audio device: No such file or directory
I know for certain the file is a good directory as downloading proves the file exists and references the source. Locally, you can also see the file generate.
The Context:
Here is my Dockerfile:
# syntax=docker/dockerfile:1
FROM python:3.9-slim-buster
WORKDIR /appname
COPY requirements.txt requirements.txt
# Added to avoid NotImplemented errors
RUN apt-get update && apt-get install -yq \
libgtk2.0-dev \
libasound2 \
alsa-tools \
# Original Run Command
&& pip3 install -r requirements.txt
# && rm -rf /var/lib/apt/lists/* \ # Doesn't work.
COPY . .
EXPOSE 5000
CMD [ "python3", "-m" , "flask", "--app", "appname", "run", "--host=0.0.0.0"]
Here is a pertinent snippet of my Flask App:
from pygame import mixer
if request.form.get('playback_midi') and MIDI_file:
if 'Playback MIDI' in request.form['playback_midi']:
mixer.init() # <-- Here is where it fails
mixer.music.load("temp_MIDI_File.mid")
mixer.music.play()
The "temp_MIDI_File.mid"
is used so that it is constantly overwritten without unique file names (that is handled elsewhere).
What I've Tried:
Currently, I'm working with these references:
Run Apps Using Audio in a Docker Container
Getting pygame running in docker
I'm thinking the 'Run Apps Using Audio in a Docker Container' might have the solution in there, I'm just not sure if the same solution could possibly work in a PaaS context (as I'm not sure what audio device would possibly be usable in this cloud hosting scenario; or if I even have privileges to access it). I'm also open to using a different package besides Pygame. Thanks!
Further Research:
Running Sound in a Container
Docker Container Audio
Docker Tips - Play Audio in a Container (2022)
Maybe this is best handled in JS...
Leaving it for now...
I was able to Use the html <audio>
tag to generate audio successfully.
All of the controls work. This leads me to two complicated avenues I don't quite have time to pursue, but will put a pin in...
audio
tags. midi2audio
seemed like a pythonic way to approach this, but seems configured on using ALSA just like pygame
. The FluidSynth API is coded in C, so I'm not sure how to bridge this.My Solution:
Fortunately, there is an awesome html MIDI player that solved this issue:
html-midi-player
Here is my Flask HTML Template Code:
{% if MIDI_playback %}
<midi-player
src="{{ MIDI_playback }}"
sound-font visualizer="#myPianoRollVisualizer">
</midi-player>
<midi-visualizer type="piano-roll" id="myPianoRollVisualizer"
src="{{ MIDI_playback }}" style="color: white">
</midi-visualizer>
<script src="https://cdn.jsdelivr.net/combine/npm/tone@14.7.58,npm/@magenta/music@1.23.1/es`6/core.js,npm/focus-visible@5,npm/html-midi-player@1.5.0">
</script>
An Important Note:
Using the script within this Python Flask App, I ran into this CORS error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled
My workaround was to specify a CORS configuration in local and production instances.