提供Tornado

时间:2015-07-02 00:03:26

标签: http http-headers video-streaming html5-video tornado

我的服务器上有几百个视频文件。 由于我不是一个大企业,我发现很难在我可用的存储中转码和维护副本。我的设置涉及nginx和Tornado。

为了解决这个问题,我决定尝试动态转码并按需提供这些临时文件

在我尝试创建subprocess尝试为我转换文件之前,我决定尝试通过Tornado提供静态视频文件。

class MediaHandler(tornado.web.RequestHandler):
    def serve(self, media, max_bufsize=1*1024*1024):

        bytes_read = 0
        file_length = None
        remaining = None

        self.set_header('Content-Type', 'video/mp4')
        with open(media.name, 'rb') as f:
            while 1:
                # While transcoding, file size will be changing
                # So compute every time
                file_length = os.fstat(f.fileno()).st_size  # Get current length
                remaining = file_length - bytes_read    # Compute remaining bytes

                # Hopefully we're producing faster than we're consuming...
                if remaining == 0:
                    break

                buffer_size = max_bufsize if max_bufsize < remaining else remaining
                bytes = f.read(buffer_size)
                assert len(bytes) == buffer_size
                bytes_read += buffer_size

                self.write(bytes)
                self.flush()


    def get(self):
        log('Media Request: %s' % (self.request.uri))
        #XXX: Currently this is hard-coded in some sense..fix it
        media_path = os.path.abspath(os.path.join(dir_path, self.request.uri[1:]))  #Strip leading '/'
        log('media_path: %s' % (media_path))
        try:
            media = avprobe(media_path)
        except SubprocessException, e:
            raise e

        if media.video_codec not in valid_video_codecs or \
                media.audio_codec not in valid_audio_codecs:
            # Transcode and serve
            pass
        else:
            self.serve(media)
        self.finish()

我注意到当我尝试从Tornado提供文件时,Firefox根本不会加载视频。 检查后,我的回复标题如下:

HTTP/1.1 200 OK
Date: Thu, 02 Jul 2015 00:04:50 GMT
Content-Type: video/mp4
Transfer-Encoding: chunked
Connection: keep-alive
Server: TornadoServer/4.2

当我要求它提供相同的文件时,Nginx似乎会生成以下标题:

HTTP/1.1 206 Partial Content
Server: nginx/1.8.0
Date: Wed, 01 Jul 2015 23:57:06 GMT
Content-Type: video/mp4
Content-Length: 65796881
Last-Modified: Thu, 09 Apr 2015 21:47:56 GMT
Connection: keep-alive
Etag: "5526f38c-3ebfb11"
Content-Range: bytes 0-65796880/65796881

似乎Firefox并不喜欢我发送它的数据。 它在控制台上吐出以下内容:

Media resource http://xxxx:8000/video_test/media/test.mp4 could not be decoded.
All candidate resources failed to load. Media load paused.

有人可以指出我做错了什么,以及如何从Tornado提供静态媒体(不使用StaticFileHandler ..因为我不认为我可以将此用于我的最终目的)

另外,有没有更好的方法来实现即时转码+流媒体?

1 个答案:

答案 0 :(得分:0)

浏览器不喜欢下载嵌入视频的整个文件;他们希望能够发出HTTP Range请求以下载部分块(以支持搜索等)。有些浏览器对此非常严格,如果没有正确的Content-Range标头,则完全拒绝加载视频。不幸的是,这使得在事先不知道文件大小时难以提供视频。

如果文件足够小,您可以在提供之前将整个内容转码为临时文件,那么您可以这样做,然后以与Content-Range相同的方式提供StaticFileHandler。如果没有,那么我认为您可能需要使用更复杂的协议,例如HLS or MPEG-DASH,以使其适用于所有浏览器。