【问题标题】:HTML5 video skips ranges after 32,768HTML5 视频跳过 32,768 之后的范围
【发布时间】:2021-06-20 14:40:27
【问题描述】:

我正在使用 Java 探索 Http Range 请求和视频流。我想创建一个控制器,将视频流式传输到标签。

由于某种原因,在结束范围 32768 之后,浏览器发送了开始 100237312 的请求。 以下是我控制台中的一部分日志:

...
Start: 27648, End: 28672, chunk size: 1024

Start: 28672, End: 29696, chunk size: 1024

Start: 29696, End: 30720, chunk size: 1024

Start: 30720, End: 31744, chunk size: 1024

Start: 31744, End: 32768, chunk size: 1024

Start: 100237312, End: 100238336, chunk size: 1024

Start: 100238336, End: 100239360, chunk size: 1024
...

我的代码:

package com.example.demo.controllers;

import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.nio.file.Files;
import java.util.Arrays;

@RestController
@RequestMapping("/video")
public class VideoCtrl {

    @CrossOrigin
    @ResponseBody
    @GetMapping
    public ResponseEntity<InputStreamResource> getVideo(@RequestHeader("Range") String range) {
        String[] rangeHeaderParams = HttpRange.parseHttpRangeHeader(range);
        File file = new File(getClass().getClassLoader().getResource("video_for_test.mp4").getFile());
        InputStream is = null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        long fileSize = file.length();
        assert is != null;

        final int CHUNK_SIZE = 1024;
        String type = rangeHeaderParams[0];
        int start = Integer.parseInt(rangeHeaderParams[1]);
        int end = start + CHUNK_SIZE;


        System.out.println(String.format(
                "Start: %d, End: %d, chunk size: %d\n", start, end, end - start
        ));

        byte[] chunk = new byte[CHUNK_SIZE];

        try {
            is.skip(start);
            is.read(chunk, 0, end - start);

            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.set("Content-Range", String.format("%s %d-%d/%d", type, start, end, fileSize));
            responseHeaders.set("Accept-Ranges", type);
            responseHeaders.set("Content-Length", String.format("%d", CHUNK_SIZE));
            responseHeaders.set("Content-Type", "video/mp4");
            responseHeaders.set("Connection", "keep-alive");
            responseHeaders.set("Content-Transfer-Encoding", "binary");
            responseHeaders.set("Cache-Control", "no-cache, no-store");
            responseHeaders.set("Expires", "0");
            responseHeaders.set("Keep-Alive", "timeout=100000 max=50");

            return new ResponseEntity<>(new InputStreamResource(new ByteArrayInputStream(chunk)), responseHeaders, HttpStatus.PARTIAL_CONTENT);
        } catch (IOException e) {
            return new ResponseEntity<>(new InputStreamResource(new ByteArrayInputStream("error".getBytes())), null, HttpStatus.BAD_REQUEST);
        }
    }
}

客户:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <video controls width="480">
        <source src="http://localhost:8080/video" type="video/mp4">
    </video>
</body>
</html>

如果有人解释整个概念,我将不胜感激,因为我认为它在实践中并不奏效。理论上,我应该只返回文件的一部分并发送结束范围,以便浏览器知道下一个“开始”是什么。

【问题讨论】:

    标签: java spring-boot video-streaming http-range


    【解决方案1】:

    MP4 文件的工作方式与您想象的不同。你不只是从一开始就开始玩。有一个名为“moov box”的“索引”,描述了“mdat box”中数据的布局。 moov 框可以位于文件的开头或结尾。在这种情况下,moov 可能位于偏移量 100237312。但是浏览器必须下载文件的开头才能了解 moov 的位置。一旦 moov 完全下载,浏览器就可以计算文件任何开始时间的字节范围偏移量。这就是寻找的工作原理。

    【讨论】:

    • 作为流媒体服务器,我怎么知道元数据在哪里?我仍然想在每个数据包中发送文件的一部分,如果我把它留给浏览器来查找元数据,它就违背了流式传输的目的。
    • “作为流媒体服务器”,它不是流媒体服务器,是普通的http服务器。这样做是故意的,因为大规模操作更便宜。 “它违背了流媒体的目的” 不,不是。这就是流媒体 mp4 的工作原理。这就是互联网上所有 mp4 流媒体的工作方式(DASH 和 HLS 不同)。服务器是愚蠢的,只是响应客户端的请求。您始终可以通过应用“快速启动”将 moov 框放在文件的开头以避免一次搜索。我怀疑这确实是一个xyproblem.info 问题,但你的问题有一些潜在的问题。
    • 如果你想知道更多关于“媒体在哪里”,你应该阅读mp4文件的结构。 Google 可以为您提供帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 2013-03-27
    • 1970-01-01
    相关资源
    最近更新 更多