Why does my nginx endpoint streaming audio via ffmpeg fail with "An unexpected TLS packet was received"

Viewed 221

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:

  1. 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?
  2. 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.
  3. 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.
  4. Response(stream_with_context(..) in flask doesn't work either.
  5. Don't know much about nginx, but tried some other suggestions e.g. buffering / no buffering through nginx, etc, nothing seems to work :(.
  6. 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 trace outside of the request context, it works!
  7. 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 type instead.

Please let me know what other debugging info would be helpful / if anyone has any hypothesis I can test out.

0 Answers
Related