バックエンドでtapestry5(5.3.5)のHTML5ビデオタグを使用してIPadにビデオをストリーミングしたい。通常、サーバー側のフレームワークはこれで役割を果たしてはいけませんが、何らかの形でそれがあります。ipadへのビデオストリーミングがTapestry5で動作しない
とにかく、ここの誰かが私を助けてくれたらうれしいです。私のプロジェクトは非常にプロトタイプであり、私が記述したものは関連する部分に単純化/縮小されていることに留意してください。人々が義務的な「あなたが間違ったことをしたい」、または問題に関連しないセキュリティ/パフォーマンスのニックピックで応答しなかった場合、私は非常に感謝しています。
だからここには行く:
セットアップ
を私はフォーマットが問題ではないことを知っているので、AppleのHTML5ショーケースから取り出したビデオを持っています。私は単に "ビデオ"タグを含む単純なtmlページ "再生"を持っています。
問題は、私は、参照ビデオファイルを開くと、それをクライアントにストリーミングすることにより、ビデオコントロールからのリクエストを処理RequestFilterを実装することによって開始しました。これは基本的なものです。もしパスが 'file'で始まり、ファイル入力ストリームを応答出力ストリームにコピーするならば。これはChromeではうまく動作しますが、Ipadではうまく動作しません。さて、Appleのショーケースをもう一度見て、同じヘッダーとコンテンツの種類が含まれていますが、喜びはありませんでした。
次に、私はt5にファイルを提供させるとどうなるか見てみましょう。私はビデオをwebappコンテキストにコピーし、リクエストフィルタを無効にして、シンプルなファイル名をビデオのsrc属性に入れました。これはChromeとiPadで動作します。 それは私に驚いて、T5がどのように静的ファイル/コンテキスト要求を処理するかを見るように促しました。これまでのところ、ハードワイヤードの「ビデオsrc」を@Path(「コンテキスト:」)を持つ資産に切り替えることで、私が確認した2つの異なるパスがあるように感じました。これは、Chromeでも動作しますが、IPadでは動作しません。
ここで私は本当に迷っています。 IPad上で動作することを可能にする「シンプルコンテキスト」要求では、この秘密のジュースは何ですか?特別なことは何もありませんが、これが唯一の方法です。問題が
ソリューションので
...私は本当に私のWebアプリケーションコンテキストから、それらの分割動画を提供することはできません、それは「範囲」と呼ばれるこのHTTPヘッダがあることが判明とiPadのことを、Chromeが使用していますとは違ってビデオ付きです「秘密のソース」は、静的リソース要求のサーブレットハンドラがT5の間に範囲要求を処理する方法を知っていることです。ここに私のカスタム実装があります:
OutputStream os = response.getOutputStream("video/mp4");
InputStream is = new BufferedInputStream(new FileInputStream(f));
try {
String range = request.getHeader("Range");
if(range != null && !range.equals("bytes=0-")) {
logger.info("Range response _______________________");
String[] ranges = range.split("=")[1].split("-");
int from = Integer.parseInt(ranges[0]);
int to = Integer.parseInt(ranges[1]);
int len = to - from + 1 ;
response.setStatus(206);
response.setHeader("Accept-Ranges", "bytes");
String responseRange = String.format("bytes %d-%d/%d", from, to, f.length());
logger.info("Content-Range:" + responseRange);
response.setHeader("Connection", "close");
response.setHeader("Content-Range", responseRange);
response.setDateHeader("Last-Modified", new Date().getTime());
response.setContentLength(len);
logger.info("length:" + len);
byte[] buf = new byte[4096];
is.skip(from);
while(len != 0) {
int read = is.read(buf, 0, len >= buf.length ? buf.length : len);
if(read != -1) {
os.write(buf, 0, read);
len -= read;
}
}
} else {
response.setStatus(200);
IOUtils.copy(is, os);
}
} finally {
os.close();
is.close();
}
これは便利な情報です。 Tapestryが標準の資産処理コード内でこれを自動的に処理できない理由はありません。私たちはそれが必要であることを認識していません。このレベルの情報をJIRAに追加することが、最初のステップです。 –
優れた答え。すぐに魅力のように動作します。どうもありがとう。 –