Http 提供来自Tornado的视频文件

Http 提供来自Tornado的视频文件,http,http-headers,video-streaming,html5-video,tornado,Http,Http Headers,Video Streaming,Html5 Video,Tornado,我的服务器上有几百个视频文件。 由于我不是一家大企业,我发现在我可用的存储中转码和维护副本很困难。我的设置包括nginx和Tornado 为了解决这个问题,我决定尝试动态转码,并按需提供这些临时文件 在我尝试创建一个子流程来尝试转换文件之前,我决定尝试通过Tornado提供一个静态视频文件 class MediaHandler(tornado.web.RequestHandler): def serve(self, media, max_bufsize=1*1024*1024):

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

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

在我尝试创建一个
子流程
来尝试转换文件之前,我决定尝试通过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()
当我要求Nginx提供相同的文件时,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
。因为我认为我不能将其用于我的最终目的)


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

浏览器不喜欢为嵌入式视频下载整个文件;他们希望能够发出HTTP
Range
请求来下载部分块(以支持搜索等)。一些浏览器对此要求非常严格,如果视频没有正确的
内容范围
标题,就拒绝加载视频。不幸的是,这使得在事先不知道文件大小的情况下很难提供视频


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

浏览器不喜欢为嵌入式视频下载整个文件;他们希望能够发出HTTP
Range
请求来下载部分块(以支持搜索等)。一些浏览器对此要求非常严格,如果视频没有正确的
内容范围
标题,就拒绝加载视频。不幸的是,这使得在事先不知道文件大小的情况下很难提供视频


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

我认为这就是可能发生的情况。我想,它说我可以使用
内容范围
,即使长度未知。我将在未知的
内容范围内尝试这一点
我认为这就是可能发生的情况。我想,它说我可以使用
内容范围
,即使长度未知。我将在未知的
内容范围内尝试此功能
Media resource http://xxxx:8000/video_test/media/test.mp4 could not be decoded.
All candidate resources failed to load. Media load paused.