Java .mp4视频末尾的流损坏 - 网络错误



请帮忙,我的问题是使用此页面上的代码从.mp4流式传输字节 http://balusc.blogspot.ru/2009/02/fileservlet-supporting-resume-and.html 并且几乎正确完成,但是流总是在电影结束时损坏,例如:

视频长达 57 分钟 - 在 52 秒时出现故障,并显示消息:"网络错误导致流中途失败",我尝试了几次测试它,认为这确实是网络问题 - 但它总是相同的。我认为使用 .mp4 表示浏览器字节的代码可能存在一些特定问题。

任何帮助将不胜感激。

浏览器中的错误消息:网络错误导致视频下载中途失败。

问题应该出在这部分代码中,现在我想系统 Linux Ubuntu,可能是 JVM 没有足够的空间,文件大小超过 1.6Gb,正如 C. Trimble 在评论中提到的那样 - 可能我应该在文件的读取流套接字上或在 JVM 本身中分配更多内存我不知道如何(-Xms, -Xmx):

  private static void copy(RandomAccessFile input, OutputStream output, long start, long length) {
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    int read;
    try {
      if (input.length() == length) {
        // Write full range.
        Logger.log("length==length read/write "+length);
        while ((read = input.read(buffer)) > 0) {
          output.write(buffer, 0, read);
        }
      } else {
        // Write partial range.
        input.seek(start);
        Logger.log("start length: "+start);
        long toRead = length+start;
        while ((read = input.read(buffer)) > 0) {
          if ((toRead -= read) > 0) {
            output.write(buffer, 0, read);
            Logger.log("toRead -= read read/write "+toRead);
//            output.write(buffer, 0, DEFAULT_BUFFER_SIZE);
          } else { // the end of a movie - ERROR APPEARS HERE !!!
            Logger.log("the end read/write "+toRead);
            output.write(buffer, 0, (int) toRead + read);
//            output.write(buffer, 0, DEFAULT_BUFFER_SIZE);
            break;
          }
        }
      }
    } catch (IOException ex) {
      Logger.log(Arrays.toString(ex.getStackTrace()), "error.log");
      Logger.log(ex.getMessage(), "error.log");
    }
  }

响应内容 - 从日志从 1-st 开始到下降时结束的范围:

2014-12-27 17:55:625 内容范围:字节 1784938496-1787737811/17877378122014-12-27 17:55:645 内容范围:字节 262144-1787737811/17877378122014-12-27 17:55:795 内容范围:字节 1048576-1787737811/17877378122014-12-27 17:55:190 内容范围:字节 1572864-1787737811/17877378122014-12-27 17:55:676 内容范围:字节 2097152-1787737811/17877378122014-12-27 17:55:195 内容范围:字节 2621440-1787737811/17877378122014-12-27 17:55:721 内容范围:字节 3145728-1787737811/17877378122014-12-27 17:55:421 内容范围:字节 786432-1787737811/17877378122014-12-27 17:55:992 内容范围:字节 1409024-1787737811/17877378122014-12-27 17:55:453 内容范围:字节 1835008-1787737811/17877378122014-12-27 17:55:34 内容范围:字节 2359296-1787737811/17877378122014-12-27 17:55:757 内容范围:字节 2883584-1787737811/17877378122014-12-27 17:55:340 内容范围:字节 5767168-1787737811/1787737812

来自FireBug Net工具的所有标头 - 响应:

Accept-Ranges   bytes
Content-Disposition inline;filename="True.Detective.S01E02.BDRip.720p.mp4"
Content-Length  1769137613
Content-Range   bytes 1572864-1770710476/1770710477
Content-Type    video/mp4
Date    Sat, 27 Dec 2014 17:53:54 GMT
Etag    True.Detective.S01E02.BDRip.720p.mp4_1770710477_1419450095000
Expires Sat, 03 Jan 2015 17:53:54 GMT
Last-Modified   Wed, 24 Dec 2014 19:41:35 GMT
Server  Apache-Coyote/1.1

请求标头:

Accept  video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5
Accept-Language ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Connection  keep-alive
Cookie  _ga=GA1.2.1399057170.1418569894; ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22013f5e68900cbd78accb95573968b6f3%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A12%3A%22109.173.78.7%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A72%3A%22Mozilla%2F5.0+%28Windows+NT+6.3%3B+WOW64%3B+rv%3A34.0%29+Gecko%2F20100101+Firefox%2F34.0%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1419680981%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7D4785741ee92c92e18475135f708e4283; PHPSESSID=s0cbpcnbqegb5u3312joe36510; _gat=1; _ym_visorc_27490695=w
Host    test.fast-seasons.ru:8080
Range   bytes=1572864-
Referer http://test.fast-seasons.ru:8080/tv/streaming?token=549ef20cd8a82
User-Agent  Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0

失败前日志中的输出 - 由于文件或内存分配较大,在系统/JVM 失败之前似乎很好:

2014-12-27 23:44:783 toRead -= read read/write 5792296
2014-12-27 23:44:783 toRead -= read read/write 5783080
2014-12-27 23:44:783 toRead -= read read/write 5773864
2014-12-27 23:44:783 toRead -= read read/write 5767168

有时,在自定义日志中,我看到以下异常:

2014-12-28 13:47:522 [org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:413), org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk
.java:342), org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:438), org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:
426), org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:91), ru.fastseasons.streaming.StreamServlet.copy(StreamServlet.java:446)
, ru.fastseasons.streaming.StreamServlet.processRequest(StreamServlet.java:329), ru.fastseasons.streaming.StreamServlet.doGet(StreamServlet.java:100), javax.
servlet.http.HttpServlet.service(HttpServlet.java:620), javax.servlet.http.HttpServlet.service(HttpServlet.java:727), org.apache.catalina.core.ApplicationFil
terChain.internalDoFilter(ApplicationFilterChain.java:303), org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208), org.ap
ache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220), org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java
:122), org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170), org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.jav
a:98), org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950), org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.jav
a:116), org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408), org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11P
rocessor.java:1040), org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607), org.apache.tomcat.util.net.JIoEndpoint$
SocketProcessor.run(JIoEndpoint.java:313), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145), java.util.concurrent.ThreadPoolEx
ecutor$Worker.run(ThreadPoolExecutor.java:615), java.lang.Thread.run(Thread.java:745)]
2014-12-28 13:47:522 null

当然,我查看了第 446 行,看到 read 变量作为 3d 参数传递以读取其中包含的字节数,但这应该没有程序问题,因为 read var 总是>0 通过 while 循环条件。

我想奇怪的行为是它发生在.mp4格式较大的 1Gb 文件上,可能是这是 Linux 或 JVM 内存窒息 - 我不知道,也不知道如何测试它。我也试图看看 ulimit -r -l

real-time priority              (-r) 95
max locked memory       (kbytes, -l) unlimited

每个 mp3/视频流的日志中实际上有 4 行(当视频通过浏览器播放时 Windows 上的 Chrome) - 似乎很正常,这里是:

2014-12-28 22:29:167 Content-Range: bytes 0-1180454117/1180454118
2014-12-28 22:29:168 Content-Length: 1180454118
2014-12-28 22:29:601 Content-Range: bytes 1178816938-1180454117/1180454118
2014-12-28 22:29:601 Content-Length: 1637180
2014-12-28 22:29:768 Content-Range: bytes 1178816986-1180454117/1180454118
2014-12-28 22:29:769 Content-Length: 1180454070

在Chrome中工作,感谢EJP,但在FF中仍然存在问题。

更正后在代码中实现的编辑@EJP:

long toRead = length;
while (toRead > 0 && (read = input.read(buffer, 0, (int)Math.min(buffer.length, toRead))) > 0)
{
    output.write(buffer, 0, read);
    toRead -= read;
}
long toRead = length+start;

问题就在这里。它应该是:

long toRead = length;

但是,您的代码可以大大简化:

while (toRead > 0 && (read = input.read(buffer, 0, (int)Math.min(buffer.length, toRead))) > 0)
{
    output.write(buffer, 0, read);
    toRead -= read;
}

E&OE

最新更新