如何基于Spring Boot(Java11)实现HTTP/HLS视频直播上传端点?
Spring Boot(Java 11)接收客户端直播视频流的可行方案
核心思路
你的需求是接收客户端持续推送的直播流而非单个文件,因此不能依赖传统的MultipartFile(针对整文件上传),需要直接处理HTTP请求的二进制流,让服务端能持续读取并实时处理字节数据。以下是两种落地实现方案,以及客户端推送的具体方式。
方案一:传统Spring MVC流式接收
通过直接获取HttpServletRequest的输入流,持续读取客户端推送的二进制数据,适合同步处理场景。
控制器实现
@RestController @RequestMapping("/live-stream") public class VideoStreamController { // 线程池用于异步处理视频流,避免阻塞控制器线程 private final ExecutorService processingPool = Executors.newFixedThreadPool(4); @PostMapping(value = "/upload", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE) public ResponseEntity<Void> receiveLiveStream(HttpServletRequest request) throws IOException { try (InputStream inputStream = request.getInputStream()) { byte[] buffer = new byte[4096]; // 按4KB分片读取 int bytesRead; // 持续读取直到客户端断开连接 while ((bytesRead = inputStream.read(buffer)) != -1) { // 异步提交处理任务,避免阻塞IO线程 byte[] chunk = Arrays.copyOfRange(buffer, 0, bytesRead); processingPool.submit(() -> processVideoChunk(chunk)); } } catch (Exception e) { // 处理客户端断开等异常 e.printStackTrace(); } return ResponseEntity.ok().build(); } // 自定义视频片段处理逻辑(AI检测、帧解析等) private void processVideoChunk(byte[] chunk) { // 示例:打印片段长度,实际替换为业务逻辑 System.out.println("处理直播片段,字节数:" + chunk.length); // 如需解析视频帧,可引入FFmpeg绑定库(如Jaffree)解码H.264等编码格式 } }
配置注意事项
需在application.properties中调整连接超时,避免长连接被提前断开:
server.servlet.connection-timeout=3600000 # 1小时超时
方案二:Spring WebFlux响应式流式接收
适合高并发、非阻塞场景,利用Reactor的Flux处理流式数据,更贴合直播流的持续推送特性。
控制器实现
@RestController @RequestMapping("/live-stream") public class ReactiveStreamController { @PostMapping(value = "/upload-reactive", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE) public Mono<ResponseEntity<Void>> receiveReactiveStream(@RequestBody Flux<DataBuffer> dataBuffers) { return dataBuffers .doOnNext(buffer -> { // 读取当前分片数据 byte[] chunk = new byte[buffer.readableByteCount()]; buffer.read(chunk); DataBufferUtils.release(buffer); // 及时释放内存 // 异步处理片段 CompletableFuture.runAsync(() -> processVideoChunk(chunk)); }) .then(Mono.just(ResponseEntity.ok().build())); } private void processVideoChunk(byte[] chunk) { // 同MVC方案的处理逻辑 System.out.println("响应式处理直播片段,字节数:" + chunk.length); } }
客户端推送方式
不需要用分片MultiPartFile,直接以二进制流形式推送即可,以下是两种常用工具的示例:
1. FFmpeg推摄像头/本地视频流
适合真实直播场景,将摄像头或本地视频编码后推送到服务端:
# 推送本地摄像头流(Linux示例) ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -f mpegts http://localhost:8080/live-stream/upload # 推送本地视频文件模拟直播流 ffmpeg -i local-video.mp4 -c:v libx264 -f mpegts http://localhost:8080/live-stream/upload
2. CURL模拟流式推送
用于快速测试端点:
curl -X POST -H "Content-Type: application/octet-stream" --data-binary "@test-video.mp4" http://localhost:8080/live-stream/upload
HLS协议适配说明
HLS本身是拉流协议(客户端从服务端拉取TS分片),如果要让客户端推送HLS流,本质是客户端逐个上传TS分片文件。此时可以实现一个接收TS文件的端点,实时处理每个分片:
@PostMapping("/upload-hls-ts") public ResponseEntity<Void> receiveHLSTs(@RequestParam("ts") MultipartFile tsFile) throws IOException { processTSFile(tsFile.getBytes()); return ResponseEntity.ok().build(); } private void processTSFile(byte[] tsData) { // 解析TS分片,提取视频帧进行处理 System.out.println("处理HLS TS分片,大小:" + tsData.length); }
客户端可通过FFmpeg将直播流切分为TS分片后逐个上传,或使用专门的HLS推流工具。
内容的提问来源于stack exchange,提问作者hotmeatballsoup
相关产品推荐
相关产品推荐

