Spring Boot+Angular应用MP4视频无法流式播放问题求助
问题分析及解决方案
核心问题:后端范围请求处理错误
你的后端代码在处理Range请求时,虽然计算了正确的起始/结束字节、设置了Content-Range响应头,但最终返回的还是完整的文件资源(FileSystemResource),并没有实际截取请求的字节片段。浏览器拿到完整文件,自然只能等下载完成后才会开始播放。
修复步骤
1. 修正后端范围请求的文件片段返回逻辑
替换返回完整FileSystemResource的代码,改为返回截取指定字节范围的InputStreamResource:
@GetMapping("/{id}") public ResponseEntity<Resource> getVideo(@PathVariable("id") Long id, @RequestHeader HttpHeaders headers, Principal principal) throws IOException { Optional<Video> video = videoService.findOne(id, user); if (video.isEmpty()) { log.debug("Video not found"); return new ResponseEntity<>(HttpStatus.NOT_FOUND); } File videoFile = video.orElseThrow().getFileLocation(); long fileLength = videoFile.length(); List<HttpRange> httpRanges = headers.getRange(); if (httpRanges.isEmpty()) { // 处理完整文件请求 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, "video/mp4") .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength)) .body(new FileSystemResource(videoFile)); } // 处理范围请求 HttpRange httpRange = httpRanges.get(0); long start = httpRange.getRangeStart(fileLength); long end = httpRange.getRangeEnd(fileLength); long contentLength = end - start + 1; // 创建截取指定范围的输入流 InputStream inputStream = new FileInputStream(videoFile); inputStream.skip(start); // 跳过起始字节 // 用BoundedInputStream限制读取长度,需引入Apache Commons IO,或自行实现类似逻辑 InputStream rangeInputStream = new BoundedInputStream(inputStream, contentLength); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set(HttpHeaders.ACCEPT_RANGES, "bytes"); responseHeaders.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength)); responseHeaders.set(HttpHeaders.CONTENT_RANGE, "bytes " + start + "-" + end + "/" + fileLength); responseHeaders.set(HttpHeaders.CONTENT_TYPE, "video/mp4"); return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT) .headers(responseHeaders) .body(new InputStreamResource(rangeInputStream)); }
2. 确保视频文件本身支持流式播放
MP4文件的moov元数据原子如果存放在文件末尾,浏览器需要下载完整文件才能解析元数据,导致无法流式播放。可以用ffmpeg工具重新封装视频,把moov移到文件开头:
ffmpeg -i 原视频文件.mp4 -movflags faststart 处理后视频文件.mp4
3. 前端补充优化(可选)
- 确认
videoUrl()返回的是后端接口的正确地址,没有被拦截器或代理修改请求头 - 保留
preload="metadata"配置,让浏览器只预加载元数据,加快启动速度 - 若需自动播放,添加
autoplay muted属性(浏览器通常要求静音才能触发自动播放)
验证方式
修复后打开浏览器开发者工具的网络面板,查看视频请求:
- 首次请求应返回
206 Partial Content状态码,响应头包含Content-Range - 播放过程中会出现多个范围请求,说明流式播放已生效
内容的提问来源于stack exchange,提问作者Pampa Nello
相关产品推荐
相关产品推荐

