2025/11/17 18:27:18
录制与回放
声网互动白板 SDK 提供录制与回放功能,支持将实时房间中的所有互动行为录制下来,并支持高质量回放。相较于传统的录屏模式,白板录制和回放具有以下优势:
- 高效录制:采用信令记录方式,相比传统录屏模式占用带宽更少、存储空间更小
- 高质量回放:回放时还原现场效果,画质清晰、动画流畅
- 服务端录制:录制在服务端自动进行,无需客户端额外处理
- 灵活回放:支持指定时间范围回放、播放控制、视角跟随等功能
- 完整记录:录制白板操作、自定义事件、视角变化等所有互动行为
本文介绍如何开启白板录制功能以及如何实现白板内容回放。
技术原理
白板录制
声网互动白板录制不是屏幕录制,而是记录信令与数据增量构成的私有二进制数据。录制过程完全在服务端进行,具有以下优势:
- 自动录制:只需在创建房间时开启录制功能,服务端会自动录制房间内的所有互动行为
- 智能管理:只有在房间活跃时才会生成录制信息,房间无活动时录制会自动停止
- 数据紧凑:录制生成的数据相比传统音视频格式更紧凑,占用存储空间更小
白板回放
白板回放时,SDK 会依照录制的信令与数据增量还原现场,得到的效果和实时互动时一模一样。回放支持:
- 指定时间范围回放
- 播放、暂停、跳转等播放控制
- 视角跟随和自由视角切换
- 自定义事件和全局状态变化的回放
前提条件
开始前,请确保:
- 已在项目中集成声网互动白板 SDK。详见快速开始。
- 已获取有效的 SDK Token 和 Room Token。详见获取互动白板项目的安全密钥。
- 如需在业务服务器上创建房间,请参考房间管理服务端 API。
实现录制功能
开启录制
要开启白板录制功能,需要在创建房间时设置 isRecord: true 参数。以下示例展示如何通过服务端 API 创建支持录制的房间:
JavaScript
// 注意:建议在业务服务器上执行创建房间操作,不要在前端执行
var url = "https://api.netless.link/v5/rooms";
var requestInit = {
method: "POST",
headers: {
"content-type": "application/json",
"token": "NETLESSSDK_YWs9xxxxxxM2MjRi", // 替换为你的 SDK Token
"region": "cn-hz", // 替换为你的数据中心
},
body: JSON.stringify({
name: "我的录制房间",
isRecord: true, // 开启录制功能
}),
};
fetch(url, requestInit).then(function(response) {
return response.json();
}).then(function(roomJSON) {
// 创建房间成功,获取房间信息
console.log("房间 UUID:", roomJSON.uuid);
console.log("房间已开启录制功能");
}).catch(function(err) {
console.error("创建房间失败:", err);
});
注意
- SDK Token 是重要的安全凭证,建议在业务服务器中使用,不要写死在前端代码中。
- 开启录制功能后,该房间内的所有互动行为都会被自动录制。
录制内容
开启录制功能后,以下内容会被自动录制:
- 白板绘制操作(画笔、图形、文字等)
- 场景切换和内容变化
- 图片、MP3、MP4、课件(PPT、DOC)的展示和操作
- 用户视角变化
- 自定义事件(通过
dispatchMagixEvent发送的事件) - 全局状态变化(
GlobalState的修改)
实现回放功能
检查录制内容是否可回放
在创建回放播放器之前,建议先检查指定时间段是否有可回放的录制内容:
JavaScript
var whiteWebSdk = new WhiteWebSdk({
appIdentifier: "RMxxxAQ", // 替换为你的 App Identifier
});
var playableCheckingParams = {
room: "a7xxx69", // 房间 UUID
roomToken: "NETLESSROOM_YWxxxjk", // Room Token
beginTimestamp: new Date("2023-01-01 08:00:00").getTime(), // 回放开始时间
duration: 45 * 60 * 1000, // 回放持续时间(毫秒),这里是 45 分钟
};
whiteWebSdk.isPlayable(playableCheckingParams).then(function(isPlayable) {
if (isPlayable) {
console.log("该时间段有可回放的录制内容");
// 可以创建回放播放器
} else {
console.log("该时间段没有录制内容");
}
}).catch(function(err) {
console.error("检查回放内容失败:", err);
});
创建回放播放器
使用 replayRoom 方法创建回放播放器:
JavaScript
var replayRoomParams = {
room: "a7xxx69", // 房间 UUID
roomToken: "NETLESSROOM_YWxxxjk", // Room Token
beginTimestamp: new Date("2023-01-01 08:00:00").getTime(), // 回放开始时间
duration: 45 * 60 * 1000, // 回放持续时间(毫秒)
};
whiteWebSdk.replayRoom(replayRoomParams).then(function(player) {
// 成功创建回放播放器
console.log("回放播放器创建成功");
// 将播放器绑定到页面元素
player.bindHtmlElement(document.getElementById("whiteboard"));
// 开始播放
player.play();
}).catch(function(err) {
console.error("创建回放播放器失败:", err);
});
播放器控制
回放播放器提供了丰富的播放控制功能:
JavaScript
// 播放控制
player.play(); // 开始播放
player.pause(); // 暂停播放
player.stop(); // 停止播放
// 跳转到指定位置(单位:毫秒,相对于回放开始时间)
player.seekToProgressTime(10 * 60 * 1000) // 跳转到第 10 分钟
.then(function(result) {
console.log("跳转结果:", result);
});
// 设置播放倍速
player.playbackSpeed = 1.5; // 1.5 倍速播放
player.playbackSpeed = 1.0; // 恢复正常速度
// 获取播放状态信息
console.log("当前播放进度:", player.progressTime); // 当前播放位置(毫秒)
console.log("总时长:", player.timeDuration); // 回放总时长(毫秒)
console.log("播放状态:", player.phase); // 播放状态
监听播放器状态变化
可以通过回调函数监听播放器状态的变化:
JavaScript
var playerCallbacks = {
// 播放状态改变回调
onPhaseChanged: function(phase) {
switch(phase) {
case "playing":
console.log("正在播放");
break;
case "pause":
console.log("已暂停");
break;
case "buffering":
console.log("正在缓冲");
break;
case "ended":
console.log("播放结束");
break;
}
},
// 播放进度改变回调
onProgressTimeChanged: function(progressTime) {
console.log("当前播放进度:", progressTime + "ms");
},
// 播放出错回调
onStoppedWithError: function(error) {
console.error("播放出错:", error);
}
};
// 创建播放器时注册回调
whiteWebSdk.replayRoom(replayRoomParams, playerCallbacks).then(function(player) {
// 播放器创建成功
});
视角控制
回放时可以控制观看视角:
JavaScript
// 设置观看模式
player.setObserverMode("directory"); // 跟随模式,跟随录制时的视角变化
player.setObserverMode("freedom"); // 自由模式,可以自由调整视角
// 禁止用户调整视角
player.disableCameraTransform = true; // 禁止用户通过手势调整视角
player.disableCameraTransform = false; // 允许用户调整视角
回放自定义事件
如果录制时发送了自定义事件,回放时也可以监听这些事件:
JavaScript
// 监听回放中的自定义事件
player.addMagixEventListener("Greetings", function(event) {
console.log("回放中收到自定义事件:", event.payload);
});
// 监听全局状态变化
var playerCallbacks = {
onPlayerStateChanged: function(modifyState) {
if (modifyState.globalState) {
console.log("全局状态发生变化:", modifyState.globalState);
}
}
};
使用 React 展示回放
如果你使用 React 框架,可以使用 white-react-sdk 更方便地展示回放内容:
React JSX
import React from "react";
import { PlayerWhiteboard } from "white-react-sdk";
class ReplayComponent extends React.Component {
render() {
const style = {
width: "100%",
height: "100vh",
};
return (
<PlayerWhiteboard
player={this.props.player}
style={style}
/>
);
}
}
完整示例
以下是一个完整的录制和回放示例:
html
<!DOCTYPE html>
<html>
<head>
<title>白板录制与回放示例</title>
<script src="https://sdk.netless.link/white-web-sdk/2.16.51.js"></script>
</head>
<body>
<div>
<button onclick="createRecordingRoom()">创建录制房间</button>
<button onclick="startReplay()">开始回放</button>
<button onclick="pauseReplay()">暂停回放</button>
<button onclick="resumeReplay()">继续回放</button>
</div>
<div id="whiteboard" style="width: 100%; height: 500px; border: 1px solid #ccc;"></div>
<script>
var whiteWebSdk = new WhiteWebSdk({
appIdentifier: "RMxxxAQ", // 替换为你的 App Identifier
});
var player = null;
// 创建录制房间
function createRecordingRoom() {
// 注意:实际项目中应该在服务端创建房间
var url = "https://api.netless.link/v5/rooms";
var requestInit = {
method: "POST",
headers: {
"content-type": "application/json",
"token": "NETLESSSDK_YWs9xxxxxxM2MjRi", // 替换为你的 SDK Token
"region": "cn-hz",
},
body: JSON.stringify({
name: "录制房间示例",
isRecord: true, // 开启录制
}),
};
fetch(url, requestInit).then(function(response) {
return response.json();
}).then(function(roomJSON) {
console.log("录制房间创建成功:", roomJSON);
alert("录制房间创建成功,UUID: " + roomJSON.uuid);
}).catch(function(err) {
console.error("创建房间失败:", err);
});
}
// 开始回放
function startReplay() {
var replayRoomParams = {
room: "a7xxx69", // 替换为实际的房间 UUID
roomToken: "NETLESSROOM_YWxxxjk", // 替换为实际的 Room Token
beginTimestamp: new Date("2023-01-01 08:00:00").getTime(),
duration: 45 * 60 * 1000, // 45 分钟
};
var playerCallbacks = {
onPhaseChanged: function(phase) {
console.log("播放状态:", phase);
},
onProgressTimeChanged: function(progressTime) {
console.log("播放进度:", Math.floor(progressTime / 1000) + "秒");
}
};
whiteWebSdk.replayRoom(replayRoomParams, playerCallbacks).then(function(replayPlayer) {
player = replayPlayer;
player.bindHtmlElement(document.getElementById("whiteboard"));
player.play();
console.log("开始回放");
}).catch(function(err) {
console.error("回放失败:", err);
});
}
// 暂停回放
function pauseReplay() {
if (player) {
player.pause();
console.log("暂停回放");
}
}
// 继续回放
function resumeReplay() {
if (player) {
player.play();
console.log("继续回放");
}
}
</script>
</body>
</html>
参考信息
开发注意事项
在使用录制与回放功能时,需要注意以下几点:
- 录制延时:录制内容不是实时生成的,新创建的房间可能需要等待一段时间才能获得录制内容
- 时间范围:建议根据实际使用场景设置合适的回放时间范围,避免回放过长的无效内容
- 网络缓冲:回放时可能需要网络缓冲,特别是跳转到较远时间点时
- 存储成本:长期开启录制功能会产生存储成本,建议根据业务需要合理使用
- 播放器释放:使用完毕后记得调用
player.stop()释放播放器资源
错误处理
常见错误及处理方法:
JavaScript
whiteWebSdk.replayRoom(replayRoomParams).then(function(player) {
// 成功
}).catch(function(err) {
if (err.message.includes("couldn't find any matching slices")) {
console.log("录制内容还未生成,请稍后再试");
} else {
console.error("回放失败:", err.message);
}
});
API 参考
WhiteWebSdk.replayRoom- 创建回放播放器WhiteWebSdk.isPlayable- 检查是否可回放Player.play- 开始播放Player.pause- 暂停播放Player.seekToProgressTime- 跳转播放位置Player.setObserverMode- 设置观看模式PlayerCallbacks- 播放器回调
相关文档
- 房间管理服务端 API - 创建房间 API
- 互动白板 Token 概述 - Token 相关说明
- 创建自定义事件 - 自定义事件使用指南