Search code examples
pythonvideo-streaminghttp-live-streamingm3u8aiohttp

Browser cancels HLS Stream while VLC accepts it


I recorded a HSL stream by writing the MPEG-TS streams contents into GridFS filesystem.

i'm now trying to serve this content back to the browser using aiohttps SessionResponse which fails for different reasons.

    async def get_video(request):
            stream_response = StreamResponse()
            stream_response.headers['Content-Type'] = 'video/mp2t'
            stream_response.headers['Cache-Control'] = 'no-cache'
            stream_response.headers['Connection'] = 'keep-alive'
            await stream_response.prepare(request)

            fd = GridFS()
            video_stream = await fd(video_id)

            while True:
                try:
                    chunk = await video_stream.readchunk()
                    if not chunk:
                        break
                    stream_response.write(chunk)
                except CancelledError as e:
                    # fails here in safari or with diff content-type also in chrome
                    break

            await stream_response.write_eof()
            return stream_response

When trying to access the url using safari i get the player ui presented but nothing plays while the server throws a CancelledError exception trying to write on the already closed SessionResponse

Opening the URL in Chrome results in downloading the video file. This file works when playing it back in VLC. Even playing the URL inside VLC using "Network Source" works.

I also tried serving a static m3u playlist in front of this direct url like this but without luck (VLC also works using the playlist instread of direct stream):

    #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="medium",NAME="Medium",AUTOSELECT=YES,DEFAULT=YES
    #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=992000,RESOLUTION=852x480,CODECS="avc1.66.31,mp4a.40.2",VIDEO="medium"
    http://localhost:8080/videos/{video_id}

I'm not sure how do debug this any further and would appreciate any help (or ask in comments if i'm unclear). What am i missing that the files don't get played back in browser when accessing them directly? Also embedding my resource url into a html video tag didn't help (obviously, since browser do the same when accessing a video directly)

Some more informations about the video content and the raw http resonses i'm sending:

Video Informations VLC

Video Informations VLC

Direct Video Stream HTTP Response (start)

Direct Video Stream HTTP Response

M3U Playlist HTTP Response

M3U Playlist HTTP Response


Solution

  • I have no experience with HLS personally but even vast overview of RFC draft displays that you breaks the protocol.

    It's not about sending video chunks all together in single endless response but about sending multiple http responses utilizing the same socket connection by keep-alive usage.

    Client sends request for new data portions providing protocol-specific EXT* flags and server should respond properly. At very beginning client asks for playlist, server should answer with proper data.

    Communication protocol is complex enough, sorry. I cannot just fix a couple lines in your snippet to make it work.