I have a simple Python server that uses http.server
. The goal is not to show the video in a html page, or to download the video file, but to display the video in the browser directly. This is what I have so far:
import http.server
class SuperHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
path = self.path
encodedFilePath = 'file.mp4'
with open(encodedFilePath, 'rb') as videoFile:
self.send_response(200)
self.send_header('Content-type', 'video/mp4')
self.end_headers()
self.wfile.write(videoFile.read())
print('File sent: ' + videoFile.name)
server_address = ('', 8000)
handler_class = SuperHandler
httpd = http.server.HTTPServer(server_address, handler_class)
httpd.serve_forever()
The problem that I have is that the response doesn't contain the full video. file.mp4
is 50MB, but when I look in the network tab of either Chrome or Firefox, it says that the response is only 1MB. Is there a reason why the full file isn't transferred? Do I need to add some sort of HTTP header to make this work?
EDIT:
This is my code now:
server_address = ('', 8000)
handler_class = http.server.SimpleHTTPRequestHandler
httpd = http.server.HTTPServer(server_address, handler_class)
httpd.serve_forever()
I am now using the default SimpleHTTPRequestHandler's do_GET
, but it's still not working (although the response is now 40MB/30MB instead of 1MB).
When I request file.mp4
on Chrome, the socket connexion is closed after ~7 seconds (~5 seconds on Firefox), which makes the script throw a BrokenPipeError: [Errno 32] Broken pipe
, because the server is still trying to write the rest of the video file on a closed socket.
So my question is: how can I make the browser download the full response before it closes the socket?
Additional info
HTTP Response headers sent to the client:
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.5.0
Date: Mon, 28 Dec 2015 02:36:39 GMT
Content-type: video/mp4
Content-Length: 53038876
Last-Modified: Fri, 25 Dec 2015 02:09:52 GMT
It turns out that the video file I was using was corrupted (maybe it had some dropped frames or something like that). I tested with multiple other .mp4 and it worked like a charm.
All you really need to play a video file (or more accurately stream a video file as pointed by @hrunting) as far as http headers for the response are concerned is:
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.5.0
Date: Sat, 02 Jan 2016 02:45:34 GMT
Content-type: video/mp4
Content-Length: 33455269
Last-Modified: Sat, 02 Jan 2016 02:45:27 GMT
I think even the Server
, Date
and Last-Modified
headers aren't mandatory (they are sent automatically by SimpleHTTPRequestHandler
).
As pointed by @qarma and @hrunting, if you want to enable the user to jump to a specific time in video, you should support the Range
header. It's simply a good idea to support the Range
header as it is sent by default by Chrome.
To stream videos you should support at least range requests and transfer-encoding: chunked
As far as I can see http.server
does not support that directly. You can of course implement that on top.
Alternatively use a simple framework, e.g. bottle
(one file, already supports both) or cherrypy
(more solid, multi-threaded, etc)
You can also get by without any Python code, e.g. if you use nginx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With