后端服务已基于 ZLMediaKit 框架搭建,现在我们来探讨前端如何接入并播放这些直播流。在实际项目中,我们通常有两种主流选择:使用官方提供的原生 SDK,或者集成成熟的第三方播放器。
一、原生 WebRTC 播放器(ZLMRTCClient)
如果你希望最小化依赖,直接使用 ZLMediaKit 配套的 ZLMRTCClient.js 是最直接的方式。这里以 1.0.2 版本为例,需要注意不同版本的初始化方式可能有所差异。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebRTC 播放示例</title>
<!-- 引入官方 SDK -->
<script src="http://117.40.242.70:35080/ZLMRTCClient.js"></script>
</head>
<body>
<video id="videoPlayer" autoplay controls></video>
<script>
// 1. 获取视频元素
const videoElement = document.getElementById('videoPlayer');
// 2. 配置参数
const config = {
element: videoElement, // 绑定播放容器(必填)
debug: true, // 开启调试日志
zlmsdpUrl: 'http://117.40.242.70:35080/index/api/webrtc?app=live&stream=test1&type=play', // 后端流地址
simulcast: false, // 不启用 simulcast
useCamera: false, // 纯播放模式
audioEnable: true,
videoEnable: true,
recvOnly: true, // 仅接收
resolution: { w: 800, h: 450 },
usedatachannel: false
};
// 3. 创建实例(1.0.2 版本使用 Endpoint)
const rtcClient = new ZLMRTCClient.Endpoint(config);
// 4. 监听事件
rtcClient.on('error', (err) => console.error('错误:', err));
rtcClient.on('webrtcNotSupport', () => alert('浏览器不支持 WebRTC'));
let remoteStream = null;
rtcClient.on('WEBRTC_ON_REMOTE_STREAMS', (event) => {
console.log('收到远程流');
if (videoElement.srcObject !== event.streams) {
videoElement.srcObject = event.streams[0];
remoteStream = event.streams[0];
}
});
rtcClient.on('WEBRTC_ON_CONNECTION_STATE_CHANGE', (state) => {
console.log('连接状态:', state);
});
// 停止播放逻辑
function stop() {
if (!rtcClient) return;
videoElement.pause();
videoElement.srcObject = null;
if (remoteStream) {
remoteStream.getTracks().forEach(track => track.stop());
remoteStream = null;
}
if (rtcClient.disconnect) rtcClient.disconnect();
else if (rtcClient.close) rtcClient.close();
rtcClient = null;
}
</script>
</body>
</html>
开发注意:
- 版本差异:实例化对象时,旧版可能用
new ZLMRTCClient(),而 1.0.2 推荐使用Endpoint类。 - 资源清理:务必在页面关闭或停止播放时调用
disconnect并停止媒体轨道,否则可能导致内存泄漏或摄像头占用。
二、使用开源播放器 EasyPlayer
如果项目对功能有更高要求,比如需要截图、录制或更复杂的 UI 控制,EasyPlayer 是个不错的选择。它封装了底层逻辑,提供了更友好的 API。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>EasyPlayer 演示</title>
<script src="./js/EasyPlayer-pro.js"></script>
<style>
.player_item { position: relative; padding-bottom: 56%; background-color: black; margin-bottom: 20px; }
.player_box { position: absolute; top: 0; bottom: 0; right: 0; left: 0; }
.inputs { width: 100%; max-width: 600px; height: 36px; border: 1px solid #dcdfe6; padding: 0 15px; }
.btn-item { cursor: pointer; padding: 6px 12px; border-radius: 4px; border: 1px #ccc solid; margin-right: 15px; }
.df { display: flex; align-items: center; margin-bottom: 16px; }
.box { padding-top: 10px; margin: auto; max-width: 800px; }
</style>
</head>
<body>
<div class="box">
<h2>EasyPlayerPro 案例演示</h2>
<div class="player_item"><div id="player_box" class="player_box"></div></div>
<div class="df">
<input type="checkbox" id="hasAudio" /><span>音频</span>
</div>
<input type="text" id="input" class="inputs" value="ws://localhost:6230/ws_flv/live/stream_1_0.flv">
<div class="df">
<button id="onPlayer" class="btn-item">播放</button>
<button id="onReplay" class="btn-item">重播</button>
<button id="onMute" class="btn-item">静音</button>
<button id="onStop" class="btn-item">注销</button>
</div>
</div>
<script>
window.onload = function () {
var playerInfo = null;
var config = { stretch: true, hasAudio: true };
playCreate();
var input = document.getElementById('input');
var audio = document.getElementById('hasAudio');
var player = document.getElementById('onPlayer');
var replay = document.getElementById('onReplay');
var mute = document.getElementById('onMute');
var stop = document.getElementById('onStop');
if (config.hasAudio) audio.checked = true;
audio.onclick = () => { config.hasAudio = audio.checked; };
player.onclick = onPlayer;
replay.onclick = onReplay;
mute.onclick = onMute;
stop.onclick = onStop;
function playCreate() {
var container = document.getElementById('player_box');
playerInfo = new EasyPlayerPro(container, config);
}
function onPlayer() {
playerInfo && playerInfo.play(input.value).catch(e => console.error(e));
}
function onMute() {
if (!playerInfo) return;
playerInfo.setMute(true);
}
function onReplay() {
onDestroy().then(() => { playCreate(); onPlayer(); });
}
function onDestroy() {
return new Promise((resolve) => {
if (playerInfo) {
playerInfo.destroy();
playerInfo = null;
}
setTimeout(resolve, 100);
});
}
function onStop() {
onDestroy().then(() => { playCreate(); });
}
};
</script>
</body>
</html>
开发注意:
- ID 匹配:确保 HTML 元素的 ID 与 JS 中
getElementById的查询一致,这是新手最容易踩坑的地方。 - 异步处理:销毁和重建播放器涉及异步操作,建议配合 Promise 管理流程,避免状态冲突。
两种方案各有优劣,原生 SDK 轻量但需自行处理细节,EasyPlayer 功能丰富但依赖外部库。根据实际业务需求选择即可。

