2

我正在尝试将 mp4 文件从 Grails 控制器流式传输到 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 标签嵌入:

<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()没有正确使用 of ,因为它不会t 只是从输入流的任意起点读取一个chunk,但是它会从当前位置读取一个chunk,所以你必须使用save the inputStream 然后使用inputStream.skip()跳转到正确的位置。

我在这里有一个更完整的答案(我在这里回答了我自己的类似问题) https://stackoverflow.com/a/23137725/2601060

于 2014-04-17T15:58:00.883 回答