'streaming'视频文件的Java HTTP进程

标签 java http video http-headers

我正在创建一个 Java 应用程序,它通过 http 将视频文件“流式传输”到浏览器(当前为 Chrome v24.x)。此视频被发送到 FFmpeg,其输出通过 HTTP 发送。

现在,一旦文件被完全编码,文件就会使用分块传输提供服务,并响应范围请求。标题示例:

请求

GET /file/9fe6b502-c127-47c2-b6d2-83ea58676a8d HTTP/1.1 : Host: localhost:1234 : Connection: keep-alive : Accept-Encoding: identity;q=1, *;q=0 : User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17 : Accept: */* : Referer: http://localhost:1234/media/9fe6b502-c127-47c2-b6d2-83ea58676a8d : Accept-Language: en-US,en;q=0.8 : Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 : Cookie: plushContainerWidth=100%25; plushNoTopMenu=0 : Range: bytes=0- :  

响应

HTTP/1.1 206 Partial Content : Connection: close : Date: Mon, 28 Jan 2013 14:51:52 GMT : Content-Type: video/mp4 : Etag: "9fe6b502-c127-47c2-b6d2-83ea58676a8d" : Accept-Ranges: bytes : Content-Range: bytes 0-625825/625826 : Content-Length: 625826 : Transfer-Encoding: chunked :  

发送的数据为 625826 字节,不包括 header 数据和分块开销。

现在,一切正常!

问题是 GET 请求发生在文件编码完成之前。我试图通过 HTTP 立即开始发送文件,只使用没有内容长度属性或范围的分块传输,因为它们当前未知。这会导致浏览器等待完整文件(并且在传输完成之前不会开始播放)。另外,当文件传输完成后,浏览器会报视频错误,无法播放文件。标题示例:

请求

Request : GET /file/9fe6b502-c127-47c2-b6d2-83ea58676a8d HTTP/1.1 : Host: localhost:1234 : Connection: keep-alive : Accept-Encoding: identity;q=1, *;q=0 : User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17 : Accept: */* : Referer: http://localhost:1234/media/9fe6b502-c127-47c2-b6d2-83ea58676a8d : Accept-Language: en-US,en;q=0.8 : Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 : Cookie: plushContainerWidth=100%25; plushNoTopMenu=0 : Range: bytes=0- 

响应

HTTP/1.1 200 OK : Connection: close : Date: Mon, 28 Jan 2013 14:51:29 GMT : Content-Type: video/mp4 : Transfer-Encoding: chunked

发送的数据为 625826 字节,不包括 header 数据和分块开销。

有没有人知道出了什么问题,或者如何在不知道文件全长的情况下开始播放视频?

谢谢你的时间,

詹姆斯。

//编辑

由于对不完整文件的请求状态为“Range: bytes=0-” - 我可以使用 Content-Range: bytes 0-999/* 的“n”字节(比如 1000 字节)的部分内容来回复吗?

//编辑2 根据要求,这是我用于输出文件的代码。这是浓缩的,因为代码实际上跨越了几个类。

File f = new File(_filename);
RandomAccessFile raf = new RandomAccessFile(f, "r");
ChunkedOutputStream cos = new ChunkedOutputStream(_out, 1024 * 100);
byte[] bytes;

while (true){
    lBufferSizeMax = Math.min(lBufferSize, fc.length() - lCompleted);
    bytes = new byte[(int)lBufferSizeMax];

    lCurrentRead = fc.read(bytes);
    if (lCurrentRead == 0){
        break;
    }

    cos.write(bytes);
}

最佳答案

请注意 ffmpeg 可能会在编码结束时重写文件的某些部分。这意味着视频文件中的元数据直到最后都是不完整的,因此在此之前尝试流式传输文件的开头是没有用的。您可以检查用单个破折号替换 ffmpeg 命令行中的输出文件名并将标准输出重定向到文件。而不是 ffmpeg ... out.movffmpeg ... -> out.mov。如果您收到一条错误消息,指出该格式需要可搜索的输出,您就会受到影响。

我几乎完全按照您的要求做了,结果在我的 Git repo 中.我使用的容器格式是 FLV,我可以在其中玩元数据游戏。不幸的是,这不是 iPad/iPhone 设备希望看到的。

关于 'streaming'视频文件的Java HTTP进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14565260/

相关文章:

java - 求 A[J] +- A[I] 的最大值

java - xmpp中如何使用UserSearchManager检查用户是否注册?

http - 为什么我的上传进度条在传输完成之前就结束了?

c# - 手动发布到 Asp.Net MVC Controller

Python bar_chart_race 错误 - 'Exception: You do not have ffmpeg installed on your machine.'

javascript - iPad 上的 HTML5 视频播放?

java - 如何将选项放在对象的变量上?

Java servlet url 映射、url 模式

CSS 未在本地 python httpserver 重启时更新

html - ffmpeg - 将 rtsp 流流式传输到网页