You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot接收直播视频流并转发至React前端的实现方案咨询

哈哈,我完全懂你搜不到合适教程的苦恼——毕竟普通的文件视频和直播流根本不是一回事!我来给你梳理一套从直播流接入Spring Boot到转发到React前端的完整方案,咱们一步一步来,顺便补点关键术语,以后搜资料就顺畅多了:

一、先选适合的直播流技术栈

既然你能决定推送格式,咱挑最顺手、生态最成熟的来:

  • HLS (HTTP Live Streaming):首推!基于HTTP协议,前端支持拉满(大部分浏览器直接兼容,不用额外插件),Spring Boot处理起来也简单,临时存储也方便(生成的小分片文件好管理),唯一缺点是延迟大概10-30秒,适合普通直播场景
  • WebRTC:追求低延迟(几十毫秒级)的话选它,比如互动直播、连麦场景,但前后端处理相对复杂,需要额外的信令服务
  • RTMP:传统直播协议,推流效率高,但前端原生不支持,得转成HLS或者用flv.js这类库播放,适合已有RTMP推流源的场景
二、Spring Boot后端实现步骤

1. 接收直播流:两种方案任你选

Spring Boot本身不是专门的媒体服务器,小流量可以直接扛,大流量建议搭配专门的媒体服务器(比如Nginx-RTMP)更稳定。

方案A:Spring Boot直接接推流(小流量场景)

核心思路是把推流过来的字节流,用FFmpeg转成HLS格式的分片文件。先给你个伪代码参考:

@RestController
@RequestMapping("/live")
public class LiveStreamController {
    // 分片文件存储路径,你可以换成对象存储地址
    private final String HLS_STORAGE = "/tmp/hls/";

    @PostMapping("/push")
    public ResponseEntity<String> receiveStream(HttpServletRequest request) throws IOException, InterruptedException {
        // 读取推流的原始字节流
        InputStream inputStream = request.getInputStream();
        // 调用FFmpeg把输入流转成HLS分片
        ProcessBuilder ffmpegCmd = new ProcessBuilder(
            "ffmpeg", "-i", "-", "-c:v", "libx264", "-c:a", "aac",
            "-f", "hls", "-hls_time", "10", "-hls_list_size", "5", // 每10秒一个分片,保留最近5个
            HLS_STORAGE + "live.m3u8"
        );
        Process process = ffmpegCmd.start();
        
        // 把推流数据写入FFmpeg的标准输入
        try (OutputStream os = process.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        }
        process.waitFor();
        return ResponseEntity.ok("直播流已接收并转码");
    }
}

注意:服务器上要先装FFmpeg,或者用Java封装的FFmpeg库(比如ffmpeg-java)。

方案B:搭配Nginx-RTMP接收推流(大流量推荐)

Nginx-RTMP是专门的媒体服务器,接推流效率比Spring Boot高N倍,还能自动生成HLS文件。Spring Boot只需要做权限控制、地址分发就行。

先配Nginx的RTMP模块:

rtmp {
    server {
        listen 1935; # RTMP默认端口
        chunk_size 4096;

        application live {
            live on; # 开启直播模式
            hls on; # 开启HLS转码
            hls_path /tmp/hls; # HLS文件存储路径
            hls_fragment 10s; # 每10秒一个分片
            hls_playlist_length 60s; # 播放列表保留60秒的内容
        }
    }
}

再配Nginx的HTTP服务,让前端能访问HLS文件:

http {
    server {
        listen 8080;
        location /hls {
            root /tmp;
            add_header Cache-Control no-cache; # 禁止缓存,保证直播实时性
            add_header Access-Control-Allow-Origin *; # 解决跨域问题
        }
    }
}

最后Spring Boot提供一个接口返回HLS播放地址(可以加权限验证):

@GetMapping("/live/play-url")
public ResponseEntity<String> getPlayUrl() {
    // 这里可以加用户权限校验
    String hlsUrl = "http://你的服务器IP:8080/hls/live.m3u8";
    return ResponseEntity.ok(hlsUrl);
}

2. 临时存储直播流

用HLS的话,临时存储就是保存生成的.m3u8索引文件和.ts分片文件,你可以存在本地磁盘,或者MinIO、阿里云OSS这类对象存储里。

可以给Spring Boot加个定时任务,自动清理旧的分片文件,避免占满磁盘:

@Scheduled(fixedRate = 3600000) // 每小时执行一次
public void cleanOldHlsFiles() {
    File hlsDir = new File(HLS_STORAGE);
    if (!hlsDir.exists()) return;
    
    File[] files = hlsDir.listFiles();
    if (files == null) return;
    
    // 清理1小时前的文件
    long cutoffTime = System.currentTimeMillis() - 3600000;
    for (File file : files) {
        if (file.lastModified() < cutoffTime) {
            file.delete();
        }
    }
}

3. 转发流到前端

其实HLS本身就是通过HTTP拉取分片文件,所以前端直接访问.m3u8地址就能播放,Spring Boot主要负责权限控制和地址分发;如果用WebRTC,Spring Boot需要做信令转发(交换两端的连接信息)。

三、React前端实现播放

1. HLS播放(简单易上手)

大部分现代浏览器原生支持HLS,也可以用hls.js库兼容更多浏览器,给你个组件示例:

import React, { useEffect, useRef } from 'react';
import Hls from 'hls.js';

const LivePlayer = () => {
    const videoRef = useRef(null);

    useEffect(() => {
        if (!videoRef.current) return;
        
        const video = videoRef.current;
        if (Hls.isSupported()) {
            const hls = new Hls();
            // 从后端获取播放地址,这里可以换成接口请求
            hls.loadSource('http://你的服务器IP:8080/hls/live.m3u8');
            hls.attachMedia(video);
            
            hls.on(Hls.Events.MANIFEST_PARSED, () => {
                video.play();
            });
            
            // 组件卸载时清理资源
            return () => hls.destroy();
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            // Safari原生支持HLS,直接设置地址就行
            video.src = 'http://你的服务器IP:8080/hls/live.m3u8';
            video.play();
        }
    }, []);

    return (
        <div className="live-player">
            <video ref={videoRef} controls width="100%" />
        </div>
    );
};

export default LivePlayer;

2. WebRTC播放(低延迟场景)

如果需要低延迟互动,WebRTC是首选,前端需要通过Spring Boot的信令服务和推流端交换连接信息,示例代码大概是这样:

import React, { useEffect, useRef } from 'react';

const WebRTCPlayer = () => {
    const videoRef = useRef(null);
    const peerConn = useRef(null);

    useEffect(() => {
        const initWebRTC = async () => {
            // 创建PeerConnection,用谷歌的公共STUN服务器
            peerConn.current = new RTCPeerConnection({
                iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
            });

            // 接收推流端的媒体流
            peerConn.current.ontrack = (event) => {
                if (videoRef.current) {
                    videoRef.current.srcObject = event.streams[0];
                }
            };

            // 从后端获取推流端的SDP Offer
            const offerRes = await fetch('/live/webrtc/offer', { method: 'POST' });
            const offer = await offerRes.json();
            await peerConn.current.setRemoteDescription(new RTCSessionDescription(offer));

            // 创建Answer并发送给后端
            const answer = await peerConn.current.createAnswer();
            await peerConn.current.setLocalDescription(answer);
            await fetch('/live/webrtc/answer', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(answer)
            });

            // 发送ICE候选到后端,转发给推流端
            peerConn.current.onicecandidate = (event) => {
                if (event.candidate) {
                    fetch('/live/webrtc/ice', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(event.candidate)
                    });
                }
            };
        };

        initWebRTC();

        return () => peerConn.current?.close();
    }, []);

    return (
        <div className="webrtc-player">
            <video ref={videoRef} autoPlay playsInline width="100%" />
        </div>
    );
};

export default WebRTCPlayer;

后端需要维护推流端和播放端的连接,转发SDP和ICE候选信息。

四、补几个核心术语,以后搜资料不懵
  • 推流:把直播源的音视频数据发送到服务器的过程(比如用OBS推流到你的服务器)
  • 拉流:前端从服务器获取音视频数据并播放的过程
  • HLS分片:HLS把长视频切成10-30秒的小.ts文件,通过.m3u8索引文件管理,前端按需拉取
  • 媒体服务器:专门处理音视频流的服务器(比如Nginx-RTMP、SRS),比Spring Boot更适合高并发场景
  • 信令服务:WebRTC里用来交换连接信息(SDP、ICE)的服务,Spring Boot可以兼任这个角色
五、几个注意事项
  • 高并发场景别让Spring Boot直接接推流,用专门的媒体服务器扛,Spring Boot只做业务逻辑
  • HLS延迟是硬伤,如果需要低延迟优先选WebRTC
  • 前端播放一定要处理跨域,Nginx或Spring Boot记得配置CORS
  • 临时存储的分片文件一定要定时清理,不然磁盘很快就满了

内容的提问来源于stack exchange,提问作者BladesV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 01:07:39