I'm using nginx to proxy requests to a flask/gunicorn API. For most of my endpoints, it works perfectly - however, I have one endpoint which serves an audio response (through ffmpeg) which doesn't seem to work no matter what I try. Running everything through docker.
Here's my nginx config:
server {
listen $PORT;
root /usr/share/nginx/html;
index index.html index.html;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location / {
try_files $uri /index.html =404;
}
location /api/stream_audio_file {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
Here's the core of the python code for http://backend/api/stream_audio_file (run through flask, gunicorn)
ffmpeg_options = ['-i', 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3']
ffmpeg_options += ["-f", "mp3"]
ffmpeg_options += ["-to", '00:00:02.000']
ffmpeg_options += ["-vn"]
ffmpeg_options += ["-ab", "256k"]
ffmpeg_options += ["-strict", "-2"]
ffmpeg_options += ["-loglevel", "trace"]
p = Popen(["ffmpeg"] + ffmpeg_options + ["-"],
stdout=PIPE)
max_bytes = 256000
output = p.stdout.read(max_bytes)
return Response(output, headers={
"Content-Type": "audio/mp3",
"icy-name": yt_info['title'].encode('latin-1', 'ignore'),
"icy-bitrate": "256",
"ice-audio-info": "bitrate=256",
"Cache-Control": "no-cache"
})
When I test out this endpoint, I've pasted the full ffmpeg logs here: https://pastebin.com/wMMpmL6M Of import, it seems to fetch the mp3 url appropriately but fails with error:
[tls @ 0x555bf3011a80] An unexpected TLS packet was received.
https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3: I/O error
[out_0_0 @ 0x555bf302ab00] EOF on sink link out_0_0:default.
No more output streams to write to, finishing.
I've tried quite a few things:
- This endpoint works without nginx. I tried querying just the endpoint running w/ just gunicorn, and responses are streamed back correctly. Thus the error HAS to be nginx related?
- The error being TLS related is confusing - I've tried setting up nginx w/ ssl on and adding certs, but that doesn't help / change the error in any way.
- I've tried playing around with headers in both nginx and on the python side, following some of the examples here: https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/. Doesn't work.
Response(stream_with_context(..)in flask doesn't work either.- Don't know much about nginx, but tried some other suggestions e.g. buffering / no buffering through nginx, etc, nothing seems to work :(.
- When I ssh into my docker container, and run the same ffmpeg command
ffmpeg -i https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3 -f mp3 -to 00:00:02.000 -vn -ab 256k -strict -2 -loglevel traceoutside of the request context, it works! - Tried compiling ffmpeg with both openssl and gnutls, neither works. However: the openssl version fails w/
tls @ error:1408F1BB:SSL routines:ssl3_get_record:bad record typeinstead.
Please let me know what other debugging info would be helpful / if anyone has any hypothesis I can test out.