十分鐘搞定!用 Spring Boot 搭建屬于你的輕量直播平臺
直播技術正以前所未有的速度席卷各行各業。從社交媒體平臺到在線教育、電子商務甚至游戲社區,直播系統已成為增強用戶互動、傳遞實時信息的關鍵工具。本文將基于 Spring Boot 框架,構建一個具備推流、拉流、互動功能的輕量直播平臺。
一、直播技術基礎
1.1 推流與拉流的基本概念
- 推流(Push):主播通過攝像頭采集音視頻內容,編碼后推送至流媒體服務器。
- 拉流(Pull):觀眾端從流媒體服務器獲取直播流并進行解碼播放。
1.2 常見直播協議對比
協議 | 優勢 | 劣勢 | 典型場景 |
RTMP | 延遲低(1-3s)、技術成熟 | 基于 Flash、需開放 1935 端口 | 推流、低延遲直播 |
HLS | 使用 HTTP,兼容性好 | 延遲高(10s+) | 大規模分發、移動端播放 |
WebRTC | 超低延遲(<1s)、P2P 通信 | 網絡穿透難、部署復雜 | 實時互動、在線會議 |
HTTP-FLV | 延遲低、支持瀏覽器播放 | 不支持可變碼率 | 視頻門戶、低延遲場景 |
SRT | 高可靠性、低延遲 | 部署稍復雜,生態相對年輕 | 專業直播、跨國推流 |
1.3 直播系統架構組成
一個典型直播系統包括:
- 采集端:攝像頭/OBS等,用于采集視頻音頻流。
- 流媒體服務器:用于接收推流并分發(如 SRS)。
- CDN 分發層:大規模分發直播內容。
- 播放器:觀眾端使用 flv.js、hls.js 等播放流。
- 信令服務:管理用戶、直播間狀態、聊天等。
二、系統技術架構與選型
2.1 核心系統結構
采用模塊化分層方式設計:
- API 服務層:基于 Spring Boot 構建 REST 接口,處理房間創建、用戶信息等。
- 媒體服務層:通過 Docker 部署 SRS,接入 RTMP 推流、HTTP-FLV 拉流。
- 實時互動層:使用 WebSocket 進行直播間聊天室通信。
- 存儲層:使用 MinIO 對象存儲錄制回放內容。
- 前端播放器:使用 flv.js 播放直播流。
2.2 技術棧選型
模塊 | 技術 |
Web 框架 | Spring Boot 3 |
數據庫 | MySQL + Redis |
流媒體服務 | SRS (Simple RTMP Server) |
消息通信 | Spring WebSocket |
對象存儲 | MinIO |
前端播放器 | flv.js、Bootstrap、Thymeleaf |
三、基于 Spring Boot 實現直播服務
3.1 直播間管理模塊(REST API)
實體類:LiveRoom
@Entity
@Table(name = "live_room")
public class LiveRoom {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String roomId;
private String title;
private String streamer;
private String pushUrl;
private String pullUrl;
}
Repository 接口
public interface LiveRoomRepository extends JpaRepository<LiveRoom, Long> {
Optional<LiveRoom> findByRoomId(String roomId);
}
控制器接口
@RestController
@RequestMapping("/api/room")
public class LiveRoomController {
@Autowired
private LiveRoomRepository roomRepo;
@PostMapping("/create")
public ResponseEntity<?> createRoom(@RequestBody Map<String, String> payload) {
String roomId = UUID.randomUUID().toString();
String title = payload.get("title");
String streamer = payload.get("streamer");
LiveRoom room = new LiveRoom();
room.setRoomId(roomId);
room.setTitle(title);
room.setStreamer(streamer);
room.setPushUrl("rtmp://localhost:1935/live/" + roomId);
room.setPullUrl("http://localhost:8080/live/" + roomId + ".flv");
return ResponseEntity.ok(roomRepo.save(room));
}
@GetMapping("/{roomId}")
public ResponseEntity<?> getRoom(@PathVariable String roomId) {
return roomRepo.findByRoomId(roomId)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
}
3.2 推流與拉流服務(SRS接入)
通過 Docker 部署 SRS:
docker run -d --name srs \
-p 1935:1935 -p 1985:1985 -p 8080:8080 \
ossrs/srs:5
推流地址:rtmp://localhost:1935/live/{roomId}
拉流地址:http://localhost:8080/live/{roomId}.flv
使用 OBS 配置推流即可。
3.3 WebSocket 聊天服務
聊天處理器
@ServerEndpoint("/ws/chat/{roomId}")
@Component
public class ChatWebSocket {
private static Map<String, Set<Session>> roomSessions = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam("roomId") String roomId) {
roomSessions.computeIfAbsent(roomId, k -> ConcurrentHashMap.newKeySet()).add(session);
}
@OnMessage
public void onMessage(String message, @PathParam("roomId") String roomId) {
for (Session s : roomSessions.getOrDefault(roomId, Collections.emptySet())) {
s.getAsyncRemote().sendText(message);
}
}
@OnClose
public void onClose(Session session, @PathParam("roomId") String roomId) {
roomSessions.getOrDefault(roomId, Collections.emptySet()).remove(session);
}
}
WebSocket 配置
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.4 前端直播播放頁面(Thymeleaf + flv.js)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>直播間</title>
<script src="https://cdn.jsdelivr.net/npm/flv.js@1.6.2/dist/flv.min.js"></script>
<link rel="stylesheet" />
</head>
<body class="p-4">
<div class="container">
<h2>歡迎來到直播間:<span id="title"></span></h2>
<video id="liveVideo" class="w-100" controls></video>
<div class="mt-3">
<input type="text" id="chatInput" class="form-control" placeholder="輸入消息..." />
<button class="btn btn-primary mt-2" onclick="sendMessage()">發送</button>
</div>
<div class="mt-3">
<h5>聊天記錄</h5>
<div id="chatBox" class="border p-2" style="height: 200px; overflow-y: scroll;"></div>
</div>
</div>
<script>
const roomId = new URLSearchParams(window.location.search).get("roomId");
const videoUrl = "http://localhost:8080/live/" + roomId + ".flv";
const ws = new WebSocket("ws://localhost:8080/ws/chat/" + roomId);
if (flvjs.isSupported()) {
const player = flvjs.createPlayer({type: 'flv', url: videoUrl});
player.attachMediaElement(document.getElementById('liveVideo'));
player.load();
player.play();
}
ws.onmessage = function (event) {
const chatBox = document.getElementById("chatBox");
chatBox.innerHTML += `<div>${event.data}</div>`;
chatBox.scrollTop = chatBox.scrollHeight;
};
function sendMessage() {
const input = document.getElementById("chatInput");
if (input.value) {
ws.send(input.value);
input.value = "";
}
}
fetch("/api/room/" + roomId).then(res => res.json()).then(data => {
document.getElementById("title").innerText = data.title;
});
</script>
</body>
</html>
結語
通過本文的實戰內容,我們使用 Spring Boot 框架,集成 SRS 流媒體服務器和 WebSocket 技術,實現了一個從直播間創建、推流、拉流到聊天互動的輕量級直播平臺。該系統適合用于中小型直播場景或企業自建內部直播系統,未來可進一步擴展如直播錄制、轉碼、多路直播、分布式架構等功能。