我们已注意到 Google 披露的 WebRTC 版本中存在的漏洞(更多信息请参见此处),并正在调查它对 EOS SDK 的影响以及接下来应采取的措施。
像素流送信令和Web服务器提供示例播放器页面,该页面已经设置为从虚幻引擎应用程序进行媒体流送,并将鼠标、键盘和触摸事件发送回应用程序。(如需说明,请参阅入门指南。)如果此默认播放器页面符合你的需求,可以直接使用它。
最近对像素流送的一些更改已将像素流送的前端和Web服务器元素移至外部仓库。我们将其称作像素流送基础设施。
访问像素流送基础设施的方法有多种。
- 从以下地址直接访问github仓库:https://github.com/EpicGames/PixelStreamingInfrastructure
- 在你偏好的终端中执行
git clone --branch UE5.1 https://github.com/EpicGames/PixelStreamingInfrastructure.git
(确保你安装了git)。 - 找到
\Engine\Plugins\Media\PixelStreaming\Resources\WebServers
并运行get_ps_servers
命令(确保将相应的.bat
脚本用于Windows,将相应的.sh
脚本用于Linux)。这会自动将相关像素流送基础设施分支提取到该文件夹中。
上述git命令将提取基础设施的5.1分支。如果你需要不同的分支,请相应修改git命令。
有关像素流送前端和Web服务器更改的更多详情,请参阅像素流送基础设施
不过,只要了解一些Web技术的知识,比如JavaScript和HTML,再加上一点创造力,你就可以玩转播放器页面,创建自己的自定义UI,与你的虚幻引擎内容远程交互。你可以触发和响应Gameplay事件,发出控制台命令以控制虚幻引擎的行为,等等。
建议开始时使用默认播放器页面来创建自己的自定义播放器页面。此默认播放器页面位于你的虚幻引擎安装文件夹下的 PixelStreamingInfrastructure\SignallingWebServer\Public\player.html
。然后阅读此页面上的信息,了解如何扩展你的页面,并将其与你项目的Gameplay逻辑关联起来。
此外,如果你已经克隆了像素流送基础设施仓库并对上游做了更改,可以叉取该仓库并提出拉取请求。
默认播放器页面
使用HTML5 UI自定义播放器
HTML页面要求
你的自定义HTML播放器页面必须符合几个最低要求。
-
必须包含
/scripts/webRtcPlayer.js
文件。此文件处理浏览器与虚幻引擎应用程序之间的通信,接收并显示来自服务器的媒体流。仅可在绝对必要的情况下修改此JavaScript文件。<script type="text/javascript" src="scripts/webRtcPlayer.js"></script>
-
强烈建议将 /scripts/app.js 文件也包含在内。此文件设置用于处理键盘、鼠标和触摸事件的事件监听器。它还包含几个可以在播放器页面中使用的函数和钩,相关情况在本页下文中介绍。 如果你对JavaScript有一定的了解,你尽可研究此文件的代码,并修改默认行为以满足你的需求。举例而言,如要禁用键盘输入但保持鼠标和触摸事件的正常运行,需寻找处理键盘事件的代码并对其进行注解,以自定义该文件。
<script type="text/javascript" src="scripts/app.js"></script>
-
此页面必须有一个ID为
player
的div
元素。该元素会替换为从UE5应用程序流送的视频帧。<div id="player"></div>
-
页面加载时,必须调用
app.js
文件提供的load
函数。例如,将onload
句柄添加到body
标签就可以做到这一点:<body onload="load()">
播放器文件位置和URL
自定义HTML播放器页面的放置位置以及客户端浏览器访问该页面的方法都有数个选项可供选择。
- 可以在信令和Web服务器的根文件夹中创建一个名为
custom_html
的文件夹,将你的自定义HTML播放器页面放到其中。然后将其文件名附加到运行信令和Web服务器的计算机的IP地址或主机名上,便可访问该页面。 例如,名为custom_html/myplayerpage.html
的文件可在http://127.0.0.1/myplayerpage.html
处访问。 - 可以为信令和Web服务器自定义
HomepageFile
参数,并将路径设置为与信令和Web服务器相关的自定义HTML播放器页面的文件名。然后,当你访问运行信令和Web服务器的计算机的IP地址或主机名时,便可访问该页面。 例如,如果你将一个文件保存到Engine/Source/Programs/PixelStreaming/WebServers/SignallingWebServer/myfolder/myplayerpage.html
,并将HomepageFile
参数设置为myfolder/myplayerpage.html
,则无需在URLhttp://127.0.0.1/
中提供文件名即可访问该页面。 - 你也可以使用 AdditionalRoutes 参数为信令和Web服务器自定义URL路径与计算机本地文件夹之间的映射。
有关这些参数的更多详情,另请参阅像素流送参考。
自定义播放器输入选项
app.js
文件提供了一些JavaScript配置参数,可以在你的自定义播放器页面中覆盖这些参数,以控制播放器控件响应用户交互的方式。inputOptions
对象公开以下属性:
属性 | 默认值 | 说明 |
---|---|---|
controlScheme | ControlSchemeType.LockedMouse |
确定在播放器与控件交互时,播放器控件是否捕获并锁定鼠标。接受以下值:
|
suppressBrowserKeys | true | 启用此设置后,播放器控件将拦截功能键( F1 到 F12 )以及 Tab 键,并将这些按键事件传递给虚幻引擎应用程序,而非让浏览器正常处理它们。 举个例子,当此设置激活时,按 F5 将不会刷新浏览器中的播放器页面。该事件将被传递到虚幻引擎应用程序,其常规功能是切换视图以显示着色器复杂度。 |
fakeMouseWithTouches | false | 若启用此选项,当用户正在触摸屏设备(例如智能手机或平板电脑)上查看流送的内容时,此设置会导致虚幻引擎应用程序将单指触摸事件解译为鼠标点击和拖动事件。启用此设置时,即使应用程序的输入控制器并未专门处理触摸输入事件,使用移动设备的用户也可以部分控制你的虚幻引擎应用程序。 |
如下所示,你可以包含一些代码块,以在播放器页面中设置这些值。确保在将 app.js
文件加载到页面之后,但在调用 load
函数之前,运行此代码。
<script>
inputOptions.controlScheme = ControlSchemeType.HoveringMouse;
inputOptions.fakeMouseWithTouches = true;
</script>
禁用用户输入
要完全禁用一种或多种输入设备的用户输入,可以在JavaScript环境中使用空白实现覆盖播放器页面的以下函数:
- registerHoveringMouseEvents - 当inputOptions.controlScheme设置为ControlSchemeType.HoveringMouse时,禁用所有输入鼠标事件。
- registerLockedMouseEvents - 当inputOptions.controlScheme设置为ControlSchemeType.LockedMouse时,禁用所有输入鼠标事件。
- registerTouchEvents - 禁用移动设备和平板电脑上的触摸事件。
- registerKeyboardEvents - 禁用所有键盘事件。
例如,可以在你的播放器HTML页面中包含此JavaScript块,以禁用所有输入。如上所述,在将 app.js
文件加载到页面之后,但在调用 load
函数之前,运行此代码。
<script>
registerHoveringMouseEvents = function() {}
registerLockedMouseEvents = function() {}
registerTouchEvents = function() {}
registerKeyboardEvents = function() {}
</script>
要将一个或多个输入类型保持为激活,则将要保持的输入类型所对应的行注解掉,或将该行删除。
自定义播放器控件样式
在自定义HTML播放器页面中,应定义像素流送播放器控件为: id="player"
的 div
元素。可以使用标准HTML和CSS方法向该控件添加样式。
有时可能需要重新初始化控件的大小。这种情况通常发生在调整浏览器窗口大小时(如果控件设置为自动填充可用空间),或在更新输入视频流的分辨率时。发生这种情况时,播放器元素的 style
属性将被新值覆盖,可能会覆盖掉你在自己的HTML或JavaScript中设置的值。
为避免这种情况,可以在名为 styleAdditional
的特殊全局变量中设置你的自定义CSS值。每当 app.js
需要调整播放器大小并清除其样式时,它会将你在 styleAdditional
变量中设置的值附加到它分配给播放器元素的新样式属性的末尾。例如,当用户将鼠标悬停在播放器控件上方时,以下值会将鼠标光标更改为手的形状:
styleAdditional = 'cursor: grab; cursor: -moz-grab; cursor: -webkit-grab';
访问像素流蓝图API
虚幻引擎中运行的像素流送插件会公开一个蓝图API,你可以在Gameplay逻辑中用它来处理由播放器HTML页面发送的自定义UI事件,并将事件从虚幻引擎发送到播放器页面。
要访问该蓝图API,将 PixelStreamingInputComponent 添加到你关卡中的Actor。你应用程序的 玩家控制器(PlayerController) 是一个安全选项。要做到这一点,可以点击蓝图菜单中的 添加组件(Add Component) ,并从下拉菜单中选择 像素流送输入(Pixel Streaming Input) 组件。
点击查看大图。
UE 4.27之前的版本中,加载像素流送插件时会自动添加PixelStreamingInput组件。这种方法存在问题,现在需要用户自己将其添加到项目中,如上所示。
从播放器页面到UE5的通信
App.js
文件提供两个JavaScript函数,可以在你的HTML播放器页面中调用,从而使用户能够将事件和命令从浏览器中发送到虚幻引擎应用程序:
- 可以使用
emitCommand
将控制台命令发送回虚幻引擎。例如,发送stat fps
显示帧率。请参阅下方的使用emitCommand函数。 emitUIInteraction
可将任意字符串或JavaScript对象发送至游戏。使用此函数从播放器UI发送你自己的自定义命令,可以在你的Gameplay逻辑中响应该命令,从而在你的应用程序中产生需要的效果。请参阅下方的使用emitUIInteraction函数。
使用emitCommand函数
调用 emitCommand
函数时,必须向它传递一个JavaScript对象。此对象必须包含与以下字符串之一匹配的键:
-
ConsoleCommand
- 使用此键在远程虚幻引擎应用程序上执行控制台命令。此键的值应是一个字符串,其中包含要运行的命令及其所需的参数。例如:let descriptor = { ConsoleCommand: 'stat fps' } emitCommand(descriptor);
由于虚幻引擎控制台命令的功能十分强大, emitCommand
函数可能会带来安全风险。为使此函数正常工作,在启动你的虚幻引擎应用程序或使用独立游戏(Standalone Game)选项从虚幻编辑器中启动该应用程序时,你还需要在命令行上提供 -AllowPixelStreamingCommands
参数。
使用emitUIInteraction函数
调用 emitUIInteraction
函数时,可以向它传递单个字符串或JavaScript对象。例如:
emitUIInteraction("MyCustomCommand");
或
let descriptor = {
LoadLevel: "/Game/Maps/Level_2"
PlayerCharacter: {
Name: "Shinbi"
Skin: "Dynasty"
}
}
emitUIInteraction(descriptor);
如果传递JavaScript对象, emitUIInteraction
函数会在内部将其转换为JSON字符串。然后它将生成的字符串传递回虚幻引擎应用程序中的像素流送插件,从而在输入控制器上引发一个事件。在你的应用程序Gameplay逻辑中,使用 Bind Event to OnPixelStreamingInputEvent 节点绑定你自己的自定义事件,以处理这些输入。例如:
点击查看大图。
你需要绑定一次该事件,通常是在启动游戏时。每当连接到你虚幻引擎应用程序实例的播放器HTML页面调用 emitUIInteraction
函数时,将无视传递到 emitUIInteraction
的输入,自动调用你的自定义事件。
你分配的自定义事件(例如上图中的 UI Interaction 节点)有一个名为 Descriptor 的输出,可以使用该输出检索 emitUIInteraction
函数发送到你的虚幻引擎应用程序的字符串。可以使用该值确定每次调用 emitUIInteraction
时Gameplay代码的响应方式。
例如,执行以下蓝图测试,检查发送给 emitUIInteraction
的输入是否包含字符串 "MyCustomCommand" ,并调用自定义函数以处理该事件:
点击查看大图。
如果你原本将JavaScript对象传递给 emitUIInteraction
,可以使用 Pixel Streaming > Get Json String Value 节点检索该JSON对象的任意键值。例如,以下蓝图将测试名为LoadLevel的键。如果该键存在,它会调用自定义函数来处理该事件:
点击查看大图。
如需检索嵌套键,让你的键使用JavaScript中常见的点符号。例如 PlayerCharacter.Name
或 PlayerCharacter.Skin
。
从UE5到播放器页面的通信
虚幻引擎应用程序可以向所有连接的播放器HTML页面发送自定义事件,你可在播放器的JavaScript环境中响应这些事件。这样,你可以根据Gameplay事件更改网页UI。
要执行此设置:
- 在虚幻引擎应用程序中,每当要向播放器页面发送事件时,使用 Pixel Streaming > Send Pixel Streaming Response 节点。向该节点指定一个自定义字符串参数,以向播放器页面表明已发生的事件。
点击查看大图。
-
在播放器页面的JavaScript中,你将需要写入一个自定义事件处理程序函数,每当该页面从虚幻引擎应用程序收到响应事件时,都将调用此函数。它会收到由 Send Pixel Streaming Response 节点发送的原始字符串参数。例如:
function myHandleResponseFunction(data) { console.warn("Response received!"); switch (data) { case "MyCustomEvent": ...// 处理一种事件类型 case "AnotherEvent": ...// 处理另一个事件 } }
-
调用
app.js
提供的addResponseEventListener
函数来注册监听器函数。为事件监听器向此函数传递一个唯一名称以及你的函数。例如:addResponseEventListener("handle_responses", myHandleResponseFunction);
-
如果需要移除你的事件监听器,可调用
removeResponseEventListener
并传递同一名称。例如:removeResponseEventListener("handle_responses");
若要传递更复杂的数据,可以将你传递给 Send Pixel Streaming Response 节点的字符串格式化为JSON。例如:

然后在JavaScript事件处理程序函数中,使用 JSON.parse(data)
将字符串解码回JavaScript对象中。
非活跃连接超时
在部分像素流送部署类型中,可能需自动断开一段时间内非活跃的用户。例如,若虚幻引擎应用程序的可用池较为有限,并且可以访问由配对服务器控制的那些实例,你可能需要放弃旧的非活跃连接,以确保有可用的应用程序实例来处理新传入的连接请求。
可以配置你的像素流送播放器页面来检测用户离开键盘(AFK),即用户在自定义时间间隔内未与播放器控件交互。AFK系统警告用户:

若用户持续无响应,AFK系统最终会断开会话。
一旦用户与播放器面板交互,就会重置AFK定时器。这包括移动和拖动鼠标、按动鼠标按键、按键盘、移动设备上的触摸事件,以及使用 emitCommand
和 emitUIInteraction
函数设置的自定义交互。
要使用AFK系统,在播放器页面的JavaScript中设置以下三个属性。在加载 app.js
文件之后,但在调用其 load
函数之前,执行该操作。
属性 | 说明 |
---|---|
afk.enabled |
确定AFK系统是否应检查用户交互。默认值为 false ;将此值设置为 true 会使非活跃连接超时。 |
afk.warnTimeout |
设置用户可持续离开键盘的最大时间间隔(单位为秒),超过此间隔将在播放器控件中显示警告覆层。默认值为 120 ,即两分钟。 |
afk.closeTimeout |
超过 afk.warnTimeout 间隔后,用户会看到一条警告即将断开连接的消息,此变量将设置时间间隔(单位为秒),除非用户与播放器控件交互,否则在该时间间隔之后用户的连接将自动断开。默认值为 10 。 |
若要自定义覆层内容,你可以在播放器页面中重新定义 updateAfkOverlayText()
函数。在你的实现中,将 afk.overlay.innerHTML
属性设置为当用户离开时间超过AFK超时值时你要让播放器控件显示的HTML。