2

Grails コントローラーから mp4 ファイルを iOS デバイス (iPhone および iPad) にストリーミングしようとしています。

def streamContent() {
    def contentPath = "/path/to/file"
    File f = new File(contentPath)
    if(f.exists()) {
        response.setContentType("video/mp4")
        response.outputStream << f.newInputStream()
        response.outputStream.flush()
        response.outputStream.close()
    } else {
        render status: 404
    }
}

このコードは safari などのデスクトップ ブラウザでは問題なく動作しますが (動画は表示されます)、iPhone や iPad で同じページにアクセスすると、動画が再生されません。同じ動画を Apache httpd に置いて、iOS デバイスからリクエストしても問題ないことに注意してください。したがって、ストリーミングの問題に違いありません。

HTML ページでは、ビデオは HTML5 ビデオ タグを使用して埋め込まれています。

<video width="360" height="200" controls>
    <source src="http://localhost:8080/myapp/controller/streamContent" type='video/mp4'>
</video>
4

2 に答える 2

0

この問題は、部分的なコンテンツと範囲のリクエスト (HTTP 206 ステータス) を処理することで解決しました。モバイル ブラウザ/メディア プレーヤーは、一度に多くのデータを転送することを避けるために、部分的なリクエストを使用しているようです。だから、単純なことをする代わりに

response.outputStream << f.newInputStream()

リクエストがバイトの範囲に対するものである場合、リクエストされたバイトのみを読み取ります。

if (isRange) {
    //start and end are requested bytes offsets
    def bytes = new byte[end-start]
    f.newInputStream().read(bytes, start, bytes.length)
    response.outputStream << bytes
    response.status = 206
} else {
    response.outputStream << f.newInputStream()
    response.status = 200
}
于 2012-11-07T10:26:55.270 に答える
0

f.newInputStream().read()まだコメントするほどの評判はありませんが、上記の回答は完全ではないこと、具体的には追加のヘッダーを含める必要があること、およびの使用法が正確に使用されていないことを指摘したいだけです。入力ストリームから任意の開始点でチャンクを読み取るだけですが、現在の位置からチャンクを読み取るため、inputStream を保存してから、 を使用inputStream.skip()して正しい位置にジャンプする必要があります。

私はここでより完全な答えを持っています(私は自分の同様の質問に答えました) https://stackoverflow.com/a/23137725/2601060

于 2014-04-17T15:58:00.883 に答える