开发者

Django, streaming H.264 video with FileWrapper (HTML5)

开发者 https://www.devze.com 2023-01-28 06:33 出处:网络
I\'m having a strange issue trying stream H.264 video with Django using the FileWrapper class. I\'m using the following view function:

I'm having a strange issue trying stream H.264 video with Django using the FileWrapper class. I'm using the following view function:

def mp4(request, path):
  wrapper = FileWrapper(open(path, 'rb'))
  content_type = mimetypes.guess_type(path)[0]
  response = HttpResponse(wrapper, content_type=content_type)
  response['Content-Length'] = os.path.getsize(path)
  return response

The function is mapped to this URL:

  (r'^/mp4/(.*)$', 'mp4'),

And I'm referencing the URL inside an HTML5 video tag:

<video width="560" height="340" controls>
  <source src='/video/mp4//tmp/test.mp4' type='video/mp4 codecs="avc1.42E01E, mp4a.40.2"'>
</video>

However, when I open the page containing the video, the video does NOT play and the Django development server issues the following errors:

Traceback (most recent call last):
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 280, in run
    self.finish_response()
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 320, in finish_response
    self.write(data)
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 416, in write
    self._write(data)
  File "/usr/lib/python2.6/socket.py", line 300, in write
    self.flush()
  File "/usr/lib/python2.6/socket.py", line 286, in flush
    self._sock.sendall(buffer)
error: [Errno 104] Connection reset by peer

[05/Dec/2010 13:08:00] "GET /video/mp4//tmp/test.mp4 HTTP/1.1" 200 384329753

Traceback (most recent call last):
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 280, in run
    self.finish_response()
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 320, in finish_response
    self.write(data)
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 416, in write
    self._write(data)
  File "/usr/lib/python2.6/socket.py", line 300, in write
    self.flush()
  File "/usr/lib/python2.6/socket.py", line 286, in flush
    self._sock.sendall(buffer)
error: [Errno 104] Connection reset by peer

Traceback (most recent call last):
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 280, in run
    self.finish_response()
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 320, in finish_response
    self.write(data)
  File "/usr/lib/pymodules/python2.6/django/core/servers/basehttp.py", line 416, in write
    self._write(data)
  File "/usr/lib/python2.6/socket.py", line 300, in write
    self.flush()
  File "/usr/lib/python2.6/socket.py", line 286, in flush
    self._sock.sendall(buffer)
error: [Errno 32] Broken pipe

The browse开发者_StackOverflowr, Google Chrome, appears to try to retrieve the video multiple times, the first two times reseting the connection and the last time dropping the connection. Notice that Django returns a 200 OK response together with the correct size of the video.

Here is the strange part: Even though the video does not play, I can right click the player control, select Save Video As... and Google Chrome will happily download the entire video and store it locally. I can then, still in Google Chrome, play the saved video by opening it with a file:// URL.

I have also tried putting the video file in a local web server and referencing it there in the video tag, and that works as well.

So I think the issue is related to FileWrapper and/or the way Django handles HttpResponse with an iterator. The data is there, it can be saved with Save Video As..., so why won't it play?

Thanks!


For those who're stumbling across this question in 2019 (and beyond), the answer has been posted here.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号