2015-12-25 9 views
5

http.serverを使用するシンプルなPythonサーバーがあります。目標は、ビデオをHTMLページに表示すること、またはビデオファイルをダウンロードすることではなく、ビデオをブラウザに直接表示することです。これは私が今までに持っているものです:レスポンスが完全にダウンロードされる前にブラウザが閉じるソケット

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() 

私が持っている問題は、応答にフルビデオが含まれていないということです。 file.mp4は50MBですが、ChromeやFirefoxのネットワークタブを見ると、応答は1MBしかないと言われています。フルファイルが転送されない理由はありますか?この作業を行うために何らかの種類のHTTPヘッダーを追加する必要がありますか?

EDIT:

これが今の私のコードです:

server_address = ('', 8000) 
handler_class = http.server.SimpleHTTPRequestHandler 
httpd = http.server.HTTPServer(server_address, handler_class) 

httpd.serve_forever() 

応答は今40メガバイト/ 30メガバイトである代わりのが(私は今デフォルトSimpleHTTPRequestHandlerのdo_GETを使用していますが、それはまだ働いていません1MB)。

Chromeでfile.mp4をリクエストすると、ソケット接続は〜7秒後に閉じられ(Firefoxでは約5秒後に)、BrokenPipeError: [Errno 32] Broken pipebecause the server is still trying to write the rest of the video file on a closed socketにスローされます。

私の質問は、どうすればソケットを閉じる前にブラウザが完全な応答をダウンロードできるようにすることができますか?クライアントに送信され

追加情報

HTTPレスポンスヘッダ:

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 
+0

なぜhttp.serverを使用して静的ファイルを提供したいのですか? 'python3 -mhttp.server'を実行すると、ディレクトリ内のファイルを扱うことができます(クイックアンドダーティハックとして使用すると仮定します)。 – jfs

+0

静的ファイルの提供は、私がやりたいことの一部にすぎないので、私はそれを自分でコーディングする必要があります。 – maximedupre

+1

ここで 'http.server'を使うと決まったら' http.server.SimpleHTTPRequestHandler'がどのように実装されているかを見てください( 'copyfile()'はディスクからファイルを読み込み、それをユーザに送ります)。 – jfs

答えて

1

私が使用していたビデオファイルが破損していることが判明しました。私は複数の他の.mp4でテストし、それは魅力的に機能しました。

あなたが本当に懸念している応答のために限り、HTTPヘッダーなどのビデオファイルを再生する(またはより正確に@hruntingで指摘したように、ビデオファイルをストリーミング)する必要があるのは次のとおりです。

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 

私も考えますServerDateおよびLast-Modifiedヘッダーは必須ではありません(これらは自動的にSimpleHTTPRequestHandlerによって送信されます)。あなたがビデオの特定の時間にジャンプすることを可能にする場合

@qarmaと@hruntingで指摘したように

、あなたはRangeヘッダーをサポートする必要があります。 RangeヘッダーはChromeでデフォルトで送信されるため、サポートすることをお勧めします。

1

ビデオをストリーミングするために、あなたは私の知る限りhttp.serverはありません見ることができるように、少なくともrange requeststransfer-encoding: chunked

をサポートする必要があります直接それをサポートしていません。もちろん、それを上に実装することができます。

代わりに、単純なフレームワークを使用してください。 bottle(1つのファイルはすでに両方をサポートしています)またはcherrypy(より多くのソリッド、マルチスレッドなど)

また、Pythonコードを使用せずに取得することもできます。あなたが使用している場合nginx

+0

それは私がやろうとしているストリーミングですか?単純にビデオファイルを提供しようとしていませんか?多分それは同じことです。 – maximedupre

+0

また、ブラウザを5/7秒間だけダウンロードするのはなぜですか? – maximedupre

+0

私はファイル全体を転送したいので、なぜ範囲要求をサポートする必要があるのか​​わかりませんし、転送コード化をサポートする必要がある理由もわかりません。つまり、サーバーはすでにContent-長さ – maximedupre

1

基本的に、@ qarmaは正しいです。動画をストリーミングするには、最低でもRange:ヘッダーをサポートするライブラリまたはフレームワークを使用する必要があります。

しかし、あなたはビデオをストリーミングしようとしていません。ブラウザはあなたのためにそれをやっています。 video/mp4コンテンツタイプを返すと、ビデオ自体をストリームする方法を知っているブラウザはすぐにストリーミングモードに切り替わります。ファイルのダウンロード(パイプエラーの原因)を停止し、Range:ヘッダーで再起動します。これは、ブラウザ内の既存のメディアプレーヤーコードを活用して行います。 SimpleHTTPServerクラスはRange:ヘッダーをサポートしていないため、応答を適切に処理しません。

このストリーミングの動作を防ぎ、ブラウザに再生せずにファイルをダウンロードさせたい場合は、Content-Dispositionヘッダーを返して、ビデオファイルをレンダリングするコンテンツではなくダウンロードファイルとして扱います。

ここで何をしたいんあなたの最初の質問に基づいていくつかのコードです:理論的に

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.send_header('Content-Disposition', 'attachment; filename=' + encodedFilePath) 
      self.end_headers() 
      self.copyfile(videoFile, self.wfile) 

server_address = ('', 8000) 
handler_class = SuperHandler 
httpd = http.server.HTTPServer(server_address, handler_class) 
httpd.serve_forever() 

は、あなたがまた戻ってAccept-Ranges: noneを送ったが、クロムは、少なくとも、それを無視しているようです。

+0

私はまだ、私が 'Range'ヘッダをサポートする必要がある理由を見てください。私はいつもビデオの一部だけでなく、フルビデオファイルを転送したい。たぶんあなたは@ qarmaが言ったように、「ユーザーはビデオで特定の時間にジャンプするかもしれないから」と言っているかもしれませんが、私はそれが私の問題とは関係ないと思います。 「あなたが行ったファイルのダウンロードを中止して(パイプエラーの原因)を停止し、Range:ヘッダーで再起動します」というメッセージが表示されますが、それはChrome(Firefoxではなく)でのみ発生します。いいえ、私はビデオファイルをダウンロードしたくないので、ブラウザで再生したいと思います。 – maximedupre

+0

私は実際に私の問題の解決策を見つけました。答えとして投稿しますが、助けてくれてありがとう。 – maximedupre

関連する問題