我的服务器上有几百个视频文件。 由于我不是一个大企业,我发现很难在我可用的存储中转码和维护副本。我的设置涉及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
..因为我不认为我可以将此用于我的最终目的)
另外,有没有更好的方法来实现即时转码+流媒体?
答案 0 :(得分:0)
浏览器不喜欢下载嵌入视频的整个文件;他们希望能够发出HTTP Range
请求以下载部分块(以支持搜索等)。有些浏览器对此非常严格,如果没有正确的Content-Range
标头,则完全拒绝加载视频。不幸的是,这使得在事先不知道文件大小时难以提供视频。
如果文件足够小,您可以在提供之前将整个内容转码为临时文件,那么您可以这样做,然后以与Content-Range
相同的方式提供StaticFileHandler
。如果没有,那么我认为您可能需要使用更复杂的协议,例如HLS or MPEG-DASH,以使其适用于所有浏览器。