├── .backportrc.json ├── .changeset ├── README.md ├── config.json ├── red-turtles-cross.md ├── sweet-foxes-remain.md └── weak-files-wait.md ├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature.md │ └── question.md ├── pull_request_template.md └── workflows │ ├── backport.yml │ ├── changesets-publish-npm-packages.yml │ ├── changesets-update-changelogs.yml │ ├── create-gh-release.yml │ ├── healthcheck-frontend.yml │ ├── healthcheck-image-sfu.yml │ ├── healthcheck-image-wilbur.yml │ ├── healthcheck-libraries.yml │ ├── healthcheck-libs-with-public-deps.yml │ ├── healthcheck-markdown-links.yml │ ├── healthcheck-platform-scripts.yml │ ├── healthcheck-signalling-protocol.yml │ ├── healthcheck-streaming.yml │ ├── publish-container-images.yml │ ├── publish-sfu-image.yml │ └── stale.yml ├── .gitignore ├── .lintstagedrc.mjs ├── .prettierrc.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Common ├── .gitignore ├── .lintstagedrc.mjs ├── .npmignore ├── .prettierignore ├── CHANGELOG.md ├── README.md ├── docs │ ├── Event │ │ └── EventEmitter │ │ │ ├── README.md │ │ │ └── classes │ │ │ └── EventEmitter.md │ ├── Logger │ │ └── Logger │ │ │ ├── README.md │ │ │ ├── classes │ │ │ ├── LoggerContext.md │ │ │ └── LoggerType.md │ │ │ ├── enumerations │ │ │ └── LogLevel.md │ │ │ ├── functions │ │ │ └── overrideLogger.md │ │ │ ├── interfaces │ │ │ └── ILogger.md │ │ │ └── variables │ │ │ └── Logger.md │ ├── Messages │ │ ├── base_message │ │ │ ├── README.md │ │ │ └── interfaces │ │ │ │ └── BaseMessage.md │ │ ├── message_helpers │ │ │ ├── README.md │ │ │ └── functions │ │ │ │ ├── createMessage.md │ │ │ │ └── validateMessage.md │ │ └── message_registry │ │ │ ├── README.md │ │ │ └── variables │ │ │ └── MessageRegistry.md │ ├── Protocol.md │ ├── Protocol │ │ ├── KeepaliveMonitor │ │ │ ├── README.md │ │ │ └── classes │ │ │ │ └── KeepaliveMonitor.md │ │ └── SignallingProtocol │ │ │ ├── README.md │ │ │ └── classes │ │ │ └── SignallingProtocol.md │ ├── README.md │ ├── Transport │ │ ├── ITransport │ │ │ ├── README.md │ │ │ └── interfaces │ │ │ │ └── ITransport.md │ │ ├── WebSocketTransport │ │ │ ├── README.md │ │ │ └── classes │ │ │ │ └── WebSocketTransport.md │ │ └── WebSocketTransportNJS │ │ │ ├── README.md │ │ │ └── classes │ │ │ └── WebSocketTransportNJS.md │ ├── Util │ │ └── SdpUtils │ │ │ ├── README.md │ │ │ └── classes │ │ │ └── SDPUtils.md │ ├── messages.md │ └── pixelstreamingcommon │ │ └── README.md ├── eslint.config.mjs ├── package.json ├── protobuf │ ├── CHANGELOG.md │ └── signalling_messages.proto ├── src │ ├── Event │ │ └── EventEmitter.ts │ ├── Logger │ │ └── Logger.ts │ ├── Messages │ │ ├── base_message.ts │ │ ├── message_helpers.ts │ │ ├── message_registry.ts │ │ └── signalling_messages.ts │ ├── Protocol │ │ ├── KeepaliveMonitor.ts │ │ └── SignallingProtocol.ts │ ├── Transport │ │ ├── ITransport.ts │ │ ├── WebSocketTransport.ts │ │ └── WebSocketTransportNJS.ts │ ├── Util │ │ └── SdpUtils.ts │ └── pixelstreamingcommon.ts ├── tsconfig.cjs.json ├── tsconfig.esm.json └── tsconfig.json ├── Docs ├── README.md ├── Resources │ └── Images │ │ └── pixelstreamingplayerblueprint.png ├── Security-Guidelines.md └── pixel-streaming-2-migration-guide.md ├── Extras ├── FrontendTests │ ├── .gitignore │ ├── README.md │ ├── docker-compose.yml │ ├── dockerfiles │ │ └── linux │ │ │ └── Dockerfile │ ├── package.json │ ├── playwright.config.ts │ └── tests │ │ ├── basic_stream.spec.ts │ │ ├── extras.ts │ │ ├── fixtures.ts │ │ ├── helpers.ts │ │ ├── keyboard.spec.ts │ │ ├── matchers.ts │ │ ├── mouse.spec.ts │ │ ├── peerconnection.spec.ts │ │ └── resolution_changes.spec.ts ├── JSStreamer │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.json │ ├── Dockerfile │ ├── README.md │ ├── eslint.config.mjs │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.ts │ │ ├── pixelstreamingjsstreamer.ts │ │ ├── protocol.ts │ │ ├── streamer.ts │ │ └── video │ │ │ └── big-buck-bunny_trailer.webm │ ├── tsconfig.cjs.json │ ├── tsconfig.esm.json │ ├── tsconfig.json │ └── webpack.config.js ├── MinimalStreamTester │ ├── .gitignore │ ├── README.md │ ├── docker-compose.yml │ ├── dockerfiles │ │ ├── linux │ │ │ └── Dockerfile │ │ └── windows │ │ │ └── Dockerfile │ ├── package.json │ ├── playwright.config.ts │ └── tests │ │ └── stream_test.spec.ts ├── SS_Test │ ├── .gitignore │ ├── Dockerfile │ ├── docker-compose.yml │ ├── package.json │ ├── run_tests.sh │ ├── src │ │ ├── config.js │ │ ├── index.ts │ │ └── signalling_tester.ts │ └── tsconfig.json ├── Scripts │ └── pre-commit-checks.sh ├── StreamerDocker │ ├── Linux │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── build.sh │ │ └── extract-and-install-deps.py │ └── Windows │ │ ├── Dockerfile │ │ └── README.md ├── eslint │ └── plugin-check-copyright │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json └── mediasoup-sdp-bridge │ ├── .eslintrc.js │ ├── .github │ └── FUNDING.yml │ ├── .gitignore │ ├── .npmrc │ ├── .prettierignore │ ├── .prettierrc │ ├── .travis.yml │ ├── LICENSE │ ├── NOTES.md │ ├── README.md │ ├── npm-scripts.js │ ├── package.json │ ├── src │ ├── BrowserRtpCapabilities.ts │ ├── SdpUtils.ts │ └── index.ts │ ├── tools │ └── browser-rtpcapabilities │ │ └── README.md │ └── tsconfig.json ├── Frontend ├── .gitignore ├── Docs │ ├── Accessing the Pixel Streaming Blueprint API.md │ ├── Communicating from UE5 to the Player Page.md │ ├── Communicating from the Player Page to UE5.md │ ├── Customizing Player Input Options.md │ ├── Customizing the Player Webpage.md │ ├── Customizing the Player Widget Style.md │ ├── HTML Page Requirements.md │ ├── README.md │ ├── Resources │ │ └── Images │ │ │ ├── add-pixel-streaming-to-actor.png │ │ │ ├── afk-warning.png │ │ │ ├── mic-toggle.png │ │ │ ├── pixelstreaming-add-component.jpg │ │ │ ├── pixelstreaming-bpapi.png │ │ │ ├── pixelstreaming-custom-topic.png │ │ │ ├── pixelstreaming-getcomponentbyclass.png │ │ │ ├── pixelstreaming-input.jpg │ │ │ ├── pixelstreaming-send-game-event-json.png │ │ │ ├── pixelstreaming-send-game-event.png │ │ │ ├── pixelstreaming-ui-interaction-event.png │ │ │ ├── pixelstreaming-ui-interaction-extract-json.png │ │ │ ├── pixelstreaming-ui-interaction-search-substring.png │ │ │ ├── send_pixel_streaming_response.JPG │ │ │ ├── settings-panel.png │ │ │ └── settings-pixel-streaming-audio.png │ ├── Settings Panel.md │ ├── Timing Out Inactive Connections.md │ ├── Typing into streamed text inputs.md │ ├── Using the Camera Feature.md │ └── Using the Microphone Feature.md ├── README.md ├── implementations │ ├── angular │ │ └── readme.md │ ├── react │ │ ├── .prettierignore │ │ ├── .prettierrc.json │ │ ├── package.json │ │ ├── readme.md │ │ ├── src │ │ │ ├── assets │ │ │ │ └── images │ │ │ │ │ ├── favicon-16x16.png │ │ │ │ │ ├── favicon-32x32.png │ │ │ │ │ ├── favicon-96x96.png │ │ │ │ │ ├── favicon.ico │ │ │ │ │ └── favicon.png │ │ │ ├── components │ │ │ │ ├── App.tsx │ │ │ │ └── PixelStreamingWrapper.tsx │ │ │ ├── index.html │ │ │ └── index.tsx │ │ ├── tsconfig.json │ │ ├── webpack.common.js │ │ ├── webpack.dev.js │ │ └── webpack.prod.js │ └── typescript │ │ ├── package.json │ │ ├── readme.md │ │ ├── src │ │ ├── assets │ │ │ ├── css │ │ │ │ ├── login.css │ │ │ │ ├── showcase.css │ │ │ │ └── stresstest.css │ │ │ └── images │ │ │ │ ├── Aurora.jpg │ │ │ │ ├── Crunch.jpg │ │ │ │ ├── favicon-16x16.png │ │ │ │ ├── favicon-32x32.png │ │ │ │ ├── favicon-96x96.png │ │ │ │ ├── favicon.ico │ │ │ │ └── favicon.png │ │ ├── player.html │ │ ├── player.ts │ │ ├── showcase.html │ │ ├── showcase.ts │ │ ├── stresstest.html │ │ ├── stresstest.ts │ │ ├── uiless.html │ │ └── uiless.ts │ │ ├── tsconfig.cjs.json │ │ ├── tsconfig.esm.json │ │ ├── tsconfig.json │ │ ├── webpack.base.js │ │ ├── webpack.dev.js │ │ ├── webpack.esmodule.js │ │ └── webpack.prod.js ├── library │ ├── .cspell.json │ ├── .lintstagedrc.mjs │ ├── .npmignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── eslint.config.mjs │ ├── jest.config.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── AFK │ │ │ ├── AFKController.test.ts │ │ │ └── AFKController.ts │ │ ├── Config │ │ │ ├── Config.test.ts │ │ │ ├── Config.ts │ │ │ ├── SettingBase.ts │ │ │ ├── SettingFlag.ts │ │ │ ├── SettingNumber.ts │ │ │ ├── SettingOption.ts │ │ │ └── SettingText.ts │ │ ├── DataChannel │ │ │ ├── DataChannelController.ts │ │ │ ├── DataChannelLatencyTestController.ts │ │ │ ├── DataChannelLatencyTestResults.ts │ │ │ ├── DataChannelSender.ts │ │ │ ├── InitialSettings.ts │ │ │ └── LatencyTestResults.ts │ │ ├── FreezeFrame │ │ │ ├── FreezeFrame.ts │ │ │ └── FreezeFrameController.ts │ │ ├── Inputs │ │ │ ├── GamepadController.ts │ │ │ ├── GamepadTypes.ts │ │ │ ├── IInputController.ts │ │ │ ├── InputClassesFactory.ts │ │ │ ├── KeyCodes.ts │ │ │ ├── KeyboardController.ts │ │ │ ├── MouseButtons.ts │ │ │ ├── MouseController.ts │ │ │ ├── MouseControllerHovering.ts │ │ │ ├── MouseControllerLocked.ts │ │ │ ├── SpecialKeyCodes.ts │ │ │ ├── TouchController.ts │ │ │ ├── TouchControllerFake.ts │ │ │ └── XRGamepadController.ts │ │ ├── PeerConnectionController │ │ │ ├── AggregatedStats.ts │ │ │ ├── CandidatePairStats.ts │ │ │ ├── CandidateStat.ts │ │ │ ├── CodecStats.ts │ │ │ ├── DataChannelStats.ts │ │ │ ├── InboundRTPStats.ts │ │ │ ├── InboundTrackStats.ts │ │ │ ├── LatencyCalculator.ts │ │ │ ├── OutBoundRTPStats.ts │ │ │ ├── PeerConnectionController.ts │ │ │ ├── SessionStats.ts │ │ │ └── StreamStats.ts │ │ ├── PixelStreaming │ │ │ ├── PixelStreaming.test.ts │ │ │ └── PixelStreaming.ts │ │ ├── UeInstanceMessage │ │ │ ├── ResponseController.ts │ │ │ ├── SendMessageController.ts │ │ │ ├── StreamMessageController.ts │ │ │ └── ToStreamerMessagesController.ts │ │ ├── Util │ │ │ ├── BrowserUtils.ts │ │ │ ├── EventEmitter.ts │ │ │ ├── FileUtil.ts │ │ │ ├── IURLSearchParams.ts │ │ │ ├── InputCoordTranslator.ts │ │ │ └── RTCUtils.ts │ │ ├── VideoPlayer │ │ │ ├── StreamController.ts │ │ │ └── VideoPlayer.ts │ │ ├── WebRtcPlayer │ │ │ └── WebRtcPlayerController.ts │ │ ├── WebXR │ │ │ └── WebXRController.ts │ │ ├── __test__ │ │ │ ├── mockMediaStream.ts │ │ │ ├── mockRTCPeerConnection.ts │ │ │ ├── mockRTCRtpReceiver.ts │ │ │ └── mockWebSocket.ts │ │ └── pixelstreamingfrontend.ts │ ├── tsconfig.cjs.json │ ├── tsconfig.esm.json │ ├── tsconfig.jest.json │ └── tsconfig.json └── ui-library │ ├── .cspell.json │ ├── .lintstagedrc.mjs │ ├── .npmignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── README.md │ ├── eslint.config.mjs │ ├── package.json │ ├── src │ ├── Application │ │ └── Application.ts │ ├── Config │ │ ├── ConfigUI.ts │ │ ├── SettingUIBase.ts │ │ ├── SettingUIFlag.ts │ │ ├── SettingUINumber.ts │ │ ├── SettingUIOption.ts │ │ └── SettingUIText.ts │ ├── Overlay │ │ ├── AFKOverlay.ts │ │ ├── ActionOverlay.ts │ │ ├── BaseOverlay.ts │ │ ├── ConnectOverlay.ts │ │ ├── DisconnectOverlay.ts │ │ ├── ErrorOverlay.ts │ │ ├── InfoOverlay.ts │ │ ├── PlayOverlay.ts │ │ └── TextOverlay.ts │ ├── Styles │ │ └── PixelStreamingApplicationStyles.ts │ ├── UI │ │ ├── Controls.ts │ │ ├── DataChannelLatencyTest.ts │ │ ├── EditTextModal.ts │ │ ├── FullscreenIcon.ts │ │ ├── LabelledButton.ts │ │ ├── LatencyTest.ts │ │ ├── SessionTest.ts │ │ ├── SettingsIcon.ts │ │ ├── SettingsPanel.ts │ │ ├── StatsIcon.ts │ │ ├── StatsPanel.ts │ │ ├── UIConfigurationTypes.ts │ │ ├── VideoQpIndicator.ts │ │ └── XRIcon.ts │ ├── Util │ │ └── MathUtils.ts │ └── pixelstreamingfrontend-ui.ts │ ├── tsconfig.cjs.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── LICENSE.md ├── Matchmaker ├── .gitignore └── README.md ├── NODE_VERSION ├── README.md ├── RELEASE_BRANCHING.md ├── RELEASE_VERSION ├── RELEASING.md ├── SECURITY.md ├── SFU ├── .dockerignore ├── CHANGELOG.md ├── Dockerfile ├── Docs │ ├── What is the SFU.md │ └── images │ │ ├── Layer1.PNG │ │ ├── Layer2.PNG │ │ ├── Layer3.PNG │ │ ├── SFUDiagram.PNG │ │ └── SFULayerBP.PNG ├── README.md ├── config.js ├── package.json ├── platform_scripts │ ├── bash │ │ ├── Dockerfile │ │ ├── common_utils.sh │ │ ├── docker-build.sh │ │ ├── docker-start.sh │ │ ├── docker-stop.sh │ │ ├── run_cloud.sh │ │ ├── run_local.sh │ │ └── setup.sh │ └── cmd │ │ ├── run_cloud.bat │ │ ├── run_local.bat │ │ ├── setup.bat │ │ └── setup_node.bat └── sfu_server.js ├── Signalling ├── .gitignore ├── .lintstagedrc.mjs ├── .npmignore ├── .prettierignore ├── CHANGELOG.md ├── README.md ├── docs │ ├── Logger │ │ ├── README.md │ │ ├── functions │ │ │ └── InitLogging.md │ │ ├── interfaces │ │ │ └── IConfig.md │ │ └── variables │ │ │ └── Logger.md │ ├── LoggingUtils │ │ ├── README.md │ │ ├── functions │ │ │ ├── createHandlerListener.md │ │ │ ├── logForward.md │ │ │ ├── logIncoming.md │ │ │ └── logOutgoing.md │ │ └── interfaces │ │ │ ├── IMessageLogger.md │ │ │ └── IProtoLogObj.md │ ├── PlayerConnection │ │ ├── README.md │ │ └── classes │ │ │ └── PlayerConnection.md │ ├── PlayerRegistry │ │ ├── README.md │ │ ├── classes │ │ │ └── PlayerRegistry.md │ │ └── interfaces │ │ │ ├── IPlayer.md │ │ │ └── IPlayerInfo.md │ ├── README.md │ ├── SFUConnection │ │ ├── README.md │ │ └── classes │ │ │ └── SFUConnection.md │ ├── SignallingServer │ │ ├── README.md │ │ ├── classes │ │ │ └── SignallingServer.md │ │ ├── interfaces │ │ │ └── IServerConfig.md │ │ └── type-aliases │ │ │ └── ProtocolConfig.md │ ├── StreamerConnection │ │ ├── README.md │ │ └── classes │ │ │ └── StreamerConnection.md │ ├── StreamerRegistry │ │ ├── README.md │ │ ├── classes │ │ │ └── StreamerRegistry.md │ │ └── interfaces │ │ │ ├── IStreamer.md │ │ │ └── IStreamerInfo.md │ ├── Utils │ │ ├── README.md │ │ └── functions │ │ │ ├── beautify.md │ │ │ └── stringify.md │ ├── WebServer │ │ ├── README.md │ │ ├── classes │ │ │ └── WebServer.md │ │ └── interfaces │ │ │ └── IWebServerConfig.md │ └── pixelstreamingsignalling │ │ └── README.md ├── eslint.config.mjs ├── package.json ├── src │ ├── Logger.ts │ ├── LoggingUtils.ts │ ├── PlayerConnection.ts │ ├── PlayerRegistry.ts │ ├── SFUConnection.ts │ ├── SignallingServer.ts │ ├── StreamerConnection.ts │ ├── StreamerRegistry.ts │ ├── Utils.ts │ ├── WebServer.ts │ └── pixelstreamingsignalling.ts ├── tsconfig.cjs.json ├── tsconfig.esm.json └── tsconfig.json ├── SignallingWebServer ├── .gitignore ├── .lintstagedrc.mjs ├── .prettierignore ├── CHANGELOG.md ├── Dockerfile ├── README.md ├── apidoc │ └── api-definition-base.yml ├── config.json ├── eslint.config.mjs ├── from_cirrus.md ├── package.json ├── platform_scripts │ ├── bash │ │ ├── README.txt │ │ ├── common.sh │ │ ├── docker-build-wilbur.sh │ │ ├── docker-start-turn.sh │ │ ├── docker-start-wilbur-local.sh │ │ ├── docker-start-wilbur-with-turn.sh │ │ ├── docker-start-wilbur.sh │ │ ├── docker-stop-all.sh │ │ ├── docker-stop-turn.sh │ │ ├── docker-stop-wilbur.sh │ │ ├── setup.sh │ │ ├── start.sh │ │ ├── start_turn.sh │ │ ├── start_with_stun.sh │ │ └── start_with_turn.sh │ └── cmd │ │ ├── README.txt │ │ ├── common.bat │ │ ├── setup.bat │ │ ├── start.bat │ │ ├── start_turn.bat │ │ ├── start_with_stun.bat │ │ └── start_with_turn.bat ├── src │ ├── InputHandler.ts │ ├── Utils.ts │ ├── index.ts │ └── paths │ │ ├── config.ts │ │ ├── players.ts │ │ ├── players │ │ └── {playerId}.ts │ │ ├── status.ts │ │ ├── streamers.ts │ │ └── streamers │ │ └── {streamerId}.ts └── tsconfig.json ├── eslint.config.mjs ├── package-lock.json └── package.json /.backportrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "repoOwner": "EpicGamesExt", 3 | "repoName": "PixelStreamingInfrastructure", 4 | "targetBranchChoices": ["master", "UE5.2", "UE5.3", "UE5.4", "UE5.5", "UE5.6"], 5 | "autoMerge": true, 6 | "autoMergeMethod": "squash" 7 | } 8 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /.changeset/red-turtles-cross.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@epicgames-ps/wilbur': minor 3 | --- 4 | 5 | Adds command line options to wilbur to allow for configuring the reverse proxy: 6 | 7 | --reverse-proxy Enables reverse proxy mode. This will 8 | trust the X-Forwarded-For header. 9 | (default: false) 10 | --reverse-proxy-num-proxies Sets the number of proxies to trust. 11 | This is used to calculate the real 12 | client IP address. (default: 1) 13 | -------------------------------------------------------------------------------- /.changeset/sweet-foxes-remain.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@epicgames-ps/wilbur': minor 3 | --- 4 | 5 | Updates to platform_scripts to fix argument passing to Wilbur. 6 | 7 | - Added separator between script parameters and signalling server parameters when using platform scripts 8 | - From now on, anything after the `--` marker on the command line is passed directly to Wilbur. 9 | - Parameters before this marker are intended for the scripts. These parameters are validated and unknown parameters will cause an error. 10 | - Added the new `--peer_options_file` parameter to the signalling server. 11 | - JSON data is problematic to pass on the command line. 12 | - This new parameter allows you to use a JSON file as your peer options for the server. 13 | - Using `--peer_options` is now discouraged. 14 | - Fixed issue with passing peer_options while using platform scripts. 15 | 16 | -------------------------------------------------------------------------------- /.changeset/weak-files-wait.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.6': minor 3 | '@epicgames-ps/lib-pixelstreamingfrontend-ue5.6': minor 4 | --- 5 | 6 | Changes for regression/latency testing. 7 | 8 | ## Latency Session Test and dump to csv 9 | 10 | Added a new feature to run a variable length latency test session (e.g. a 60s window) 11 | and dump that stats from the session to two .csv files: 12 | 13 | 1. latency.csv - Which contains the video timing stats 14 | 2. stats.csv - Which contains all WebRTC stats the library currently tracks 15 | 16 | To enable the latency session test use the flag/url parameter ?LatencyCSV 17 | to enable this feature (by default it is disabled and not UI-configurable). 18 | 19 | To use this latency session test feature: 20 | 21 | 1. Navigate to http://localhost/?LatencyCSV 22 | 2. Open the stats panel and click the "Run Test" button under the "Session Test" heading. 23 | 24 | ## 4.27 support restored 25 | 26 | Re-shipped UE 4.27 support by restoring the ?BrowserSendOffer flag. 27 | It was found useful to support running this latency session test against UE 4.27 28 | for internal historical testing so support for connecting to this version has been restored. 29 | 30 | To connect to a 4.27 project: 31 | 32 | 1. Navigate to http://localhost/?BrowserSendOffer 33 | 2. Connect (warning: this option is not compatible with all newer UE versions) 34 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | **/build/ 3 | **/dist/ 4 | **/node_modules/ 5 | SignallingWebServer/platform_scripts/cmd/coturn/ 6 | SignallingWebServer/platform_scripts/cmd/node/ 7 | SignallingWebServer/platform_scripts/bash/node/ 8 | SignallingWebServer/logs/ 9 | SignallingWebServer/www/ 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] - Complete your bug title here" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **UE Version:** 11 | E.g. UE 5.1.1 12 | 13 | **Frontend Version:** 14 | E.g. UE5.3-0.3.0 15 | 16 | **Problem component** 17 | E.g. Signalling Server, Frontend, Pixel Streaming C++ plugin 18 | 19 | **Description** 20 | A clear and concise description of what the bug is. 21 | 22 | **Steps to Reproduce:** 23 | 1. Go to '...' 24 | 2. Click on '....' 25 | 3. Scroll down to '....' 26 | 4. See error 27 | 28 | **Expected behavior** 29 | 1. A clear and concise description of what you expected to happen. 30 | 2. Ideally laid out in steps. 31 | 32 | **Screenshots** 33 | If applicable, add screenshots to help explain your problem. 34 | 35 | **Platform (please complete the following information):** 36 | - OS: [e.g. Windows 10 Pro] 37 | - Browser + version [e.g. chrome 100] 38 | - Version [e.g. 22] 39 | 40 | **Additional context** 41 | Add any other context about the problem here. 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature 3 | about: Suggest a feature for the Pixel Streaming Infrastructure repo 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Component your feature request relates to** 11 | - [ ] Signalling server 12 | - [ ] Frontend library 13 | - [ ] Frontend UI library 14 | - [ ] Matchmaker 15 | - [ ] SFU 16 | - [ ] This repo 17 | 18 | **Problem your feature solves? Please describe.** 19 | A clear and concise description of what the problem is. 20 | 21 | **Describe the solution you'd like** 22 | A clear and concise description of what you want to happen. 23 | 24 | **Additional context** 25 | Add any other context or screenshots about the feature request here. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question about the PSInfra, we encourage discussions in public so all can benefit from the answers. 4 | title: '' 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Component your question relates to 11 | - [ ] Signalling server 12 | - [ ] Frontend library 13 | - [ ] Frontend UI library 14 | - [ ] Matchmaker 15 | - [ ] SFU 16 | - [ ] This repo 17 | - [ ] Other 18 | 19 | ## Background 20 | A clear and concise description of the background of your question, if relevant (if not relevant, delete this section). 21 | 22 | ## Question 23 | A clear and concise question you would like to ask. If there are multiple please list them like so: 24 | 1. My first question? 25 | 2. My second question? 26 | 27 | ## Additional context 28 | Add any other context or screenshots that are relevant for your question. 29 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Relevant components: 2 | - [ ] Signalling server 3 | - [ ] Common library 4 | - [ ] Frontend library 5 | - [ ] Frontend UI library 6 | - [ ] Matchmaker 7 | - [ ] Platform scripts 8 | - [ ] SFU 9 | 10 | ## Problem statement: 11 | What problem does this PR address? 12 | 13 | ## Solution 14 | How does this PR solve the problem? 15 | 16 | ## Documentation 17 | If you added a new feature or changed an existing feature please add some documentation here. 18 | 19 | Or better yet, link to the relevant `/Docs` update in your PR. 20 | 21 | ## Test Plan and Compatibility 22 | What steps have you taken to ensure this PR maintains compataibility with the existing functionality? 23 | 24 | Or better yet, link to the unit tests that accompany this PR. 25 | -------------------------------------------------------------------------------- /.github/workflows/backport.yml: -------------------------------------------------------------------------------- 1 | name: Backport 2 | 3 | on: 4 | pull_request_target: 5 | types: ["labeled", "closed"] 6 | 7 | permissions: 8 | contents: write 9 | pull-requests: write 10 | 11 | jobs: 12 | backport: 13 | name: Backport PR 14 | runs-on: ubuntu-latest 15 | if: | 16 | github.event.pull_request.merged == true 17 | && contains(github.event.pull_request.labels.*.name, 'auto-backport') 18 | && ( 19 | (github.event.action == 'labeled' && github.event.label.name == 'auto-backport') 20 | || (github.event.action == 'closed') 21 | ) 22 | steps: 23 | - name: Backport Action 24 | uses: sqren/backport-github-action@v8.9.3 25 | with: 26 | github_token: ${{ secrets.GITHUB_TOKEN }} 27 | auto_backport_label_prefix: auto-backport-to- 28 | add_original_reviewers: true 29 | 30 | - name: Info log 31 | if: ${{ success() }} 32 | run: cat ~/.backport/backport.info.log 33 | 34 | - name: Debug log 35 | if: ${{ failure() }} 36 | run: cat ~/.backport/backport.debug.log 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/changesets-update-changelogs.yml: -------------------------------------------------------------------------------- 1 | name: Update Changelogs 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - 'UE*' 8 | 9 | concurrency: ${{ github.workflow }}-${{ github.ref }} 10 | 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | 15 | jobs: 16 | release: 17 | name: Release 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout Repo 21 | uses: actions/checkout@v3 22 | 23 | - name: Setup Node.js 20.x 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: 20.x 27 | 28 | - name: Install Dependencies 29 | run: npm install 30 | 31 | - name: Create Release Pull Request 32 | uses: changesets/action@v1.4.10 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | with: 36 | title: '[Bot] NPM Packages Release ${{ github.ref_name }}' 37 | commit: 'Updated NPM changelogs' 38 | 39 | -------------------------------------------------------------------------------- /.github/workflows/healthcheck-image-sfu.yml: -------------------------------------------------------------------------------- 1 | name: Check health of SFU docker image 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | paths: 7 | - ".github/workflow/healthcheck-image-sfu.yml" 8 | - "SFU/**" 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | build-docker-image: 15 | if: github.repository == 'EpicGamesExt/PixelStreamingInfrastructure' 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v3 20 | 21 | - name: Build the SFU container image 22 | uses: docker/build-push-action@v3 23 | with: 24 | context: . 25 | push: false 26 | file: SFU/Dockerfile 27 | 28 | 29 | -------------------------------------------------------------------------------- /.github/workflows/healthcheck-image-wilbur.yml: -------------------------------------------------------------------------------- 1 | name: Check health of wilbur docker image 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | paths: 7 | - ".github/workflows/healthcheck-image-wilbur.yml" 8 | - "SignallingWebServer/**" 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | build-docker-image: 15 | if: github.repository == 'EpicGamesExt/PixelStreamingInfrastructure' 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v3 20 | 21 | - name: Build the wilbur container image 22 | uses: docker/build-push-action@v3 23 | with: 24 | context: . 25 | push: false 26 | file: SignallingWebServer/Dockerfile 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/healthcheck-libs-with-public-deps.yml: -------------------------------------------------------------------------------- 1 | name: Check health of libraries (public deps) 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | commitsha: 7 | description: "Commit SHA for the release (if blank use latest on this branch)" 8 | 9 | permissions: 10 | contents: read 11 | 12 | env: 13 | commitsha: "${{ github.event.inputs.commitsha || github.sha }}" 14 | 15 | jobs: 16 | build-using-public-deps: 17 | runs-on: ubuntu-latest 18 | strategy: 19 | matrix: 20 | package: 21 | - Common 22 | - Signalling 23 | - Frontend/library 24 | - Frontend/ui-library 25 | - Frontend/implementations/typescript 26 | 27 | steps: 28 | - name: Checkout source code 29 | uses: actions/checkout@v3 30 | with: 31 | ref: "${{ env.commitsha }}" 32 | 33 | - name: Get node version 34 | id: get_node_version 35 | run: echo "node_version=$(cat NODE_VERSION)" >> $GITHUB_OUTPUT 36 | 37 | - uses: actions/setup-node@v4 38 | with: 39 | node-version: "${{ steps.get_node_version.outputs.node_version }}" 40 | registry-url: 'https://registry.npmjs.org' 41 | 42 | - name: Remove NPM workspaces 43 | run: rm package.json 44 | 45 | # Not linting or testing because some of those tools require the 46 | # workspace dependencies. eg. eslint and its plugins. 47 | 48 | - name: Build ${{ matrix.package }} 49 | working-directory: ${{ matrix.package }} 50 | run: | 51 | npm install 52 | npm run build 53 | -------------------------------------------------------------------------------- /.github/workflows/healthcheck-markdown-links.yml: -------------------------------------------------------------------------------- 1 | name: Check health of document links 2 | 3 | on: 4 | workflow_dispatch: 5 | # schedule: 6 | # - cron: '0 0 * * *' 7 | 8 | permissions: 9 | contents: read 10 | issues: write 11 | 12 | jobs: 13 | linkChecker: 14 | if: github.repository == 'EpicGamesExt/PixelStreamingInfrastructure' 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Link Checker 20 | id: lychee 21 | uses: lycheeverse/lychee-action@v1.9.0 22 | with: 23 | args: --github-token ${{ secrets.WORKFLOW_TOKEN }} --exclude 'localhost' --exclude 'github.com/EpicGames/UnrealEngine' --exclude '.png' --exclude '.jpg' --exclude-path 'SFU/mediasoup-sdp-bridge/README.md' './**/*.md' 24 | 25 | - name: Create Issue From File 26 | if: env.lychee_exit_code != 0 27 | uses: peter-evans/create-issue-from-file@v4 28 | with: 29 | title: Link Checker Report 30 | content-filepath: ./lychee/out.md 31 | labels: report, automated issue 32 | -------------------------------------------------------------------------------- /.github/workflows/healthcheck-signalling-protocol.yml: -------------------------------------------------------------------------------- 1 | name: Check health of signalling protocol 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | paths: 7 | - ".github/workflows/healthcheck-signalling-protocol.yml" 8 | - "Common/**" 9 | - "Signalling/**" 10 | - "SignallingWebServer/**" 11 | - "Extras/SS_Test/**" 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | signalling-protocol-test: 18 | if: github.repository == 'EpicGamesExt/PixelStreamingInfrastructure' 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout source code 22 | uses: actions/checkout@v3 23 | 24 | - name: Launch signalling tests in docker containers 25 | uses: isbang/compose-action@v1.5.1 26 | with: 27 | compose-file: "Extras/SS_Test/docker-compose.yml" 28 | up-flags: "--build --abort-on-container-exit --exit-code-from tester" 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark and close stale issues and pull requests 2 | 3 | on: 4 | 5 | workflow_dispatch: 6 | schedule: 7 | - cron: "0 0 * * *" 8 | 9 | permissions: 10 | contents: read 11 | issues: write 12 | pull-requests: write 13 | 14 | jobs: 15 | stale: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/stale@v8 19 | with: 20 | repo-token: ${{ secrets.GITHUB_TOKEN }} 21 | stale-issue-message: 'Issues go stale after 30 days of inactivity. Please comment or re-open the issue if you are still interested in getting this issue fixed.' 22 | stale-issue-label: 'stale' 23 | exempt-issue-labels: 'enhancement,never-stale' 24 | 25 | stale-pr-message: 'PRs go stale after 30 days of inactivity. Please comment or re-open the PR if you are still working on this PR.' 26 | stale-pr-label: 'stale' 27 | exempt-pr-labels: 'awaiting-approval,never-stale' 28 | 29 | days-before-stale: 30 30 | days-before-close: 0 31 | 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | node_modules/ 3 | **/platform_scripts/cmd/*/ 4 | !**/platform_scripts/cmd/setenv/ 5 | **/platform_scripts/bash/*/ 6 | node.zip 7 | SignallingWebServer/Public/ 8 | SignallingWebServer/certificates 9 | .vscode 10 | coverage/ 11 | common/types/* 12 | .nx/cache 13 | .nx/workspace-data 14 | -------------------------------------------------------------------------------- /.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | "*.json": "prettier --write" 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 110, 3 | "trailingComma": "none", 4 | "tabWidth": 4, 5 | "semi": true, 6 | "singleQuote": true 7 | } 8 | -------------------------------------------------------------------------------- /Common/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | node_modules/ 4 | types/ 5 | .vscode 6 | -------------------------------------------------------------------------------- /Common/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '../.lintstagedrc.mjs' 2 | 3 | export default { 4 | ...baseConfig, 5 | '*.ts': 'eslint --fix', 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Common/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Common/.npmignore -------------------------------------------------------------------------------- /Common/.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Common/.prettierignore -------------------------------------------------------------------------------- /Common/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/lib-pixelstreamingcommon-ue5.6 2 | 3 | -------------------------------------------------------------------------------- /Common/README.md: -------------------------------------------------------------------------------- 1 | # lib-pixelstreamingcommon 2 | 3 | The common library for the browser/client side of Pixel Streaming experiences. This library exposes common functionality for frontend applications of the pixel streaming ecosystem. 4 | 5 | For examples of how to implement this library. 6 | - See [lib-pixelstreamingfrontend](/Frontend/library) 7 | - See [lib-pixelstreamingsignalling](/Signalling) 8 | - Also see [Wilbur](/SignallingWebServer) which uses the signalling library to implement a full signalling server. 9 | 10 | ### Adding it to your project 11 | `npm i @epicgames-ps/lib-pixelstreamingcommon-ue5.6` 12 | 13 | ## Documentation 14 | The API is documented [here](docs). 15 | 16 | ### How this library is built 17 | The NPM packages supports: 18 | - ES6 module usage 19 | - CommonJS usage 20 | - Type definitions 21 | - Source maps 22 | -------------------------------------------------------------------------------- /Common/docs/Event/EventEmitter/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Event/EventEmitter 6 | 7 | # Event/EventEmitter 8 | 9 | ## Classes 10 | 11 | - [EventEmitter](classes/EventEmitter.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Logger/Logger/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Logger/Logger 6 | 7 | # Logger/Logger 8 | 9 | ## Enumerations 10 | 11 | - [LogLevel](enumerations/LogLevel.md) 12 | 13 | ## Classes 14 | 15 | - [LoggerContext](classes/LoggerContext.md) 16 | - [LoggerType](classes/LoggerType.md) 17 | 18 | ## Interfaces 19 | 20 | - [ILogger](interfaces/ILogger.md) 21 | 22 | ## Variables 23 | 24 | - [Logger](variables/Logger.md) 25 | 26 | ## Functions 27 | 28 | - [overrideLogger](functions/overrideLogger.md) 29 | -------------------------------------------------------------------------------- /Common/docs/Logger/Logger/classes/LoggerContext.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Logger/Logger](../README.md) / LoggerContext 6 | 7 | # Class: LoggerContext 8 | 9 | Defined in: [Logger/Logger.ts:23](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L23) 10 | 11 | The global context for the logger configuration. 12 | This cannot be stored statically in the Logger class because we sometimes have multiple execution 13 | contexts, such as stats reporting. Instead we store the logger config context on the window object 14 | to be shared with any Logger instances. 15 | 16 | ## Constructors 17 | 18 | ### new LoggerContext() 19 | 20 | > **new LoggerContext**(): [`LoggerContext`](LoggerContext.md) 21 | 22 | #### Returns 23 | 24 | [`LoggerContext`](LoggerContext.md) 25 | 26 | ## Properties 27 | 28 | ### includeStack 29 | 30 | > **includeStack**: `boolean` = `true` 31 | 32 | Defined in: [Logger/Logger.ts:25](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L25) 33 | 34 | *** 35 | 36 | ### logLevel 37 | 38 | > **logLevel**: [`LogLevel`](../enumerations/LogLevel.md) = `LogLevel.Debug` 39 | 40 | Defined in: [Logger/Logger.ts:24](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L24) 41 | -------------------------------------------------------------------------------- /Common/docs/Logger/Logger/enumerations/LogLevel.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Logger/Logger](../README.md) / LogLevel 6 | 7 | # Enumeration: LogLevel 8 | 9 | Defined in: [Logger/Logger.ts:9](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L9) 10 | 11 | ## Enumeration Members 12 | 13 | ### Debug 14 | 15 | > **Debug**: `4` 16 | 17 | Defined in: [Logger/Logger.ts:14](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L14) 18 | 19 | *** 20 | 21 | ### Disabled 22 | 23 | > **Disabled**: `0` 24 | 25 | Defined in: [Logger/Logger.ts:10](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L10) 26 | 27 | *** 28 | 29 | ### Error 30 | 31 | > **Error**: `1` 32 | 33 | Defined in: [Logger/Logger.ts:11](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L11) 34 | 35 | *** 36 | 37 | ### Info 38 | 39 | > **Info**: `3` 40 | 41 | Defined in: [Logger/Logger.ts:13](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L13) 42 | 43 | *** 44 | 45 | ### Warning 46 | 47 | > **Warning**: `2` 48 | 49 | Defined in: [Logger/Logger.ts:12](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L12) 50 | -------------------------------------------------------------------------------- /Common/docs/Logger/Logger/functions/overrideLogger.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Logger/Logger](../README.md) / overrideLogger 6 | 7 | # Function: overrideLogger() 8 | 9 | > **overrideLogger**(`logger`): `void` 10 | 11 | Defined in: [Logger/Logger.ts:36](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L36) 12 | 13 | ## Parameters 14 | 15 | ### logger 16 | 17 | [`ILogger`](../interfaces/ILogger.md) 18 | 19 | ## Returns 20 | 21 | `void` 22 | -------------------------------------------------------------------------------- /Common/docs/Logger/Logger/variables/Logger.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Logger/Logger](../README.md) / Logger 6 | 7 | # Variable: Logger 8 | 9 | > **Logger**: [`ILogger`](../interfaces/ILogger.md) 10 | 11 | Defined in: [Logger/Logger.ts:156](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Logger/Logger.ts#L156) 12 | -------------------------------------------------------------------------------- /Common/docs/Messages/base_message/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Messages/base\_message 6 | 7 | # Messages/base\_message 8 | 9 | ## Interfaces 10 | 11 | - [BaseMessage](interfaces/BaseMessage.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Messages/base_message/interfaces/BaseMessage.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Messages/base\_message](../README.md) / BaseMessage 6 | 7 | # Interface: BaseMessage 8 | 9 | Defined in: [Messages/base\_message.ts:4](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Messages/base_message.ts#L4) 10 | 11 | All Pixel Streaming messages should adhere to this interface. 12 | 13 | ## Properties 14 | 15 | ### playerId? 16 | 17 | > `optional` **playerId**: `string` 18 | 19 | Defined in: [Messages/base\_message.ts:8](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Messages/base_message.ts#L8) 20 | 21 | *** 22 | 23 | ### type 24 | 25 | > **type**: `string` 26 | 27 | Defined in: [Messages/base\_message.ts:6](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Messages/base_message.ts#L6) 28 | -------------------------------------------------------------------------------- /Common/docs/Messages/message_helpers/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Messages/message\_helpers 6 | 7 | # Messages/message\_helpers 8 | 9 | ## Functions 10 | 11 | - [createMessage](functions/createMessage.md) 12 | - [validateMessage](functions/validateMessage.md) 13 | -------------------------------------------------------------------------------- /Common/docs/Messages/message_helpers/functions/createMessage.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Messages/message\_helpers](../README.md) / createMessage 6 | 7 | # Function: createMessage() 8 | 9 | > **createMessage**(`messageType`, `params`?): [`BaseMessage`](../../base_message/interfaces/BaseMessage.md) 10 | 11 | Defined in: [Messages/message\_helpers.ts:14](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Messages/message_helpers.ts#L14) 12 | 13 | A helper for creating signalling messages. Takes in optional given parameters and 14 | includes them in a message object with the 'type' field set properly for the message 15 | type supplied. 16 | 17 | ## Parameters 18 | 19 | ### messageType 20 | 21 | `IMessageType`\<[`BaseMessage`](../../base_message/interfaces/BaseMessage.md)\> 22 | 23 | A message type from MessageRegistry that indicates the type of message to create. 24 | 25 | ### params? 26 | 27 | `object` 28 | 29 | An optional object whose fields are added to the newly created message. 30 | 31 | ## Returns 32 | 33 | [`BaseMessage`](../../base_message/interfaces/BaseMessage.md) 34 | 35 | The resulting message object. 36 | -------------------------------------------------------------------------------- /Common/docs/Messages/message_helpers/functions/validateMessage.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Messages/message\_helpers](../README.md) / validateMessage 6 | 7 | # Function: validateMessage() 8 | 9 | > **validateMessage**(`msg`): `null` \| `IMessageType`\<[`BaseMessage`](../../base_message/interfaces/BaseMessage.md)\> 10 | 11 | Defined in: [Messages/message\_helpers.ts:29](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Messages/message_helpers.ts#L29) 12 | 13 | Tests that the supplied message is valid. That is contains all expected fields and 14 | doesn't contain any unknown fields. 15 | 16 | ## Parameters 17 | 18 | ### msg 19 | 20 | [`BaseMessage`](../../base_message/interfaces/BaseMessage.md) 21 | 22 | The message object to test. 23 | 24 | ## Returns 25 | 26 | `null` \| `IMessageType`\<[`BaseMessage`](../../base_message/interfaces/BaseMessage.md)\> 27 | 28 | The message type from MessageRegistry of the supplied message object if it's valid, or null if invalid. 29 | -------------------------------------------------------------------------------- /Common/docs/Messages/message_registry/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Messages/message\_registry 6 | 7 | # Messages/message\_registry 8 | 9 | ## Variables 10 | 11 | - [MessageRegistry](variables/MessageRegistry.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Messages/message_registry/variables/MessageRegistry.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Messages/message\_registry](../README.md) / MessageRegistry 6 | 7 | # Variable: MessageRegistry 8 | 9 | > `const` **MessageRegistry**: `Record`\<`string`, `IMessageType`\<[`BaseMessage`](../../base_message/interfaces/BaseMessage.md)\>\> 10 | 11 | Defined in: [Messages/message\_registry.ts:10](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Messages/message_registry.ts#L10) 12 | 13 | A map of all the supported signalling messages in the Pixel Streaming 14 | signalling protocol. This allows mapping of signalling message names 15 | to actual message types. 16 | -------------------------------------------------------------------------------- /Common/docs/Protocol/KeepaliveMonitor/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Protocol/KeepaliveMonitor 6 | 7 | # Protocol/KeepaliveMonitor 8 | 9 | ## Classes 10 | 11 | - [KeepaliveMonitor](classes/KeepaliveMonitor.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Protocol/SignallingProtocol/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Protocol/SignallingProtocol 6 | 7 | # Protocol/SignallingProtocol 8 | 9 | ## Classes 10 | 11 | - [SignallingProtocol](classes/SignallingProtocol.md) 12 | -------------------------------------------------------------------------------- /Common/docs/README.md: -------------------------------------------------------------------------------- 1 | **@epicgames-ps/lib-pixelstreamingcommon-ue5.5** 2 | 3 | *** 4 | 5 | # @epicgames-ps/lib-pixelstreamingcommon-ue5.5 6 | 7 | ## Modules 8 | 9 | - [Event/EventEmitter](Event/EventEmitter/README.md) 10 | - [Logger/Logger](Logger/Logger/README.md) 11 | - [Messages/base\_message](Messages/base_message/README.md) 12 | - [Messages/message\_helpers](Messages/message_helpers/README.md) 13 | - [Messages/message\_registry](Messages/message_registry/README.md) 14 | - [pixelstreamingcommon](pixelstreamingcommon/README.md) 15 | - [Protocol/KeepaliveMonitor](Protocol/KeepaliveMonitor/README.md) 16 | - [Protocol/SignallingProtocol](Protocol/SignallingProtocol/README.md) 17 | - [Transport/ITransport](Transport/ITransport/README.md) 18 | - [Transport/WebSocketTransport](Transport/WebSocketTransport/README.md) 19 | - [Transport/WebSocketTransportNJS](Transport/WebSocketTransportNJS/README.md) 20 | - [Util/SdpUtils](Util/SdpUtils/README.md) 21 | -------------------------------------------------------------------------------- /Common/docs/Transport/ITransport/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Transport/ITransport 6 | 7 | # Transport/ITransport 8 | 9 | ## Interfaces 10 | 11 | - [ITransport](interfaces/ITransport.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Transport/WebSocketTransport/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Transport/WebSocketTransport 6 | 7 | # Transport/WebSocketTransport 8 | 9 | ## Classes 10 | 11 | - [WebSocketTransport](classes/WebSocketTransport.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Transport/WebSocketTransportNJS/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Transport/WebSocketTransportNJS 6 | 7 | # Transport/WebSocketTransportNJS 8 | 9 | ## Classes 10 | 11 | - [WebSocketTransportNJS](classes/WebSocketTransportNJS.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Util/SdpUtils/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../README.md) / Util/SdpUtils 6 | 7 | # Util/SdpUtils 8 | 9 | ## Classes 10 | 11 | - [SDPUtils](classes/SDPUtils.md) 12 | -------------------------------------------------------------------------------- /Common/docs/Util/SdpUtils/classes/SDPUtils.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingcommon-ue5.5**](../../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingcommon-ue5.5](../../../README.md) / [Util/SdpUtils](../README.md) / SDPUtils 6 | 7 | # Class: SDPUtils 8 | 9 | Defined in: [Util/SdpUtils.ts:3](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Util/SdpUtils.ts#L3) 10 | 11 | ## Constructors 12 | 13 | ### new SDPUtils() 14 | 15 | > **new SDPUtils**(): [`SDPUtils`](SDPUtils.md) 16 | 17 | #### Returns 18 | 19 | [`SDPUtils`](SDPUtils.md) 20 | 21 | ## Methods 22 | 23 | ### addVideoHeaderExtensionToSdp() 24 | 25 | > `static` **addVideoHeaderExtensionToSdp**(`sdp`, `uri`): `string` 26 | 27 | Defined in: [Util/SdpUtils.ts:4](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/e5168fb9b95d09ea76d485376bd036403b747ad2/Common/src/Util/SdpUtils.ts#L4) 28 | 29 | #### Parameters 30 | 31 | ##### sdp 32 | 33 | `string` 34 | 35 | ##### uri 36 | 37 | `string` 38 | 39 | #### Returns 40 | 41 | `string` 42 | -------------------------------------------------------------------------------- /Common/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import tseslint from 'typescript-eslint'; 4 | import tsdocPlugin from 'eslint-plugin-tsdoc'; 5 | import baseConfig from '../eslint.config.mjs' 6 | 7 | export default tseslint.config( 8 | baseConfig, 9 | { 10 | ignores: ["src/Messages/signalling_messages.ts"], 11 | }, 12 | { 13 | languageOptions: { 14 | parser: tseslint.parser, 15 | parserOptions: { 16 | project: 'tsconfig.cjs.json', 17 | }, 18 | }, 19 | files: ["src/**/*.ts"], 20 | plugins: { 21 | 'tsdoc': tsdocPlugin 22 | }, 23 | rules: { 24 | "tsdoc/syntax": "warn", 25 | "@typescript-eslint/require-array-sort-compare": "error", 26 | "no-unused-vars": "off", 27 | "@typescript-eslint/no-unused-vars": [ 28 | "error", 29 | { 30 | "argsIgnorePattern": "^_", 31 | "varsIgnorePattern": "^_", 32 | "caughtErrorsIgnorePattern": "^_" 33 | } 34 | ] 35 | } 36 | } 37 | ); 38 | -------------------------------------------------------------------------------- /Common/protobuf/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Pixelstreaming Signalling Protocol Changelog 2 | 3 | # 02-04-2025 4 | - Added the subscribeFailed message 5 | 6 | -------------------------------------------------------------------------------- /Common/src/Messages/base_message.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | /** 3 | * All Pixel Streaming messages should adhere to this interface. 4 | */ 5 | export interface BaseMessage { 6 | // the type of the message 7 | type: string; 8 | // the player id that this message is related to (usually describes the target of the message) 9 | playerId?: string; 10 | } 11 | -------------------------------------------------------------------------------- /Common/src/Transport/ITransport.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { EventEmitter } from '../Event/EventEmitter'; 3 | 4 | /** 5 | * An interface to a transport protocol that is in charge of sending and receiving signalling messages. 6 | * Implement this interface to support your custom transport. You can then supply an instance of your 7 | * transport to the constructor of SignallingProtocol during startup. 8 | */ 9 | export interface ITransport extends EventEmitter { 10 | /** 11 | * Called when the protocol wants to send a message over the transport. 12 | * @param msg - The message to send over the transport. 13 | */ 14 | sendMessage(msg: string): void; 15 | 16 | /** 17 | * Callback filled in by the SignallingProtocol and should be called by the transport when a new message arrives. 18 | */ 19 | onMessage?: (msg: string) => void; 20 | 21 | /** 22 | * Connect to a given URL. 23 | * @param url - The URL for the transport to connect to. 24 | * @returns True if the connection was successful. 25 | */ 26 | connect(url: string): boolean; 27 | 28 | /** 29 | * Disconnect this transport. 30 | * @param code - An optional disconnect code. 31 | * @param reason - A descriptive string for the disconnect reason. 32 | */ 33 | disconnect(code?: number, reason?: string): void; 34 | 35 | /** 36 | * Should return true when the transport is connected and ready to send/receive messages. 37 | * @returns True if the transport is connected. 38 | */ 39 | isConnected(): boolean; 40 | } 41 | -------------------------------------------------------------------------------- /Common/src/Util/SdpUtils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | export class SDPUtils { 4 | static addVideoHeaderExtensionToSdp(sdp: string, uri: string): string { 5 | // Find the highest used header extension id by sorting the extension ids used, 6 | // eliminating duplicates and adding one. 7 | // Todo: Update this when WebRTC in Chrome supports the header extension API. 8 | const usedIds = sdp 9 | .split('\n') 10 | .filter((line) => line.startsWith('a=extmap:')) 11 | .map((line) => parseInt(line.split(' ')[0].substring(9), 10)) 12 | .sort((a, b) => a - b) 13 | .filter((item, index, array) => array.indexOf(item) === index); 14 | const nextId = usedIds[usedIds.length - 1] + 1; 15 | const extmapLine = 'a=extmap:' + nextId + ' ' + uri + '\r\n'; 16 | 17 | const sections = sdp.split('\nm=').map((part, index) => { 18 | return (index > 0 ? 'm=' + part : part).trim() + '\r\n'; 19 | }); 20 | const sessionPart = sections.shift(); 21 | // Only add extension to m=video media section 22 | return ( 23 | sessionPart + 24 | sections 25 | .map((mediaSection) => 26 | mediaSection.startsWith('m=video') ? mediaSection + extmapLine : mediaSection 27 | ) 28 | .join('') 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Common/src/pixelstreamingcommon.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | export { Logger, LogLevel, ILogger, overrideLogger } from './Logger/Logger'; 3 | export { ITransport } from './Transport/ITransport'; 4 | export { WebSocketTransport } from './Transport/WebSocketTransport'; 5 | export { WebSocketTransportNJS } from './Transport/WebSocketTransportNJS'; 6 | export { SignallingProtocol } from './Protocol/SignallingProtocol'; 7 | export { IMessageType } from '@protobuf-ts/runtime'; 8 | export { BaseMessage } from './Messages/base_message'; 9 | export { EventEmitter } from './Event/EventEmitter'; 10 | export { MessageRegistry } from './Messages/message_registry'; 11 | export * as Messages from './Messages/signalling_messages'; 12 | export * as MessageHelpers from './Messages/message_helpers'; 13 | export { KeepaliveMonitor } from './Protocol/KeepaliveMonitor'; 14 | export * from './Util/SdpUtils'; 15 | -------------------------------------------------------------------------------- /Common/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/cjs", 5 | "module": "node16", 6 | "moduleResolution": "node16" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Common/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/esm", 5 | "module": "es6", 6 | "moduleResolution": "bundler" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "esModuleInterop": true, 5 | "target": "ES6", 6 | "sourceMap": true, 7 | "allowJs": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noImplicitOverride": false, // generated code breaks this 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "noPropertyAccessFromIndexSignature": true, 14 | "declaration": true, 15 | "declarationDir": "./dist/types", 16 | "moduleResolution": "bundler" // helps IDEs 17 | }, 18 | "include": ["./src/*.ts"], 19 | "typedocOptions": { 20 | "entryPoints": ["src/**/*.ts"], 21 | "out": "docs", 22 | "exclude": ["src/Messages/signalling_messages.ts"], 23 | "excludeExternals": true, 24 | "excludePrivate": true, 25 | "excludeInternal": true, 26 | "cleanOutputDir": false, 27 | "plugin": "typedoc-plugin-markdown", 28 | "readme": "none" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Docs/README.md: -------------------------------------------------------------------------------- 1 | # General Documentation and Information 2 | Welcome to the general documentation page for Pixel Streaming. This page serves as the central hub for accessing various documentation related to Pixel Streaming. It also functions as a Table of Contents, providing easy navigation to different sections of this repository. 3 | 4 | [Documentation Table of Contents](/README.md#documentation) 5 | ### General Documentation 6 | 7 | * [Security Guidelines](/Docs/Security-Guidelines.md) 8 | 9 | 10 | 11 | ## Legal 12 | © 2004-2025, Epic Games, Inc. Unreal and its logo are Epic’s trademarks or registered trademarks in the US and elsewhere. 13 | -------------------------------------------------------------------------------- /Docs/Resources/Images/pixelstreamingplayerblueprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Docs/Resources/Images/pixelstreamingplayerblueprint.png -------------------------------------------------------------------------------- /Extras/FrontendTests/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | playwright-report/ 3 | results/ 4 | test-results/ 5 | -------------------------------------------------------------------------------- /Extras/FrontendTests/README.md: -------------------------------------------------------------------------------- 1 | # rtcp-playwright-test 2 | 3 | ## Running locally 4 | ### Setup 5 | ``` 6 | npm install 7 | npx playwright install-deps 8 | npx playwright install firefox 9 | npx playwright install chromium 10 | ``` 11 | 12 | ### Prepare 13 | - Run signalling server 14 | - Start streamer pointed at signalling server 15 | - [optional] Create .env file (can use example.env as a reference) and point to signalling server URL if not localhost 16 | 17 | ### Run tests 18 | ``` 19 | npx playwright test 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /Extras/FrontendTests/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3.4" 3 | services: 4 | signalling: 5 | build: 6 | context: ../../ 7 | dockerfile: ./SignallingWebServer/Dockerfile 8 | image: signalling 9 | command: -- --rest_api 10 | networks: 11 | - testing 12 | healthcheck: 13 | test: ["CMD", "curl", "-f", "http://signalling:80"] 14 | interval: 10s 15 | timeout: 5s 16 | retries: 3 17 | start_period: 30s 18 | start_interval: 5s # only supported on docker engine 25+ 19 | 20 | streamer: 21 | build: 22 | context: ../../ 23 | dockerfile: ./Extras/JSStreamer/Dockerfile 24 | image: streamer 25 | networks: 26 | - testing 27 | healthcheck: 28 | test: ["CMD", "curl", "-f", "http://streamer:4000"] 29 | interval: 5s 30 | timeout: 5s 31 | retries: 10 32 | depends_on: 33 | signalling: 34 | condition: service_healthy 35 | 36 | tester: 37 | build: 38 | context: ../../ 39 | dockerfile: ./Extras/FrontendTests/dockerfiles/linux/Dockerfile 40 | image: tester 41 | environment: 42 | - STREAMER_SIGNALLING_URL=ws://signalling:8888 43 | - PIXELSTREAMING_URL=http://signalling 44 | - PIXELSTREAMER_URL=http://streamer:4000 45 | networks: 46 | - testing 47 | volumes: 48 | - ./results:/tester/playwright-report 49 | depends_on: 50 | streamer: 51 | condition: service_healthy 52 | 53 | networks: 54 | testing: 55 | -------------------------------------------------------------------------------- /Extras/FrontendTests/dockerfiles/linux/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-bookworm 2 | 3 | WORKDIR /tester 4 | COPY /Extras/FrontendTests . 5 | 6 | RUN npm install 7 | RUN npx playwright install firefox 8 | RUN npx playwright install chromium 9 | RUN npx playwright install-deps 10 | 11 | VOLUME /tester/playwright-report 12 | 13 | # CMD [ "curl", "-f", "http://streamer:4000" ] 14 | CMD [ "npm", "run", "test" ] 15 | 16 | -------------------------------------------------------------------------------- /Extras/FrontendTests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend-tests", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "private": true, 7 | "scripts": { 8 | "test": "npx playwright test", 9 | "build": "", 10 | "clean": "" 11 | }, 12 | "keywords": [], 13 | "author": "Epic Games", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "@playwright/test": "^1.49.1", 17 | "@types/node": "^20.12.7", 18 | "@types/uuid": "^9.0.8" 19 | }, 20 | "dependencies": { 21 | "@epicgames-ps/js-streamer": "^0.0.4", 22 | "@epicgames-ps/lib-pixelstreamingfrontend-ue5.6": "*", 23 | "dotenv": "^16.4.5", 24 | "node-fetch": "^2.7.0", 25 | "uuid": "^9.0.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Extras/FrontendTests/tests/basic_stream.spec.ts: -------------------------------------------------------------------------------- 1 | import { test } from './fixtures'; 2 | import { expect } from './matchers'; 3 | import * as helpers from './helpers'; 4 | import { StatsReceivedEvent } from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.6'; 5 | 6 | // NOTE: add a new test to check qp values 7 | 8 | // just quickly test that the default stream is working 9 | test('Test default stream.', { 10 | tag: ['@basic'], 11 | }, async ({ page, streamerId }) => { 12 | 13 | await page.goto(`/?StreamerId=${streamerId}`); 14 | 15 | // let the stream run for a short duration 16 | await helpers.startAndWaitForVideo(page); 17 | 18 | let frameCount: number = await page.evaluate(()=> { 19 | return new Promise((resolve) => { 20 | window.pixelStreaming.addEventListener("statsReceived", (e: StatsReceivedEvent) => { 21 | if(e.data.aggregatedStats && e.data.aggregatedStats.inboundVideoStats && e.data.aggregatedStats.inboundVideoStats.framesReceived) { 22 | resolve(e.data.aggregatedStats.inboundVideoStats.framesReceived); 23 | } 24 | }); 25 | }); 26 | }); 27 | 28 | // pass the test if we recorded any frames 29 | expect(frameCount).toBeGreaterThan(0); 30 | }); 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Extras/JSStreamer/.gitignore: -------------------------------------------------------------------------------- 1 | certs/ 2 | dist/ 3 | build/ 4 | 5 | -------------------------------------------------------------------------------- /Extras/JSStreamer/.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Extras/JSStreamer/.prettierignore -------------------------------------------------------------------------------- /Extras/JSStreamer/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 110, 3 | "trailingComma": "none", 4 | "tabWidth": 4, 5 | "semi": true, 6 | "singleQuote": true 7 | } 8 | -------------------------------------------------------------------------------- /Extras/JSStreamer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-bookworm 2 | 3 | ## Note: This dockerfile is expected to be called from the root of this repo 4 | ## Maybe something like: docker build -t epicgames/jsstreamer:latest -f ./Extras/JSStreamer/Dockerfile . 5 | 6 | WORKDIR /streamer 7 | COPY /Common ./Common 8 | COPY /Extras/JSStreamer ./Extras/JSStreamer 9 | COPY ./package.json ./package.json 10 | COPY NODE_VERSION ./NODE_VERSION 11 | 12 | # Initiate NPM workspaces so we can install deps like our common lib using local built packages as opposed to remove published packages 13 | RUN npm install 14 | 15 | # Install and build common 16 | RUN cd ./Common && npm install && npm run build 17 | 18 | # Install and build JSStream using the common lib we just build 19 | RUN cd ./Extras/JSStreamer && npm install && npm run build 20 | 21 | # Run JSStreamer 22 | CMD cd ./Extras/JSStreamer && npm run develop 23 | 24 | -------------------------------------------------------------------------------- /Extras/JSStreamer/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Streamer 2 | 3 | The JavaScript Streamer is a functional drop-in for an instance of a Unreal Engine Pixel Streaming application 4 | except it can run in the browser, requires no GPU, and has zero dependencies on Unreal Engine. 5 | 6 | Its purpose is as follows: 7 | - A mock of Unreal Engine Pixel Streaming for testing the various Pixel Streaming Infrastructure components in CI without requiring UE. 8 | - A reference to demonstrate how to implement your own Pixel Streaming source (yes, you _could_ stream from things other than UE). 9 | 10 | ## Running 11 | - `npm install` 12 | - `npm run build` 13 | - `npm run develop` 14 | - Visit http://localhost:4000 in your browser -------------------------------------------------------------------------------- /Extras/JSStreamer/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import tseslint from 'typescript-eslint'; 4 | import tsdocPlugin from 'eslint-plugin-tsdoc'; 5 | import baseConfig from '../../eslint.config.mjs' 6 | 7 | export default tseslint.config( 8 | baseConfig, 9 | { 10 | ignores: [], 11 | }, 12 | { 13 | languageOptions: { 14 | parser: tseslint.parser, 15 | parserOptions: { 16 | project: 'tsconfig.cjs.json', 17 | }, 18 | }, 19 | files: ["src/**/*.ts"], 20 | plugins: { 21 | 'tsdoc': tsdocPlugin, 22 | }, 23 | rules: { 24 | "tsdoc/syntax": "warn", 25 | "@typescript-eslint/require-array-sort-compare": "error", 26 | "no-unused-vars": "off", 27 | "@typescript-eslint/no-unused-vars": [ 28 | "error", 29 | { 30 | "argsIgnorePattern": "^_", 31 | "varsIgnorePattern": "^_", 32 | "caughtErrorsIgnorePattern": "^_" 33 | } 34 | ] 35 | } 36 | } 37 | ); 38 | -------------------------------------------------------------------------------- /Extras/JSStreamer/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Extras/JSStreamer/src/pixelstreamingjsstreamer.ts: -------------------------------------------------------------------------------- 1 | export { Streamer } from './streamer'; 2 | export { DataProtocol } from './protocol'; 3 | -------------------------------------------------------------------------------- /Extras/JSStreamer/src/video/big-buck-bunny_trailer.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Extras/JSStreamer/src/video/big-buck-bunny_trailer.webm -------------------------------------------------------------------------------- /Extras/JSStreamer/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/cjs", 5 | "module": "commonjs", 6 | "declaration": true, 7 | "declarationDir": "./dist/types" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Extras/JSStreamer/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/esm", 5 | "module": "nodenext", 6 | "moduleResolution": "nodenext" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Extras/JSStreamer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": false, 4 | "esModuleInterop": true, 5 | "target": "ES6", 6 | "sourceMap": true, 7 | "allowJs": true, 8 | "strict": false 9 | }, 10 | "include": ["./src/*.ts"], 11 | "typedocOptions": { 12 | "entryPoints": ["src/**/*.ts"], 13 | "out": "docs", 14 | "excludeExternals": true, 15 | "excludePrivate": true, 16 | "excludeInternal": true, 17 | "cleanOutputDir": false, 18 | "plugin": "typedoc-plugin-markdown", 19 | "readme": "none" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Extras/MinimalStreamTester/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | playwright-report/ 3 | results/ 4 | .env 5 | 6 | -------------------------------------------------------------------------------- /Extras/MinimalStreamTester/README.md: -------------------------------------------------------------------------------- 1 | ## Minimal Stream Tester 2 | Just a small playwright application that attempts to start a stream. Used in testing to make sure streaming continues to work. 3 | -------------------------------------------------------------------------------- /Extras/MinimalStreamTester/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3.4" 3 | services: 4 | signalling: 5 | build: 6 | context: ../../ 7 | dockerfile: ./SignallingWebServer/Dockerfile 8 | image: signalling 9 | command: -- --rest_api 10 | networks: 11 | - testing 12 | healthcheck: 13 | test: ["CMD", "curl", "-f", "http://signalling:80"] 14 | interval: 10s 15 | timeout: 5s 16 | retries: 3 17 | start_period: 30s 18 | start_interval: 5s # only supported on docker engine 25+ 19 | 20 | streamer: 21 | image: pixelstreamingunofficial/ps-minimal-streamer-linux 22 | command: -PixelStreamingURL=ws://signalling:8888 -nothreadtimeout -PixelStreamingEncoderCodec=vp8 -RenderOffScreen -AllowSoftwareRendering 23 | networks: 24 | - testing 25 | healthcheck: 26 | test: ["CMD", "curl", "-f", "http://signalling:80/api/streamers/DefaultStreamer"] 27 | interval: 20s 28 | timeout: 5s 29 | retries: 10 30 | depends_on: 31 | signalling: 32 | condition: service_healthy 33 | 34 | tester: 35 | build: 36 | context: ../../ 37 | dockerfile: ./Extras/MinimalStreamTester/dockerfiles/linux/Dockerfile 38 | image: tester 39 | environment: 40 | - PIXELSTREAMING_URL=http://signalling 41 | networks: 42 | - testing 43 | volumes: 44 | - ./results:/tester/playwright-report 45 | depends_on: 46 | streamer: 47 | condition: service_healthy 48 | 49 | networks: 50 | testing: 51 | -------------------------------------------------------------------------------- /Extras/MinimalStreamTester/dockerfiles/linux/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-bookworm 2 | 3 | WORKDIR /tester 4 | COPY /Extras/MinimalStreamTester . 5 | 6 | RUN npm install 7 | RUN npx playwright install --with-deps 8 | RUN npx playwright install chrome 9 | 10 | VOLUME /tester/playwright-report 11 | 12 | CMD [ "npx", "playwright", "test" ] 13 | -------------------------------------------------------------------------------- /Extras/MinimalStreamTester/dockerfiles/windows/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | 3 | FROM mcr.microsoft.com/windows:ltsc2019 4 | 5 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"] 6 | 7 | WORKDIR C:/tester 8 | COPY NODE_VERSION . 9 | 10 | RUN $node_version = Get-Content NODE_VERSION -Raw; ` 11 | Invoke-WebRequest -OutFile nodejs.zip -UseBasicParsing "https://nodejs.org/dist/$node_version/node-$node_version-win-x64.zip"; ` 12 | Expand-Archive nodejs.zip -DestinationPath C:\; ` 13 | Rename-Item "C:\node-$node_version-win-x64" c:\nodejs 14 | 15 | RUN Set-ExecutionPolicy -ExecutionPolicy Unrestricted 16 | 17 | RUN setx /M PATH \"$Env:PATH;C:\nodejs\" 18 | 19 | RUN npm config set registry https://registry.npmjs.org/ 20 | 21 | # Copy the signalling server and frontend source code from the build context 22 | COPY /Extras/MinimalStreamTester . 23 | 24 | # Install the dependencies for the signalling server and build the frontend 25 | RUN npm i 26 | RUN npx playwright install --with-deps 27 | RUN npx playwright install chrome 28 | 29 | ENTRYPOINT [ "cmd.exe", "/C", "npx", "playwright", "test" ] 30 | -------------------------------------------------------------------------------- /Extras/MinimalStreamTester/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MinimalStreamTester", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "private": true, 7 | "scripts": { 8 | "build": "", 9 | "clean": "" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "@playwright/test": "^1.49.1", 16 | "@types/node": "^20.12.7", 17 | "@types/uuid": "^9.0.8" 18 | }, 19 | "dependencies": { 20 | "dotenv": "^16.4.5", 21 | "node-fetch": "^2.7.0", 22 | "uuid": "^9.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Extras/SS_Test/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | -------------------------------------------------------------------------------- /Extras/SS_Test/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22.14.0 as builder 2 | 3 | WORKDIR /SignallingTester 4 | 5 | COPY NODE_VERSION ./NODE_VERSION 6 | COPY package.json ./package.json 7 | COPY Common/ ./Common 8 | COPY Extras/SS_Test/ ./Extras/SS_Test 9 | 10 | RUN npm i 11 | RUN cd Common && npm i && npm run build 12 | RUN cd Extras/SS_Test && npm i && npm run build 13 | 14 | USER node 15 | 16 | CMD cd Extras/SS_Test && node dist/index.js 17 | 18 | 19 | -------------------------------------------------------------------------------- /Extras/SS_Test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3.4" 3 | services: 4 | signalling: 5 | build: 6 | context: ../../ 7 | dockerfile: ./SignallingWebServer/Dockerfile 8 | image: signalling 9 | init: true 10 | network_mode: "host" 11 | healthcheck: 12 | test: ["CMD", "curl", "-f", "http://localhost:80"] 13 | interval: 10s 14 | timeout: 5s 15 | retries: 3 16 | start_period: 30s 17 | start_interval: 5s # only supported on docker engine 25+ 18 | 19 | tester: 20 | build: 21 | context: ../../ 22 | dockerfile: ./Extras/SS_Test/Dockerfile 23 | image: signalling_tester 24 | network_mode: "host" 25 | depends_on: 26 | signalling: 27 | condition: service_healthy 28 | 29 | 30 | -------------------------------------------------------------------------------- /Extras/SS_Test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SS_Test", 3 | "version": "1.0.3", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "private": true, 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "clean": "rimraf ./dist", 10 | "build": "tsc", 11 | "rebuild": "npm run clean && npm run build", 12 | "start": "npm run build && node ./dist/index.js" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "@epicgames-ps/lib-pixelstreamingcommon-ue5.6": "*", 18 | "@protobuf-ts/plugin": "^2.9.3", 19 | "ws": "^8.17.1" 20 | }, 21 | "devDependencies": { 22 | "@types/assert": "^1.5.10", 23 | "@types/node": "^20.10.1", 24 | "@types/ws": "^8.5.10", 25 | "rimraf": "^5.0.5", 26 | "typescript": "^5.3.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Extras/SS_Test/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export BUILDKIT_PROGRESS=plain 4 | docker compose up --build --abort-on-container-exit --exit-code-from tester 5 | 6 | if [[ $? -ne 0 ]]; then 7 | echo "Testing failed." 8 | else 9 | echo "Testing succeeded." 10 | fi 11 | 12 | -------------------------------------------------------------------------------- /Extras/SS_Test/src/config.js: -------------------------------------------------------------------------------- 1 | 2 | const config = { 3 | streamerURL: "ws://127.0.0.1:8888", 4 | streamerId: "signalling_tester", 5 | 6 | playerURL: "ws://127.0.0.1:80", 7 | } 8 | 9 | module.exports = config; 10 | -------------------------------------------------------------------------------- /Extras/SS_Test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "noImplicitAny": true, 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "target": "es5", 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "allowJs": true, 11 | "declaration": false 12 | }, 13 | "lib": ["es2015"], 14 | "include": ["./src/*.ts"] 15 | } 16 | -------------------------------------------------------------------------------- /Extras/Scripts/pre-commit-checks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # No longer used in favor of using lint-staged 4 | # Will remove this eventually but leaving here for reference for now 5 | 6 | LINT_CHECK_PATHS=( 7 | "Common/" 8 | "Signalling/" 9 | "Frontend/library/" 10 | "Frontend/ui-library/" 11 | "SignallingWebServer/" 12 | ) 13 | 14 | FAILURE=0 15 | FAILED_PATHS=() 16 | 17 | for CHECK_PATH in "${LINT_CHECK_PATHS[@]}"; do 18 | STAGED_FILES=$(git diff --name-only --cached "$CHECK_PATH") 19 | 20 | # check if any of the npm packages have changes 21 | if [[ -n "$STAGED_FILES" ]]; then 22 | echo ${CHECK_PATH} has changes. Running lint... 23 | pushd $CHECK_PATH >/dev/null 24 | if ! npm run lint; then 25 | FAILURE=1 26 | FAILED_PATHS+=("$CHECK_PATH") 27 | fi 28 | popd >/dev/null 29 | fi 30 | done 31 | 32 | if [[ $FAILURE -eq 1 ]]; then 33 | echo Linting failures in the following paths... 34 | for FAILED_PATH in "${FAILED_PATHS[@]}"; do 35 | echo " $FAILED_PATH" 36 | done 37 | exit 1 38 | fi 39 | 40 | 41 | -------------------------------------------------------------------------------- /Extras/StreamerDocker/Linux/README.md: -------------------------------------------------------------------------------- 1 | ## Software rendering UE streamer 2 | 3 | ### Prepare the project 4 | 5 | You will need to build and package the project targeting SM5. Package it to this directory to make it easy. 6 | 7 | ### Build the image using docker 8 | 9 | Run `./build.sh ` 10 | Supply the tag you want to tag the image as and the location of the packaged project. 11 | Note that docker will use the current directory as the root so if its packaged in `./Packaged/Linux` you will want to supply `/Packaged/Linux` as the path. 12 | Also note that the entrypoint refers to `./Minimal.sh` to start the project. So your project should be named Minimal or update the Dockerfile. 13 | 14 | -------------------------------------------------------------------------------- /Extras/StreamerDocker/Linux/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker buildx build --progress=plain -t $1 --build-arg "MESA_VERSION=24.1.5" --build-arg "PROJECT_PATH=$2" . 3 | 4 | -------------------------------------------------------------------------------- /Extras/StreamerDocker/Linux/extract-and-install-deps.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | from pathlib import Path 3 | import re, subprocess, sys 4 | 5 | # Executes a command and verifies that it succeeds 6 | def run(command): 7 | print(command, file=sys.stderr, flush=True) 8 | return subprocess.run(command, check=True) 9 | 10 | 11 | # Read the contents of the Mesa dependencies shell script 12 | depsScript = Path(sys.argv[1]).read_text('utf-8') 13 | 14 | # Identify the required version of the LLVM toolchain 15 | llvmVersion = re.search('LLVM_VERSION:=([0-9]+)', depsScript).group(1) 16 | 17 | # Extract the list of apt packages that need to be installed 18 | aptPackages = re.search('\DEPS=\(\n(.+?)\n\)\n\n', depsScript, re.DOTALL | re.MULTILINE).group(1) 19 | aptPackages = aptPackages.replace('\\', '') 20 | aptPackages = aptPackages.replace('\"', '') 21 | aptPackages = aptPackages.replace('${LLVM_VERSION}',llvmVersion) 22 | aptPackages = [p.strip() for p in aptPackages.splitlines() if len(p.strip()) > 0] 23 | 24 | # Append any required packages that are missing from the list 25 | PACKAGES = [ 26 | 'libdrm-dev', 27 | 'libudev-dev', 28 | 'libwayland-egl-backend-dev', 29 | 'libxcb-dri2-0-dev', 30 | 'libxcb-dri3-dev', 31 | 'libxcb-glx0-dev', 32 | 'libxcb-present-dev', 33 | 'llvm-{}-dev'.format(llvmVersion), 34 | 'meson' 35 | ] 36 | for package in PACKAGES: 37 | if package not in aptPackages: 38 | aptPackages.append(package) 39 | 40 | run(['pip3', 'install', 'meson==1.4.0']) 41 | 42 | # Install the apt packages (this will include the LLVM toolchain) 43 | run(['apt-get', 'install', '-y', '--no-install-recommends'] + aptPackages) 44 | -------------------------------------------------------------------------------- /Extras/StreamerDocker/Windows/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | FROM mcr.microsoft.com/windows:ltsc2019 3 | 4 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] 5 | RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; ` 6 | Invoke-WebRequest "https://aka.ms/vs/17/release/vc_redist.x64.exe" -OutFile "vc_redist.x64.exe"; ` 7 | Start-Process -filepath C:\vc_redist.x64.exe -ArgumentList "/install", "/passive", "/norestart" -Passthru | Wait-Process; ` 8 | Remove-Item -Force vc_redist.x64.exe; 9 | 10 | ARG PROJECT_DIR=. 11 | COPY $PROJECT_DIR /ue-project/ 12 | WORKDIR /ue-project/ 13 | 14 | ENTRYPOINT ["Minimal/Binaries/Win64/Minimal-Win64-Debug-Cmd.exe", "-warp", "-dx12", "-res=1920", "-resy=720", "-PixelStreamingEncoderCodec=VP8", "-renderoffscreen", "-AllowSoftwareRendering"] 15 | 16 | -------------------------------------------------------------------------------- /Extras/StreamerDocker/Windows/README.md: -------------------------------------------------------------------------------- 1 | ## Software rendering UE streamer for Windows 2 | 3 | ### Prepare the project 4 | 5 | You will need to build and package the project targeting SM5. Package it to this directory to make it easy. 6 | 7 | ### Build the image using docker 8 | 9 | Run `docker build -t --build-arg PROJECT_DIR= .` 10 | Supply the tag you want to tag the image as and the location of the packaged project. 11 | Note that docker will use the current directory as the root so if its packaged in `./Packaged/Windows` you will want to supply `/Packaged/Windows` as the path. 12 | Also note that the entrypoint refers to `Minimal` to start the project. So your project should be named Minimal or update the Dockerfile. 13 | 14 | -------------------------------------------------------------------------------- /Extras/eslint/plugin-check-copyright/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@epicgames-ps/eslint-plugin-check-copyright", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "private": true, 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "devDependencies": { 10 | "eslint": "^9.20.0" 11 | }, 12 | "author": "", 13 | "license": "MIT", 14 | "description": "" 15 | } 16 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: mediasoup 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/.prettierignore: -------------------------------------------------------------------------------- 1 | # Originals from forked repo. 2 | .eslintrc.js 3 | npm-scripts.js 4 | 5 | # Auto-generated contents. 6 | src/BrowserRtpCapabilities.ts 7 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/.prettierrc: -------------------------------------------------------------------------------- 1 | # Use the default formatting style from Prettier. 2 | # No exceptions. 3 | {} 4 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright © 2020, Iñaki Baz Castillo 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/NOTES.md: -------------------------------------------------------------------------------- 1 | # Important note for developers. 2 | Please do not reformat. This package is to stay as close to the original content as possible so that not only 3 | are changes very obvious but any new merges from the original repo can be handled easily. Reformatting this 4 | code might cause headaches for merges in the future. 5 | 6 | ## Merging upstream changes 7 | If there is a change upstream that we wish to merge in we can achieve that by the following. 8 | ``` 9 | git subtree pull --prefix Extras/mediasoup-sdp-bridge https://github.com/OpenVidu/mediasoup-sdp-bridge.git v3 10 | ``` 11 | This will pull changes from the v3 branch into this subtree. 12 | 13 | 14 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/tools/browser-rtpcapabilities/README.md: -------------------------------------------------------------------------------- 1 | # Truncated 2 | Removed due to vulnerabilities in the dependencies 3 | This was only a tool that extracted capabilities from the browser. It is not needed. If we do need it we can recover it from the source repo. 4 | 5 | -------------------------------------------------------------------------------- /Extras/mediasoup-sdp-bridge/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node16/tsconfig.json", 3 | 4 | "compileOnSave": true, 5 | "compilerOptions": { 6 | "baseUrl": "./", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "incremental": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitReturns": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": false, 14 | "outDir": "./lib", 15 | "removeComments": true, 16 | "sourceMap": true 17 | }, 18 | "include": ["./src"] 19 | } 20 | -------------------------------------------------------------------------------- /Frontend/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | types/ 4 | .vscode 5 | -------------------------------------------------------------------------------- /Frontend/Docs/Accessing the Pixel Streaming Blueprint API.md: -------------------------------------------------------------------------------- 1 | ## Accessing the Pixel Streaming Blueprint API 2 | 3 | The Pixel Streaming Plugin that runs within the Unreal Engine exposes a Blueprint API that you can use in your gameplay logic to handle custom UI events sent by the player HTML page, and to emit events from the Unreal Engine to the player page. 4 | 5 | To access this Blueprint API, add the **PixelStreamingInputComponent** to an Actor in your level. Your application's **PlayerController** is a safe choice. You can do this by clicking **Add Component** in the Blueprint menu and selecting the **Pixel Streaming Input** component from the dropdown. 6 | 7 | 8 |

9 | Adding the Pixel Streaming component 10 |

11 | 12 | 13 | **_NOTE:_** Prior to UE 4.27, the PixelStreamingInput Component was automatically added when you loaded the Pixel Streaming plugin. This was problematic, and now requires users to add this to their project themselves, as seen above. 14 | -------------------------------------------------------------------------------- /Frontend/Docs/Customizing the Player Widget Style.md: -------------------------------------------------------------------------------- 1 | ## Customizing the Player Widget Style 2 | 3 | CSS Styles for the frontend application are applied on page-load using [`PixelStreamingApplicationStyle`](/Frontend/ui-library/src/Styles/PixelStreamingApplicationStyles.ts) object, which is then applied to the page using the `PixelStreamingApplicationStyle.applyStyleSheet` method. This must be invoked in your implementation before the the application object is created and added to the page. 4 | 5 | Rather than altering or extending the `PixelStreamingApplicationStyle` class, the constructor can be supplied with an object containing your desired CSS options as well as separate base color palettes (reused extensively by the default style) for light mode and dark mode. Further customizations to the base color palette can be made either by using the `setColorMode` method to select light mode or dark, or by invoking `applyPalette` with a custom `ColorPalette`. 6 | 7 | This system will apply over any existing CSS in your implementation's HTML page and so it is recommended this method be used for the cleanest interoperability with the rest of the frontend infrastructure. 8 | 9 | -------------------------------------------------------------------------------- /Frontend/Docs/README.md: -------------------------------------------------------------------------------- 1 | Pixel Streaming Infrastructure Frontend Documentation 2 | --- 3 | 4 | * [Accessing the Pixel Streaming Blueprint API](/Frontend/Docs/Accessing%20the%20Pixel%20Streaming%20Blueprint%20API.md) 5 | * [Communicating from the Player Page to Unreal Engine](/Frontend/Docs/Communicating%20from%20the%20Player%20Page%20to%20UE5.md) 6 | * [Communicating from Unreal Engine to the Player Page](/Frontend/Docs/Communicating%20from%20UE5%20to%20the%20Player%20Page.md) 7 | * [Customizing Player Input Options](/Frontend/Docs/Customizing%20Player%20Input%20Options.md) 8 | * [Customizing the Player Webpage](/Frontend/Docs/Customizing%20the%20Player%20Webpage.md) 9 | * [Customizing Player Widget Style](/Frontend/Docs/Customizing%20the%20Player%20Widget%20Style.md) 10 | * [HTML Page Requirements](/Frontend/Docs/HTML%20Page%20Requirements.md) 11 | * [The Settings Panel](/Frontend/Docs/Settings%20Panel.md) 12 | * [Timing Out Inactive Connections](/Frontend/Docs/Timing%20Out%20Inactive%20Connections.md) 13 | 14 | -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/add-pixel-streaming-to-actor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/add-pixel-streaming-to-actor.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/afk-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/afk-warning.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/mic-toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/mic-toggle.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-add-component.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-add-component.jpg -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-bpapi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-bpapi.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-custom-topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-custom-topic.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-getcomponentbyclass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-getcomponentbyclass.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-input.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-input.jpg -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-send-game-event-json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-send-game-event-json.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-send-game-event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-send-game-event.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-ui-interaction-event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-ui-interaction-event.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-ui-interaction-extract-json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-ui-interaction-extract-json.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/pixelstreaming-ui-interaction-search-substring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/pixelstreaming-ui-interaction-search-substring.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/send_pixel_streaming_response.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/send_pixel_streaming_response.JPG -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/settings-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/settings-panel.png -------------------------------------------------------------------------------- /Frontend/Docs/Resources/Images/settings-pixel-streaming-audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/Docs/Resources/Images/settings-pixel-streaming-audio.png -------------------------------------------------------------------------------- /Frontend/implementations/angular/readme.md: -------------------------------------------------------------------------------- 1 | # Angular Implementations 2 | 3 | Here are a selection of community contributed implementations of Angular frontends. 4 | 5 | - [cheikhnadiouf](https://github.com/cheikhnadiouf)'s implementation - [LINK](https://github.com/cheikhnadiouf/PixelStreamingInfrastructure/tree/AngularImplementations/Frontend/implementations/angular) 6 | 7 | If you wish to contribute your own example frontend, please open an issue/PR. 8 | 9 | **Disclaimer: We do not warrant these for any fitness of purpose, nor do we maintain them.** 10 | -------------------------------------------------------------------------------- /Frontend/implementations/react/.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | docs/ 3 | node_modules/ 4 | types/ 5 | package-lock.json 6 | package.json 7 | .cspell.json 8 | tsconfig.json 9 | webpack.config.js 10 | .eslintrc.js 11 | .vscode 12 | -------------------------------------------------------------------------------- /Frontend/implementations/react/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /Frontend/implementations/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@epicgames-ps/react-pixelstreamingfrontend-react-ue5.6", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "./src/index.tsx", 6 | "private": true, 7 | "scripts": { 8 | "clean": "rimraf ./dist", 9 | "build": "npx webpack --config webpack.prod.js", 10 | "build:dev": "npx webpack --config webpack.dev.js", 11 | "rebuild": "npm run clean && npm run build", 12 | "watch": "npx webpack --watch", 13 | "serve": "webpack serve --config webpack.dev.js", 14 | "serve-prod": "webpack serve --config webpack.prod.js" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^19.0.8", 18 | "@types/react-dom": "^19.0.3", 19 | "html-loader": "^5.1.0", 20 | "html-webpack-plugin": "^5.6.3", 21 | "ts-loader": "^9.5.2", 22 | "typescript": "^5.7.3", 23 | "webpack": "^5.97.1", 24 | "webpack-cli": "^6.0.1" 25 | }, 26 | "dependencies": { 27 | "@epicgames-ps/lib-pixelstreamingfrontend-ue5.6": "*", 28 | "react": "^19.0.0", 29 | "react-dom": "^19.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Frontend/implementations/react/readme.md: -------------------------------------------------------------------------------- 1 | ## Pixel Streaming sample React application 2 | 3 | A minimal sample application that uses the Pixel Streaming library in React. 4 | 5 | ### Key features 6 | - A minimal React application with a Pixel Streaming wrapper component 7 | - Starts a Pixel Streaming session on wrapper component mount 8 | - Disconnects the session on wrapper component unmount e.g. if navigating to another view in a single page app 9 | - Hooks to `playStreamRejected` event and displays a `Click to play` overlay if the browser rejects video stream auto-play 10 | 11 | ### Developing 12 | 13 | To build and run the React application, run: 14 | 15 | - `npm install` 16 | - `npm run build-all` 17 | - `npm run serve` 18 | -------------------------------------------------------------------------------- /Frontend/implementations/react/src/assets/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/react/src/assets/images/favicon-16x16.png -------------------------------------------------------------------------------- /Frontend/implementations/react/src/assets/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/react/src/assets/images/favicon-32x32.png -------------------------------------------------------------------------------- /Frontend/implementations/react/src/assets/images/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/react/src/assets/images/favicon-96x96.png -------------------------------------------------------------------------------- /Frontend/implementations/react/src/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/react/src/assets/images/favicon.ico -------------------------------------------------------------------------------- /Frontend/implementations/react/src/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/react/src/assets/images/favicon.png -------------------------------------------------------------------------------- /Frontend/implementations/react/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import React from 'react'; 4 | import { PixelStreamingWrapper } from './PixelStreamingWrapper'; 5 | 6 | export const App = () => { 7 | return ( 8 |
14 | 24 |
25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /Frontend/implementations/react/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Pixel Streaming 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Frontend/implementations/react/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import React from 'react'; 3 | import { createRoot } from 'react-dom/client'; 4 | import { App } from './components/App'; 5 | 6 | document.body.onload = function () { 7 | // Attach the React app root component to document.body 8 | createRoot(document.body).render(); 9 | }; 10 | -------------------------------------------------------------------------------- /Frontend/implementations/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "noImplicitAny": true, 5 | "module": "es6", 6 | "esModuleInterop": true, 7 | "target": "es5", 8 | "moduleResolution": "node", 9 | "sourceMap": false, 10 | "allowJs": true, 11 | "declaration": false, 12 | "jsx": "react-jsx" 13 | }, 14 | "lib": ["es2015"], 15 | "include": ["./src/*.tsx"], 16 | } 17 | -------------------------------------------------------------------------------- /Frontend/implementations/react/webpack.dev.js: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | const { merge } = require('webpack-merge'); 4 | const common = require('./webpack.common.js'); 5 | const path = require('path'); 6 | 7 | module.exports = merge(common, { 8 | mode: 'development', 9 | devtool: 'inline-source-map' 10 | }); 11 | -------------------------------------------------------------------------------- /Frontend/implementations/react/webpack.prod.js: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | const { merge } = require('webpack-merge'); 4 | const common = require('./webpack.common.js'); 5 | 6 | module.exports = merge(common, { 7 | mode: 'production', 8 | optimization: { 9 | usedExports: true, 10 | minimize: true 11 | }, 12 | stats: 'errors-only', 13 | performance: { 14 | hints: false 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@epicgames-ps/reference-pixelstreamingfrontend-ue5.6", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "./src/player.ts", 6 | "private": true, 7 | "scripts": { 8 | "clean": "rimraf ./dist", 9 | "build": "npx webpack --config webpack.prod.js", 10 | "build:dev": "npx webpack --config webpack.dev.js", 11 | "build:esm": "npx webpack --config webpack.esmodule.js", 12 | "build:prod": "npx webpack --config webpack.prod.js", 13 | "rebuild": "npm run clean && npm run build", 14 | "watch": "webpack --watch --config webpack.dev.js", 15 | "serve": "webpack serve --config webpack.dev.js", 16 | "serve-prod": "webpack serve --config webpack.prod.js" 17 | }, 18 | "devDependencies": { 19 | "html-loader": "^5.1.0", 20 | "html-webpack-plugin": "^5.6.3", 21 | "ts-loader": "^9.5.2", 22 | "webpack": "^5.97.1", 23 | "webpack-cli": "^6.0.1" 24 | }, 25 | "dependencies": { 26 | "@epicgames-ps/lib-pixelstreamingfrontend-ue5.6": "*", 27 | "@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.6": "*" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/readme.md: -------------------------------------------------------------------------------- 1 | ## TypeScript Reference Frontend 2 | 3 | This is the frontend we ship with the Pixel Streaming plugin. The reference frontend contains: 4 | 5 | 1. The base `lib-pixelstreamingfrontend` library. 6 | 2. The reference ui plugin for the base library `lib-pixelstreamingfrontend-ui`. 7 | 8 | Using these two libraries gives a fully functional (and customizable) Pixel Streaming experience. 9 | 10 | This package is also a good example of how to include the frontend libraries as dependencies and bundle/minify the final application you ship. 11 | 12 | ### Key features of the reference frontend 13 | - An info panel (screen right) that provides a UI for displaying live statistics to the user. 14 | - A settings panel (screen right) that provides a UI for all the options inside [config.ts](/Frontend/library/src/Config/Config.ts). 15 | - A set of controls (screen left) to maximize the video, open the settings panel, open the info panel, and enter VR mode. 16 | - Ability to display overlays that present information or errors to the user, or present prompts for the user to interact with. 17 | 18 | ### Building the reference frontend 19 | ``` 20 | cd Frontend/implementations/typescript 21 | npm install 22 | npm run build 23 | ``` 24 | 25 | ### Using the reference frontend 26 | Building the reference frontend using the commands above will place it in the `SignallingWebServer/www` directory. 27 | ``` 28 | # Serve the reference frontend 29 | cd SignallingWebServer/platform_scripts/cmd 30 | start.bat 31 | # Navigate to http://localhost in your browser to see the reference frontend 32 | ``` 33 | 34 | ***Note:* You can also run `start.bat --build` to build all the dependent libraries. 35 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/css/login.css: -------------------------------------------------------------------------------- 1 | /* Copyright Epic Games, Inc. All Rights Reserved. */ 2 | 3 | body { 4 | margin: 0px; 5 | background-color: black; 6 | font-family: 'Montserrat', sans-serif; 7 | justify-content: center; 8 | display: flex; 9 | align-items: center; 10 | height: 100vh; 11 | } 12 | 13 | form { 14 | background-color: white; 15 | width: 50%; 16 | padding: 5rem; 17 | } 18 | 19 | div { 20 | padding: 1rem; 21 | display: inline-flex; 22 | width: 100%; 23 | } 24 | 25 | .button { 26 | text-align: center; 27 | display: block; 28 | padding-bottom: 0; 29 | } 30 | 31 | input { 32 | border: none; 33 | border-bottom: 2px solid #3c3b40; 34 | width: 100%; 35 | line-height: 3rem; 36 | font-size: 1.25rem; 37 | font-family: 'Montserrat', sans-serif; 38 | } 39 | 40 | button { 41 | background-color: #3c3b40; 42 | border: 3px solid #3c3b40; 43 | color: #fff; 44 | width: 6rem; 45 | padding: 0.5rem; 46 | text-align: center; 47 | line-height: 1.75rem; 48 | font-family: 'Montserrat'; 49 | border-radius: 4px; 50 | } 51 | 52 | button:hover { 53 | background-color: #0585fe; 54 | border: 3px solid #0585fe; 55 | transition: 0.25s ease; 56 | } 57 | 58 | button:active { 59 | background-color: #3c3b40; 60 | border: 3px solid #0585fe; 61 | } 62 | 63 | *:focus { 64 | outline: none; 65 | } 66 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/css/stresstest.css: -------------------------------------------------------------------------------- 1 | /* Copyright Epic Games, Inc. All Rights Reserved. */ 2 | 3 | body { 4 | height: 100vh; 5 | color: #000; 6 | background-color: #fff; 7 | } 8 | 9 | #control { 10 | width: 100vw; 11 | height: 10%; 12 | } 13 | 14 | #control > div, button { 15 | margin-top: 15px; 16 | display: inline-block; 17 | } 18 | 19 | #control > button { 20 | background-color: #3c3b40; 21 | border: 3px solid #3c3b40; 22 | color: #fff; 23 | width: 6rem; 24 | 25 | padding: 0.5rem; 26 | text-align: center; 27 | line-height: 1.75rem; 28 | font-family: 'Montserrat'; 29 | margin-left: 1%; 30 | } 31 | 32 | #control > button:hover { 33 | background-color: #0585fe; 34 | border: 3px solid #0585fe; 35 | transition: 0.25s ease; 36 | } 37 | 38 | #control > button:active { 39 | background-color: #3c3b40; 40 | border: 3px solid #0585fe; 41 | } 42 | 43 | #streamsContainer { 44 | height: 90%; 45 | display: grid; 46 | align-content: stretch; 47 | grid-template-columns: 1fr 1fr 1fr; 48 | } 49 | 50 | #streamsContainer > div { 51 | margin: 10px; 52 | } -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/Aurora.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/Aurora.jpg -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/Crunch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/Crunch.jpg -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/favicon-16x16.png -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/favicon-32x32.png -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/favicon-96x96.png -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/favicon.ico -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/implementations/typescript/src/assets/images/favicon.png -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/player.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Pixel Streaming 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/player.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | export * from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.6'; 4 | export * from '@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.6'; 5 | import { Config, PixelStreaming, Logger, LogLevel } from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.6'; 6 | import { Application, PixelStreamingApplicationStyle } from '@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.6'; 7 | const PixelStreamingApplicationStyles = 8 | new PixelStreamingApplicationStyle(); 9 | PixelStreamingApplicationStyles.applyStyleSheet(); 10 | 11 | // expose the pixel streaming object for hooking into. tests etc. 12 | declare global { 13 | interface Window { pixelStreaming: PixelStreaming; } 14 | } 15 | 16 | document.body.onload = function() { 17 | Logger.InitLogging(LogLevel.Warning, true); 18 | 19 | // Create a config object 20 | const config = new Config({ useUrlParams: true }); 21 | 22 | // Create the main Pixel Streaming object for interfacing with the web-API of Pixel Streaming 23 | const stream = new PixelStreaming(config); 24 | 25 | const application = new Application({ 26 | stream, 27 | onColorModeChanged: (isLightMode) => PixelStreamingApplicationStyles.setColorMode(isLightMode) 28 | }); 29 | document.body.appendChild(application.rootElement); 30 | 31 | window.pixelStreaming = stream; 32 | } 33 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/stresstest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Pixel Streaming Stress Tester 18 | 19 | 20 | 21 |
22 | 23 |
Total streams: 0
24 |
25 | Max peers: 26 | 5 27 | 28 |
29 |
30 | Peer creation interval (seconds): 31 | 32 |
33 |
34 | Peer deletion interval (seconds): 35 | 36 |
37 |
38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/src/uiless.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { Config, PixelStreaming } from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.6'; 4 | 5 | document.body.onload = function() { 6 | 7 | // Create a config object 8 | const config = new Config({ 9 | initialSettings: { 10 | AutoPlayVideo: true, 11 | AutoConnect: true, 12 | StartVideoMuted: true, 13 | WaitForStreamer: true, 14 | } 15 | }); 16 | 17 | // Create a PixelStreaming instance and attach the video element to an existing parent div 18 | const pixelStreaming = new PixelStreaming(config, { videoElementParent: document.getElementById("videoParentElement")}); 19 | 20 | // If browser denies autoplay, show "Click to play" and register a click-to-play handler 21 | pixelStreaming.addEventListener("playStreamRejected", () => { 22 | const clickToPlay = document.getElementById("clickToPlayElement"); 23 | clickToPlay.className = "visible"; 24 | clickToPlay.onclick = () => { 25 | pixelStreaming.play(); 26 | clickToPlay.className = ""; 27 | clickToPlay.onclick = undefined; 28 | } 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/cjs", 5 | "module": "node16", 6 | "moduleResolution": "node16" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/esm", 5 | "module": "es6", 6 | "moduleResolution": "bundler" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "esModuleInterop": true, 5 | "target": "ES6", 6 | "sourceMap": true, 7 | "allowJs": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noImplicitOverride": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitReturns": true, 12 | "noPropertyAccessFromIndexSignature": true, 13 | "declaration": true, 14 | "declarationDir": "./dist/types", 15 | "moduleResolution": "bundler" // helps IDEs 16 | }, 17 | "lib": ["ES6"], 18 | "include": ["./src/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/webpack.dev.js: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | const { merge } = require('webpack-merge'); 4 | const common = require('./webpack.base.js'); 5 | const path = require('path'); 6 | 7 | module.exports = merge(common, { 8 | mode: 'development', 9 | devtool: 'inline-source-map', 10 | }); 11 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/webpack.esmodule.js: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const path = require('path'); 5 | 6 | module.exports = { 7 | mode: 'development', 8 | devtool: 'inline-source-map', 9 | entry: './src/player.ts', 10 | plugins: [ 11 | new HtmlWebpackPlugin({ 12 | title: `Pixel Streaming ES Module`, 13 | scriptLoading: 'module', 14 | template: `./src/player.html`, 15 | filename: `player_esm.html` 16 | }), 17 | ], 18 | output: { 19 | filename: 'player.esm.js', 20 | libraryTarget: 'module', 21 | module: true, 22 | path: process.env.WEBPACK_OUTPUT_PATH ? path.resolve(process.env.WEBPACK_OUTPUT_PATH) : path.resolve(__dirname, '../../../SignallingWebServer/www'), 23 | globalObject: 'this', 24 | hashFunction: 'xxhash64' 25 | }, 26 | experiments: { 27 | outputModule: true, 28 | }, 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.tsx?$/, 33 | loader: 'ts-loader', 34 | exclude: [ 35 | /node_modules/, 36 | ], 37 | options: { 38 | configFile: "tsconfig.esm.json" 39 | } 40 | }, 41 | { 42 | test: /\.html$/i, 43 | use: 'html-loader' 44 | }, 45 | { 46 | test: /\.css$/, 47 | type: 'asset/resource', 48 | generator: { 49 | filename: 'css/[name][ext]' 50 | } 51 | }, 52 | { 53 | test: /\.(png|svg|jpg|jpeg|gif)$/i, 54 | type: 'asset/resource', 55 | generator: { 56 | filename: 'images/[name][ext]' 57 | } 58 | } 59 | ], 60 | }, 61 | resolve: { 62 | extensions: ['.tsx', '.ts', '.js', '.svg', '.json'], 63 | }, 64 | }; 65 | -------------------------------------------------------------------------------- /Frontend/implementations/typescript/webpack.prod.js: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | const { merge } = require('webpack-merge'); 4 | const common = require('./webpack.base.js'); 5 | const TerserPlugin = require('terser-webpack-plugin'); 6 | 7 | module.exports = merge(common, { 8 | mode: 'production', 9 | optimization: { 10 | usedExports: true, 11 | minimize: true, 12 | minimizer: [new TerserPlugin({ 13 | extractComments: false, 14 | })], 15 | }, 16 | stats: 'errors-only', 17 | performance: { 18 | hints: false 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /Frontend/library/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '../../.lintstagedrc.mjs' 2 | 3 | export default { 4 | ...baseConfig, 5 | '*.ts': 'eslint --fix', 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Frontend/library/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/library/.npmignore -------------------------------------------------------------------------------- /Frontend/library/.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/library/.prettierignore -------------------------------------------------------------------------------- /Frontend/library/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/lib-pixelstreamingfrontend-ue5.6 2 | 3 | ## 1.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 208d100: Add: a html modal for editing text input that is shown on the frontend when user clicks/taps on a streamed UE widget. 8 | 9 | This edit text modal fixes the following: 10 | 11 | - Fix: Users can now input non-latin characters (e.g. Chinese, Japanese, Korean etc.) using IME assistance. 12 | - Fix: Users on mobile can now type using on-device native on-screen keyboards (which was previously non-functioning). 13 | - Add: Users can copy/paste from their clipboard into the edit text modal naturally. 14 | 15 | When adding this modal the following was also fixed and extended: 16 | 17 | - Fix: Typing into other frontend widgets (e.g. the settings panel) no longer sends input to the focused UE widget. 18 | - Add: Exposed a frontend event for when UE sends text input content, meaning customisation of behaviour is now possible. 19 | - Docs: Added docs explaning this new edit text modal. 20 | 21 | Further details about the edit text modal as mentioned in this PR: https://github.com/EpicGamesExt/PixelStreamingInfrastructure/pull/564 22 | -------------------------------------------------------------------------------- /Frontend/library/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest/presets/js-with-ts", 3 | testEnvironment: "jsdom", 4 | transform: { 5 | "^.+\\.tsx?$": [ 6 | "ts-jest", 7 | { 8 | tsconfig: "tsconfig.jest.json", 9 | }, 10 | ], 11 | }, 12 | modulePathIgnorePatterns: ["/build/"], 13 | testPathIgnorePatterns: ["/build/", "/node_modules/"], 14 | globals: { 15 | TextDecoder: TextDecoder, 16 | TextEncoder: TextEncoder, 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /Frontend/library/readme.md: -------------------------------------------------------------------------------- 1 | ## lib-pixelstreamingfrontend 2 | 3 | The core library for the browser/client side of Pixel Streaming experiences. **This library contains no UI.** 4 | 5 | See [lib-pixelstreamingfrontend-ui](/Frontend/implementations/typescript) for an example of how to build UI on top of this library. 6 | 7 | ### Key features 8 | - Create a websocket connection to communicate with the signalling server. 9 | - Create a WebRTC peer connection that displays the Unreal Engine video and audio. 10 | - Handling of input from the user and transmitting it back to Unreal Engine. 11 | - Opens a data channel connection sending and receiving custom data (in addition to input). 12 | - Programmable and url specified settings. 13 | 14 | ### Adding it to your project 15 | `npm install @epicgames-ps/lib-pixelstreamingfrontend-ue5.5` 16 | 17 | ### How this library is built 18 | The NPM packages supports: 19 | - ES6 module usage 20 | - CommonJS usage 21 | - Type definitions 22 | - Source maps 23 | 24 | **Note:** The NPM package does not contain a minified/bundled output, this is up to the user to do this in their application. 25 | -------------------------------------------------------------------------------- /Frontend/library/src/Inputs/GamepadTypes.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * The interface for controllers 5 | */ 6 | export interface Controller { 7 | currentState: Gamepad; 8 | prevState: Gamepad; 9 | id: number | undefined; 10 | } 11 | 12 | /** 13 | * Deep copies the values from a gamepad by first converting it to a JSON object and then back to a gamepad 14 | * 15 | * @param gamepad the original gamepad 16 | * @returns a new gamepad object, populated with the original gamepads values 17 | */ 18 | export function deepCopyGamepad(gamepad: Gamepad): Gamepad { 19 | return JSON.parse( 20 | JSON.stringify({ 21 | buttons: gamepad.buttons.map((b) => 22 | JSON.parse( 23 | JSON.stringify({ 24 | pressed: b.pressed, 25 | touched: b.touched, 26 | value: b.value 27 | }) 28 | ) 29 | ), 30 | axes: gamepad.axes 31 | }) 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /Frontend/library/src/Inputs/IInputController.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | /** 3 | * The base interface for all input controllers. 4 | * Since controllers mostly just register events and handle them the external interface is limited 5 | * to register/unregister 6 | */ 7 | export interface IInputController { 8 | /** 9 | * Tells the controller to register itself to the events it needs to operate. 10 | */ 11 | register(): void; 12 | 13 | /** 14 | * Tells the cnotroller to unregister from the events it previously registered to. 15 | * No behaviour through the controller should happen past this point until register is called again. 16 | */ 17 | unregister(): void; 18 | } 19 | -------------------------------------------------------------------------------- /Frontend/library/src/Inputs/MouseButtons.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Mouse Button Data 5 | * {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button} 6 | */ 7 | export class MouseButton { 8 | static mainButton = 0; // Left button. 9 | static auxiliaryButton = 1; // Wheel button. 10 | static secondaryButton = 2; // Right button. 11 | static fourthButton = 3; // Browser Back button. 12 | static fifthButton = 4; // Browser Forward button. 13 | } 14 | 15 | /** 16 | * Mouse Button Mask Data 17 | * {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons} 18 | */ 19 | export class MouseButtonsMask { 20 | static primaryButton = 1; // Left button. 21 | static secondaryButton = 2; // Right button. 22 | static auxiliaryButton = 4; // Wheel button. 23 | static fourthButton = 8; // Browser Back button. 24 | static fifthButton = 16; // Browser Forward button. 25 | } 26 | -------------------------------------------------------------------------------- /Frontend/library/src/Inputs/SpecialKeyCodes.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Registers the Special Key codes 5 | * Must be kept in sync with JavaScriptKeyCodeToFKey C++ array. 6 | * The index of the entry in the array is the special key code given below. 7 | */ 8 | export class SpecialKeyCodes { 9 | static backSpace = 8; 10 | static shift = 16; 11 | static control = 17; 12 | static alt = 18; 13 | static rightShift = 253; 14 | static rightControl = 254; 15 | static rightAlt = 255; 16 | } 17 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/CandidatePairStats.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * ICE Candidate Pair Stats collected from the RTC Stats Report 5 | */ 6 | export class CandidatePairStats { 7 | bytesReceived: number; 8 | bytesSent: number; 9 | currentRoundTripTime: number; 10 | id: string; 11 | lastPacketReceivedTimestamp: number; 12 | lastPacketSentTimestamp: number; 13 | localCandidateId: string; 14 | nominated: boolean; 15 | priority: number; 16 | readable: boolean; 17 | remoteCandidateId: string; 18 | selected: boolean; 19 | state: string; 20 | timestamp: number; 21 | transportId: string; 22 | type: string; 23 | writable: boolean; 24 | } 25 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/CandidateStat.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * ICE Candidate Stat collected from the RTC Stats Report 5 | */ 6 | export class CandidateStat { 7 | address: string; 8 | candidateType: string; 9 | id: string; 10 | label: string; 11 | port: number; 12 | protocol: 'tcp' | 'udp'; 13 | relayProtocol: 'tcp' | 'udp' | 'tls'; 14 | transportId: string; 15 | } 16 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/CodecStats.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Codec Stats collected from the RTC Stats Report 5 | */ 6 | export class CodecStats { 7 | /* common stats */ 8 | clockRate: number; 9 | id: string; 10 | mimeType: string; 11 | payloadType: number; 12 | sdpFmtpLine: string; 13 | timestamp: number; 14 | transportId: string; 15 | type: string; 16 | 17 | /* audio specific stats */ 18 | channels: number; 19 | } 20 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/DataChannelStats.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Data Channel Stats collected from the RTC Stats Report 5 | */ 6 | export class DataChannelStats { 7 | bytesReceived: number; 8 | bytesSent: number; 9 | dataChannelIdentifier: number; 10 | id: string; 11 | label: string; 12 | messagesReceived: number; 13 | messagesSent: number; 14 | protocol: string; 15 | state: string; 16 | timestamp: number; 17 | } 18 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/InboundTrackStats.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Inbound Track Stats collected from the RTC Stats Report 5 | */ 6 | export class InboundTrackStats { 7 | type: string; 8 | kind: string; 9 | trackIdentifier: string; 10 | receiveToCompositeMs: number; 11 | timestamp: number; 12 | bytesReceived: number; 13 | framesDecoded: number; 14 | packetsLost: number; 15 | bytesReceivedStart: number; 16 | framesDecodedStart: number; 17 | timestampStart: number; 18 | bitrate: number; 19 | lowBitrate: number; 20 | highBitrate: number; 21 | avgBitrate: number; 22 | framerate: number; 23 | lowFramerate: number; 24 | highFramerate: number; 25 | averageFrameRate: number; 26 | framesDropped: number; 27 | framesReceived: number; 28 | framesDroppedPercentage: number; 29 | frameHeight: number; 30 | frameWidth: number; 31 | frameHeightStart: number; 32 | frameWidthStart: number; 33 | jitter: number; 34 | } 35 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/SessionStats.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Session statistics 5 | */ 6 | export class SessionStats { 7 | runTime: string; 8 | controlsStreamInput: string; 9 | videoEncoderAvgQP: number; 10 | } 11 | -------------------------------------------------------------------------------- /Frontend/library/src/PeerConnectionController/StreamStats.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Class to hold the stream stats data coming in from webRtc 5 | */ 6 | export class StreamStats { 7 | id: string; 8 | streamIdentifier: string; 9 | timestamp: number; 10 | trackIds: string[]; 11 | } 12 | -------------------------------------------------------------------------------- /Frontend/library/src/UeInstanceMessage/ResponseController.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.6'; 4 | 5 | export class ResponseController { 6 | responseEventListeners: Map void> = new Map(); 7 | 8 | /** 9 | * Add a response event listener to the response map 10 | * @param name - The name of the response 11 | * @param listener - The method to be activated when the response is selected 12 | */ 13 | addResponseEventListener(name: string, listener: (response: string) => void) { 14 | this.responseEventListeners.set(name, listener); 15 | } 16 | 17 | /** 18 | * Remove a response event listener to the response map 19 | * @param name - The name of the response 20 | */ 21 | removeResponseEventListener(name: string) { 22 | this.responseEventListeners.delete(name); 23 | } 24 | 25 | /** 26 | * Handle a response when receiving one form the streamer 27 | * @param message - Data received from the data channel with the command in question 28 | */ 29 | onResponse(message: ArrayBuffer) { 30 | Logger.Info('DataChannelReceiveMessageType.Response'); 31 | const responses = new TextDecoder('utf-16').decode(message.slice(1)); 32 | 33 | Logger.Info(responses); 34 | this.responseEventListeners.forEach((listener: (response: string) => void) => { 35 | listener(responses); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Frontend/library/src/Util/BrowserUtils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.6'; 4 | 5 | export class BrowserUtils { 6 | static getSupportedVideoCodecs(): Array { 7 | const browserSupportedCodecs: Array = []; 8 | // Try get the info needed from the RTCRtpReceiver. This is only available on chrome 9 | if (!RTCRtpReceiver.getCapabilities) { 10 | Logger.Warning( 11 | 'RTCRtpReceiver.getCapabilities API is not available in your browser, defaulting to guess that we support H.264.' 12 | ); 13 | browserSupportedCodecs.push( 14 | 'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f' 15 | ); 16 | return browserSupportedCodecs; 17 | } 18 | 19 | const matcher = /(VP\d|H26\d|AV1).*/; 20 | const capabilities = RTCRtpReceiver.getCapabilities('video'); 21 | if (!capabilities) { 22 | browserSupportedCodecs.push( 23 | 'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f' 24 | ); 25 | return browserSupportedCodecs; 26 | } 27 | capabilities.codecs.forEach((codec) => { 28 | const str = codec.mimeType.split('/')[1] + ' ' + (codec.sdpFmtpLine || ''); 29 | const match = matcher.exec(str); 30 | if (match !== null) { 31 | browserSupportedCodecs.push(str); 32 | } 33 | }); 34 | return browserSupportedCodecs; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Frontend/library/src/Util/IURLSearchParams.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | /** 3 | * A case insensitive, partial implementation of URLSearchParams 4 | */ 5 | export class IURLSearchParams { 6 | _urlParams: Record; 7 | 8 | constructor(search: string) { 9 | this._urlParams = {}; 10 | const urlParams = new URLSearchParams(search); 11 | for (const [name, value] of urlParams) { 12 | this._urlParams[name.toLowerCase()] = value; 13 | } 14 | } 15 | 16 | public has(name: string): boolean { 17 | return name.toLowerCase() in this._urlParams; 18 | } 19 | 20 | public get(name: string): string | null { 21 | if (this.has(name)) { 22 | return this._urlParams[name.toLowerCase()]; 23 | } 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Frontend/library/src/__test__/mockRTCRtpReceiver.ts: -------------------------------------------------------------------------------- 1 | export const mockRTCRtpReceiverImpl = { 2 | prototype: jest.fn(), 3 | getCapabilities: () => ({ 4 | codecs: [ 5 | { 6 | clockRate: 60, 7 | mimeType: "testMimeType", 8 | sdpFmtpLine: "AV1" 9 | } 10 | ] as RTCRtpCodec[], 11 | headerExtensions: [] as RTCRtpHeaderExtensionCapability[] 12 | }) 13 | } as any as typeof global.RTCRtpReceiver; 14 | 15 | const originalRTCRtpReceiver = global.RTCRtpReceiver; 16 | export const mockRTCRtpReceiver = () => { 17 | global.RTCRtpReceiver = mockRTCRtpReceiverImpl; 18 | } 19 | 20 | export const unmockRTCRtpReceiver = () => { 21 | global.RTCRtpReceiver = originalRTCRtpReceiver; 22 | } 23 | -------------------------------------------------------------------------------- /Frontend/library/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/cjs", 5 | "module": "node16", 6 | "moduleResolution": "node16" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/library/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/esm", 5 | "module": "es6", 6 | "moduleResolution": "bundler" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/library/tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["./src/**/*.ts"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "module": "commonjs" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/library/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "noImplicitAny": true, 5 | "esModuleInterop": true, 6 | "target": "ES6", 7 | "sourceMap": true, 8 | "allowJs": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noImplicitOverride": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "noPropertyAccessFromIndexSignature": true, 14 | "declaration": true, 15 | "declarationDir": "./dist/types", 16 | "moduleResolution": "bundler" // helps IDEs 17 | }, 18 | "lib": ["ES6"], 19 | "include": ["./src/**/*.ts"], 20 | "exclude": ["./src/**/*.test.ts"], 21 | "typedocOptions": { 22 | "exclude": "src/index.*", 23 | "entryPoints": ["src/pixelstreamingfrontend.ts"], 24 | "sort": ["enum-value-ascending", "required-first", "source-order"], 25 | "out": "docs", 26 | "theme": "default", 27 | "hideGenerator": "true" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Frontend/ui-library/.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1", 3 | "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/master/cspell.schema.json", 4 | "language": "en", 5 | "words": [ 6 | "unquantize", 7 | "denormalize", 8 | "noselect", 9 | "rtcfps", 10 | "autoplaying", 11 | "kbps", 12 | "webrtc", 13 | "textbox", 14 | "unquantized", 15 | "denormalized", 16 | "gamepadconnected", 17 | "gamepaddisconnected", 18 | "webkitgamepadconnected", 19 | "webkitgamepaddisconnected", 20 | "UE's", 21 | "mozpointerlockchange", 22 | "backquote", 23 | "munge", 24 | "useinbandfec", 25 | "sprop", 26 | "maxcapturerate", 27 | "maxaveragebitrate", 28 | "peerconnection", 29 | "charcode", 30 | "numtouches", 31 | "ctrler", 32 | "mozfullscreenchange", 33 | "tooltiptext", 34 | "wifi", 35 | "bytelength", 36 | "datachannels", 37 | "DATACHANNELREQUEST", 38 | "SFURECVDATACHANNELREADY", 39 | "onmessagebinary" 40 | ], 41 | "flagWords": [], 42 | "ignorePaths": [ 43 | "package.json", 44 | "package-lock.json", 45 | "tsconfig.json", 46 | "node_modules/**" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /Frontend/ui-library/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '../../.lintstagedrc.mjs' 2 | 3 | export default { 4 | ...baseConfig, 5 | '*.ts': 'eslint --fix', 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Frontend/ui-library/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/ui-library/.npmignore -------------------------------------------------------------------------------- /Frontend/ui-library/.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Frontend/ui-library/.prettierignore -------------------------------------------------------------------------------- /Frontend/ui-library/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.6 2 | 3 | ## 1.2.0 4 | 5 | ### Minor Changes 6 | 7 | - 208d100: Add: a html modal for editing text input that is shown on the frontend when user clicks/taps on a streamed UE widget. 8 | 9 | This edit text modal fixes the following: 10 | 11 | - Fix: Users can now input non-latin characters (e.g. Chinese, Japanese, Korean etc.) using IME assistance. 12 | - Fix: Users on mobile can now type using on-device native on-screen keyboards (which was previously non-functioning). 13 | - Add: Users can copy/paste from their clipboard into the edit text modal naturally. 14 | 15 | When adding this modal the following was also fixed and extended: 16 | 17 | - Fix: Typing into other frontend widgets (e.g. the settings panel) no longer sends input to the focused UE widget. 18 | - Add: Exposed a frontend event for when UE sends text input content, meaning customisation of behaviour is now possible. 19 | - Docs: Added docs explaning this new edit text modal. 20 | 21 | Further details about the edit text modal as mentioned in this PR: https://github.com/EpicGamesExt/PixelStreamingInfrastructure/pull/564 22 | 23 | ### Patch Changes 24 | 25 | - Updated dependencies [208d100] 26 | - @epicgames-ps/lib-pixelstreamingfrontend-ue5.5@1.1.0 27 | 28 | ## 1.1.0 29 | 30 | ### Minor Changes 31 | 32 | - 8961c17: Frontend library is no longer a peer dependency but instead now a normal dependency. 33 | -------------------------------------------------------------------------------- /Frontend/ui-library/README.md: -------------------------------------------------------------------------------- 1 | ## lib-pixelstreamingfrontend-ui 2 | 3 | A plugin library that add UI support to the `lib-pixelstreamingfrontend` library. 4 | 5 | This UI library depends on a the base library as a peer dependency, so you should include both as dependencies in your application 6 | if you want to use this library. 7 | 8 | ### Key features 9 | - Stock Pixel Streaming frontend 10 | - Setting panel 11 | - Info panel 12 | 13 | ### Adding it to your project 14 | `npm i @epicgames-ps/lib-pixelstreamingfrontend-ue5.5` 15 | `npm i @epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.5` 16 | 17 | ### How this library is built 18 | The NPM packages supports: 19 | - ES6 module usage 20 | - CommonJS usage 21 | - Type definitions 22 | - Source maps 23 | 24 | **Note:** The NPM package does not contain a minified/bundled output, this is up to the user to do this in their application. -------------------------------------------------------------------------------- /Frontend/ui-library/src/Config/SettingUIBase.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { SettingBase } from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.6'; 4 | 5 | /** 6 | * Base class for a setting that has a text label, an arbitrary setting value it stores, an a HTML element that represents this setting. 7 | */ 8 | export class SettingUIBase { 9 | _setting: SettingBase; 10 | _rootElement: HTMLElement; 11 | 12 | constructor(setting: SettingBase) { 13 | this._setting = setting; 14 | } 15 | 16 | /** 17 | * @returns The setting component. 18 | */ 19 | public get setting(): SettingBase { 20 | return this._setting; 21 | } 22 | 23 | /** 24 | * @returns Return or creates a HTML element that represents this setting in the DOM. 25 | */ 26 | public get rootElement(): HTMLElement { 27 | if (!this._rootElement) { 28 | this._rootElement = document.createElement('div'); 29 | } 30 | return this._rootElement; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/Overlay/BaseOverlay.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | /** 4 | * Class for the base overlay structure 5 | */ 6 | export class OverlayBase { 7 | protected rootElement: HTMLElement; 8 | protected rootDiv: HTMLElement; 9 | public textElement: HTMLElement; 10 | 11 | /** 12 | * Construct an overlay 13 | * @param rootDiv - the root element this overlay will be inserted into 14 | * @param rootElement - the root element that is the overlay 15 | */ 16 | protected constructor(rootDiv: HTMLElement, rootElement: HTMLElement, textElement: HTMLElement) { 17 | this.rootDiv = rootDiv; 18 | this.rootElement = rootElement; 19 | this.textElement = textElement; 20 | this.rootElement.appendChild(this.textElement); 21 | this.hide(); 22 | this.rootDiv.appendChild(this.rootElement); 23 | } 24 | 25 | /** 26 | * Show the overlay 27 | */ 28 | public show(): void { 29 | this.rootElement.classList.remove('hiddenState'); 30 | } 31 | 32 | /** 33 | * Hide the overlay 34 | */ 35 | public hide(): void { 36 | this.rootElement.classList.add('hiddenState'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/Overlay/ConnectOverlay.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { ActionOverlay } from './ActionOverlay'; 4 | 5 | /** 6 | * Overlay shown during connection, has a button that can be clicked to initiate a connection. 7 | */ 8 | export class ConnectOverlay extends ActionOverlay { 9 | /** 10 | * @returns The created root element of this overlay. 11 | */ 12 | public static createRootElement(): HTMLElement { 13 | const connectElem = document.createElement('div'); 14 | connectElem.id = 'connectOverlay'; 15 | connectElem.className = 'clickableState'; 16 | return connectElem; 17 | } 18 | 19 | /** 20 | * @returns The created content element of this overlay, which contain whatever content this element contains, like text or a button. 21 | */ 22 | public static createContentElement(): HTMLElement { 23 | const connectContentElem = document.createElement('div'); 24 | connectContentElem.id = 'connectButton'; 25 | connectContentElem.innerHTML = 'Click to start'; 26 | return connectContentElem; 27 | } 28 | 29 | /** 30 | * Construct a connect overlay with a connection button. 31 | * @param parentElem - the parent element this overlay will be inserted into. 32 | */ 33 | public constructor(parentElem: HTMLElement) { 34 | super(parentElem, ConnectOverlay.createRootElement(), ConnectOverlay.createContentElement()); 35 | 36 | // add the new event listener 37 | this.rootElement.addEventListener('click', () => { 38 | this.activate(); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/Overlay/ErrorOverlay.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { TextOverlay } from './TextOverlay'; 4 | 5 | /** 6 | * Generic overlay used to show textual error info to the user. 7 | */ 8 | export class ErrorOverlay extends TextOverlay { 9 | /** 10 | * @returns The created root element of this overlay. 11 | */ 12 | public static createRootElement(): HTMLElement { 13 | const errorOverlayHtml = document.createElement('div'); 14 | errorOverlayHtml.id = 'errorOverlay'; 15 | errorOverlayHtml.className = 'textDisplayState'; 16 | return errorOverlayHtml; 17 | } 18 | 19 | /** 20 | * @returns The created content element of this overlay, which contain whatever content this element contains, like text or a button. 21 | */ 22 | public static createContentElement(): HTMLElement { 23 | const errorOverlayHtmlInner = document.createElement('div'); 24 | errorOverlayHtmlInner.id = 'errorOverlayInner'; 25 | return errorOverlayHtmlInner; 26 | } 27 | 28 | /** 29 | * Construct a connect overlay with a connection button. 30 | * @param parentElem - the parent element this overlay will be inserted into. 31 | */ 32 | public constructor(parentElem: HTMLElement) { 33 | super(parentElem, ErrorOverlay.createRootElement(), ErrorOverlay.createContentElement()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/Overlay/InfoOverlay.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { TextOverlay } from './TextOverlay'; 4 | 5 | /** 6 | * Generic overlay used to show textual info to the user. 7 | */ 8 | export class InfoOverlay extends TextOverlay { 9 | /** 10 | * @returns The created root element of this overlay. 11 | */ 12 | public static createRootElement(): HTMLElement { 13 | const infoOverlayHtml = document.createElement('div'); 14 | infoOverlayHtml.id = 'infoOverlay'; 15 | infoOverlayHtml.className = 'textDisplayState'; 16 | return infoOverlayHtml; 17 | } 18 | 19 | /** 20 | * @returns The created content element of this overlay, which contain whatever content this element contains, like text or a button. 21 | */ 22 | public static createContentElement(): HTMLElement { 23 | const infoOverlayHtmlInner = document.createElement('div'); 24 | infoOverlayHtmlInner.id = 'messageOverlayInner'; 25 | return infoOverlayHtmlInner; 26 | } 27 | 28 | /** 29 | * Construct a connect overlay with a connection button. 30 | * @param parentElem - the parent element this overlay will be inserted into. 31 | */ 32 | public constructor(parentElem: HTMLElement) { 33 | super(parentElem, InfoOverlay.createRootElement(), InfoOverlay.createContentElement()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/Overlay/TextOverlay.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import { OverlayBase } from './BaseOverlay'; 4 | 5 | /** 6 | * Class for the text overlay base 7 | */ 8 | export class TextOverlay extends OverlayBase { 9 | /** 10 | * Construct a text overlay 11 | * @param rootDiv - the root element this overlay will be inserted into 12 | * @param rootElement - the root element that is the overlay 13 | * @param textElement - an element that contains text for the action overlay 14 | */ 15 | public constructor(rootDiv: HTMLElement, rootElement: HTMLElement, textElement: HTMLElement) { 16 | super(rootDiv, rootElement, textElement); 17 | } 18 | 19 | /** 20 | * Update the text overlays inner text 21 | * @param text - the update text to be inserted into the overlay 22 | */ 23 | public update(text: string): void { 24 | if (text != null || text != undefined) { 25 | this.textElement.innerHTML = text; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/Util/MathUtils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | export class MathUtils { 4 | /** 5 | * formats Bytes coming in for video stats 6 | * @param bytes - number to convert 7 | * @param decimals - number of decimal places 8 | */ 9 | static formatBytes(bytes: number, decimals: number): string { 10 | if (bytes === 0) { 11 | return '0'; 12 | } 13 | 14 | const factor = 1024; 15 | const dm = decimals < 0 ? 0 : decimals; 16 | const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; 17 | 18 | const i = Math.floor(Math.log(bytes) / Math.log(factor)); 19 | 20 | return parseFloat((bytes / Math.pow(factor, i)).toFixed(dm)) + ' ' + sizes[i]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Frontend/ui-library/src/pixelstreamingfrontend-ui.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | export { Application, UIOptions, VideoQPIndicatorConfig } from './Application/Application'; 4 | 5 | export { PixelStreamingApplicationStyle } from './Styles/PixelStreamingApplicationStyles'; 6 | 7 | export { AFKOverlay } from './Overlay/AFKOverlay'; 8 | export { ActionOverlay } from './Overlay/ActionOverlay'; 9 | export { OverlayBase } from './Overlay/BaseOverlay'; 10 | export { ConnectOverlay } from './Overlay/ConnectOverlay'; 11 | export { DisconnectOverlay } from './Overlay/DisconnectOverlay'; 12 | export { ErrorOverlay } from './Overlay/ErrorOverlay'; 13 | export { InfoOverlay } from './Overlay/InfoOverlay'; 14 | export { PlayOverlay } from './Overlay/PlayOverlay'; 15 | export { TextOverlay } from './Overlay/TextOverlay'; 16 | export { ConfigUI } from './Config/ConfigUI'; 17 | export { SettingUIBase } from './Config/SettingUIBase'; 18 | export { SettingUIFlag } from './Config/SettingUIFlag'; 19 | export { SettingUINumber } from './Config/SettingUINumber'; 20 | export { SettingUIOption } from './Config/SettingUIOption'; 21 | export { SettingUIText } from './Config/SettingUIText'; 22 | export { PanelConfiguration, UIElementConfig, UIElementCreationMode } from './UI/UIConfigurationTypes'; 23 | -------------------------------------------------------------------------------- /Frontend/ui-library/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/cjs", 5 | "module": "node16", 6 | "moduleResolution": "node16" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/ui-library/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/esm", 5 | "module": "es6", 6 | "moduleResolution": "bundler" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Frontend/ui-library/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "noImplicitAny": true, 5 | "esModuleInterop": true, 6 | "target": "ES6", 7 | "sourceMap": true, 8 | "allowJs": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noImplicitOverride": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "noPropertyAccessFromIndexSignature": true, 14 | "declaration": true, 15 | "declarationDir": "./dist/types", 16 | "moduleResolution": "bundler" 17 | }, 18 | "lib": ["es2015"], 19 | "include": ["./src/*.ts"], 20 | "typedocOptions": { 21 | "exclude": "src/index.*", 22 | "entryPoints": ["src/pixelstreamingfrontend-ui.ts"], 23 | "sort": ["enum-value-ascending", "required-first", "source-order"], 24 | "out": "docs", 25 | "theme": "default", 26 | "hideGenerator": "true" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2004-2025, Epic Games, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Matchmaker/.gitignore: -------------------------------------------------------------------------------- 1 | html/custom/ 2 | certificates/ 3 | -------------------------------------------------------------------------------- /Matchmaker/README.md: -------------------------------------------------------------------------------- 1 | ### Where is matchmaker? 2 | The matchmaker has been removed. It was not a good refernce for how to handle Pixel Streaming at scale and was adding to maintenance work, so we made the decision to remove it and discontinue its support. 3 | 4 | ### What if I still need Matchmaker? 5 | You can still obtain it from older revisions of this repo. It is removed for UE5.5, but any previous version of the Infrastructure repo will still have it, latest one being [UE 5.4 matchmaker](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/tree/UE5.4/Matchmaker). 6 | -------------------------------------------------------------------------------- /NODE_VERSION: -------------------------------------------------------------------------------- 1 | v22.14.0 -------------------------------------------------------------------------------- /RELEASE_VERSION: -------------------------------------------------------------------------------- 1 | 0.1.0 2 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | These versions are currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 5.5 | :white_check_mark: | 10 | | 5.4 | :white_check_mark: | 11 | | 5.3 | :white_check_mark: | 12 | | 5.2 | :white_check_mark: | 13 | 14 | ## Reporting a Vulnerability 15 | 16 | If you find a vulnerability please open an advisory here: https://github.com/EpicGamesExt/PixelStreamingInfrastructure/security/advisories/new 17 | -------------------------------------------------------------------------------- /SFU/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /SFU/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/pixelstreaming-sfu 2 | 3 | ## 1.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 9627f8c: No longer using custom prebuilt mediasoup binaries and instead using the provided binaries from mediasoup. 8 | -------------------------------------------------------------------------------- /SFU/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the current Long Term Support (LTS) version of Node.js 2 | FROM node:lts 3 | 4 | COPY NODE_VERSION ./NODE_VERSION 5 | COPY /SFU /SFU 6 | 7 | RUN SFU/platform_scripts/bash/setup.sh 8 | 9 | ENV SIGNALLING_URL ws://localhost:8889 10 | 11 | EXPOSE 40000-49999/tcp 12 | EXPOSE 40000-49999/udp 13 | 14 | CMD node /SFU/sfu_server.js --signallingURL=${SIGNALLING_URL} 15 | -------------------------------------------------------------------------------- /SFU/Docs/images/Layer1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/SFU/Docs/images/Layer1.PNG -------------------------------------------------------------------------------- /SFU/Docs/images/Layer2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/SFU/Docs/images/Layer2.PNG -------------------------------------------------------------------------------- /SFU/Docs/images/Layer3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/SFU/Docs/images/Layer3.PNG -------------------------------------------------------------------------------- /SFU/Docs/images/SFUDiagram.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/SFU/Docs/images/SFUDiagram.PNG -------------------------------------------------------------------------------- /SFU/Docs/images/SFULayerBP.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/SFU/Docs/images/SFULayerBP.PNG -------------------------------------------------------------------------------- /SFU/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@epicgames-ps/pixelstreaming-sfu", 3 | "version": "1.1.0", 4 | "description": "Reference implementation for a PixelStreaming SFU", 5 | "private": true, 6 | "scripts": { 7 | "clean": "", 8 | "build": "", 9 | "start-local": "run-script-os --", 10 | "start-local:windows": ".\\platform_scripts\\cmd\\run.bat", 11 | "start-local:default": "./platform_scripts/bash/run_local.sh", 12 | "start-cloud": "run-script-os --", 13 | "start-cloud:windows": ".\\platform_scripts\\cmd\\run_cloud.bat", 14 | "start-cloud:default": "./platform_scripts/bash/run_cloud.sh", 15 | "start": "run-script-os", 16 | "start:windows": "platform_scripts\\cmd\\node\\node.exe sfu_server.js", 17 | "start:default": "if [ `id -u` -eq 0 ]\nthen\n export process=\"./platform_scripts/bash/node/bin/node sfu_server.js\"\nelse\n export process=\"sudo ./platform_scripts/bash/node/bin/node sfu_server.js\"\nfi\n$process " 18 | }, 19 | "dependencies": { 20 | "mediasoup": "^3.15.5", 21 | "@epicgames-ps/mediasoup-sdp-bridge": "^1.0.0", 22 | "minimist": "^1.2.8", 23 | "run-script-os": "^1.1.6", 24 | "ws": "^7.5.10" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SFU/platform_scripts/bash/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | FROM node:latest 4 | 5 | # Make sure Mediasoup requirements are met 6 | RUN apt -y update 7 | RUN apt -y install python3-pip 8 | 9 | # Copy the Selective Forwarding Unit (SFU) to the Docker build context 10 | COPY ../NODE_VERSION /opt/NODE_VERSION 11 | COPY . /opt/SFU 12 | 13 | # Install the dependencies for the mediasoup server 14 | WORKDIR /opt/SFU 15 | RUN npm update 16 | RUN npm install . 17 | 18 | # Expose TCP port 80 for player WebSocket connections and web server HTTP access 19 | EXPOSE 40000-49999 20 | 21 | # Expose TCP port 8888 for streamer WebSocket connections 22 | EXPOSE 8889 23 | 24 | # Set the signalling server as the container's entrypoint 25 | ENTRYPOINT ["/usr/local/bin/node", "/opt/SFU/sfu_server.js"] 26 | 27 | -------------------------------------------------------------------------------- /SFU/platform_scripts/bash/docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | # Build docker image for the Selective Forwarding Unit (SFU) 5 | 6 | # When run from SFU/platform_scripts/bash, this uses the SFU directory 7 | # as the build context so the SFU files can be successfully copied into the container image 8 | docker build -t 'mediasoup_sfu:latest' -f ./Dockerfile ../.. 9 | 10 | -------------------------------------------------------------------------------- /SFU/platform_scripts/bash/docker-start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | # Start docker container by name using host networking 5 | docker run --name sfu_latest --network host --rm mediasoup_sfu 6 | 7 | # Interactive start example 8 | #docker run --name sfu_latest --network host --rm -it --entrypoint /bin/bash mediasoup_sfu 9 | -------------------------------------------------------------------------------- /SFU/platform_scripts/bash/docker-stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | # Stop the docker container 5 | PSID=$(docker ps -a -q --filter="name=sfu_latest") 6 | if [ -z "$PSID" ]; then 7 | echo "Docker SFU is not running, no stopping will be done" 8 | exit 1; 9 | fi 10 | echo "Stopping Mediasoup SFU server ..." 11 | docker stop sfu_latest 12 | 13 | -------------------------------------------------------------------------------- /SFU/platform_scripts/bash/run_cloud.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | BASH_LOCATION="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 4 | 5 | pushd "${BASH_LOCATION}" > /dev/null 6 | 7 | source common_utils.sh 8 | 9 | set_start_default_values # No server specific defaults 10 | use_args "$@" 11 | call_setup_sh 12 | print_parameters 13 | 14 | process="${BASH_LOCATION}/node/lib/node_modules/npm/bin/npm-cli.js run start:default --" 15 | arguments="--PublicIP=${publicip}" 16 | 17 | # Add arguments passed to script to arguments for executable 18 | arguments+=" ${sfucmd}" 19 | 20 | pushd ../.. > /dev/null 21 | 22 | echo "Running: $process $arguments" 23 | PATH="${BASH_LOCATION}/node/bin:$PATH" 24 | start_process $process $arguments 25 | popd 26 | 27 | popd 28 | -------------------------------------------------------------------------------- /SFU/platform_scripts/bash/run_local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | BASH_LOCATION="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 4 | 5 | pushd "${BASH_LOCATION}" > /dev/null 6 | 7 | source common_utils.sh 8 | 9 | set_start_default_values # No server specific defaults 10 | use_args "$@" 11 | call_setup_sh 12 | 13 | process="${BASH_LOCATION}/node/lib/node_modules/npm/bin/npm-cli.js run start:default --" 14 | 15 | pushd ../.. > /dev/null 16 | 17 | echo "" 18 | echo "Starting (S)elective (F)orwarding (U)nit use ctrl-c to exit" 19 | echo "-----------------------------------------" 20 | echo "" 21 | 22 | PATH="${BASH_LOCATION}/node/bin:$PATH" 23 | start_process $process 24 | 25 | popd > /dev/null # ../.. 26 | 27 | popd > /dev/null # BASH_SOURCE -------------------------------------------------------------------------------- /SFU/platform_scripts/cmd/run_cloud.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | @echo off 4 | 5 | @Rem Set script directory as working directory. 6 | pushd "%~dp0" 7 | 8 | title SFU 9 | 10 | @Rem Get our public IP if we are running this SFU on the cloud we will need this. 11 | FOR /F "tokens=*" %%g IN ('curl -L -S -s https://api.ipify.org') do (SET PUBLICIP=%%g) 12 | 13 | @Rem Call out run.bat and pass in the Public IP we grabbed earlier. 14 | call run_local.bat --PublicIP=%PUBLICIP% 15 | 16 | @Rem Pop script directory. 17 | popd 18 | 19 | pause -------------------------------------------------------------------------------- /SFU/platform_scripts/cmd/run_local.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | @echo off 4 | 5 | @Rem Set script directory as working directory. 6 | pushd "%~dp0" 7 | 8 | title SFU 9 | 10 | @Rem Run setup to ensure we have node and mediasoup installed. 11 | call setup.bat 12 | 13 | @Rem Move to sfu_server.js directory. 14 | pushd ..\.. 15 | 16 | @Rem Run node server and pass any argument along. 17 | platform_scripts\cmd\node\node.exe sfu_server %* 18 | 19 | @Rem Pop sfu_server directory. 20 | popd 21 | 22 | @Rem Pop script directory. 23 | popd 24 | 25 | pause -------------------------------------------------------------------------------- /SFU/platform_scripts/cmd/setup.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | @echo off 4 | 5 | @Rem Set script location as working directory for commands. 6 | pushd "%~dp0" 7 | 8 | @Rem Ensure we have NodeJs available for calling. 9 | call setup_node.bat 10 | 11 | @Rem Move to sfu_server.js directory and install its package.json 12 | pushd %~dp0\..\..\ 13 | call platform_scripts\cmd\node\npm install --no-save 14 | popd 15 | 16 | @Rem Pop working directory 17 | popd -------------------------------------------------------------------------------- /SFU/platform_scripts/cmd/setup_node.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | @echo off 4 | 5 | @Rem Set script location as working directory for commands. 6 | pushd "%~dp0" 7 | 8 | @Rem Name and version of node that we are downloading 9 | set /p NodeVersion=<"../../../NODE_VERSION" 10 | SET NodeName=node-%NodeVersion%-win-x64 11 | 12 | @Rem Look for a node directory next to this script 13 | if exist node\ ( 14 | echo Node directory found...skipping install. 15 | ) else ( 16 | echo Node directory not found...beginning NodeJS download for Windows. 17 | 18 | @Rem Download nodejs and follow redirects. 19 | curl -L -o ./node.zip "https://nodejs.org/dist/%NodeVersion%/%NodeName%.zip" 20 | 21 | @Rem Unarchive the .zip 22 | tar -xf node.zip 23 | 24 | @Rem Rename the extracted, versioned, directory that contains the NodeJS binaries to simply "node". 25 | ren "%NodeName%\" "node" 26 | 27 | @Rem Delete the downloaded node.zip 28 | del node.zip 29 | ) 30 | 31 | @Rem Print node version 32 | echo Node version: & node\node.exe -v 33 | 34 | @Rem Pop working directory 35 | popd 36 | -------------------------------------------------------------------------------- /Signalling/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /Signalling/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '../.lintstagedrc.mjs' 2 | 3 | export default { 4 | ...baseConfig, 5 | '*.ts': 'eslint --fix', 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Signalling/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Signalling/.npmignore -------------------------------------------------------------------------------- /Signalling/.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/Signalling/.prettierignore -------------------------------------------------------------------------------- /Signalling/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/lib-pixelstreamingsignalling-ue5.6 2 | 3 | -------------------------------------------------------------------------------- /Signalling/README.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/lib-pixelstreamingsignalling 2 | 3 | A library for developers wanting to implement tools that signal Pixel Streaming applications. 4 | 5 | ## Building 6 | 7 | To build the `Signalling` module invoke the following commands in the `Common` and `Signalling` directories. 8 | 9 | ```bash 10 | npm install 11 | npm run build 12 | ``` 13 | 14 | This will result in a `/dist` output directory. 15 | 16 | **Note:** If you just want to get a signalling server up and running refer to ["Getting Started"](../README.md#getting-started) 17 | 18 | ### How this library is built 19 | The NPM packages supports: 20 | - ES6 module usage 21 | - CommonJS usage 22 | - Type definitions 23 | - Source maps 24 | 25 | ## Documentation 26 | 27 | - [Protocol Notes](../Common/docs/Protocol.md) 28 | - [Protocol Messages](../Common/docs/messages.md) 29 | 30 | The API documentation is [here](docs/) and covers details of all exported components of the library. 31 | 32 | -------------------------------------------------------------------------------- /Signalling/docs/Logger/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / Logger 6 | 7 | # Logger 8 | 9 | ## Interfaces 10 | 11 | - [IConfig](interfaces/IConfig.md) 12 | 13 | ## Variables 14 | 15 | - [Logger](variables/Logger.md) 16 | 17 | ## Functions 18 | 19 | - [InitLogging](functions/InitLogging.md) 20 | -------------------------------------------------------------------------------- /Signalling/docs/Logger/functions/InitLogging.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [Logger](../README.md) / InitLogging 6 | 7 | # Function: InitLogging() 8 | 9 | > **InitLogging**(`config`): `void` 10 | 11 | Defined in: [Signalling/src/Logger.ts:68](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L68) 12 | 13 | Call this as early as possible to setup the logging module with your 14 | preferred settings. 15 | 16 | ## Parameters 17 | 18 | ### config 19 | 20 | [`IConfig`](../interfaces/IConfig.md) 21 | 22 | The settings to init the logger with. See IConfig interface 23 | 24 | ## Returns 25 | 26 | `void` 27 | -------------------------------------------------------------------------------- /Signalling/docs/Logger/interfaces/IConfig.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [Logger](../README.md) / IConfig 6 | 7 | # Interface: IConfig 8 | 9 | Defined in: [Signalling/src/Logger.ts:20](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L20) 10 | 11 | ## Properties 12 | 13 | ### logDir? 14 | 15 | > `optional` **logDir**: `string` 16 | 17 | Defined in: [Signalling/src/Logger.ts:22](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L22) 18 | 19 | *** 20 | 21 | ### logLevelConsole? 22 | 23 | > `optional` **logLevelConsole**: `string` 24 | 25 | Defined in: [Signalling/src/Logger.ts:28](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L28) 26 | 27 | *** 28 | 29 | ### logLevelFile? 30 | 31 | > `optional` **logLevelFile**: `string` 32 | 33 | Defined in: [Signalling/src/Logger.ts:31](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L31) 34 | 35 | *** 36 | 37 | ### logMessagesToConsole? 38 | 39 | > `optional` **logMessagesToConsole**: `string` 40 | 41 | Defined in: [Signalling/src/Logger.ts:25](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L25) 42 | -------------------------------------------------------------------------------- /Signalling/docs/Logger/variables/Logger.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [Logger](../README.md) / Logger 6 | 7 | # Variable: Logger 8 | 9 | > **Logger**: `Logger` 10 | 11 | Defined in: [Signalling/src/Logger.ts:18](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Logger.ts#L18) 12 | 13 | The actual logger object. This is just a winston logger. 14 | You can use InitLogging to get a decent result, or you can 15 | completely create your own winston logger and assign it. 16 | -------------------------------------------------------------------------------- /Signalling/docs/LoggingUtils/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / LoggingUtils 6 | 7 | # LoggingUtils 8 | 9 | ## Interfaces 10 | 11 | - [IMessageLogger](interfaces/IMessageLogger.md) 12 | - [IProtoLogObj](interfaces/IProtoLogObj.md) 13 | 14 | ## Functions 15 | 16 | - [createHandlerListener](functions/createHandlerListener.md) 17 | - [logForward](functions/logForward.md) 18 | - [logIncoming](functions/logIncoming.md) 19 | - [logOutgoing](functions/logOutgoing.md) 20 | -------------------------------------------------------------------------------- /Signalling/docs/LoggingUtils/functions/createHandlerListener.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [LoggingUtils](../README.md) / createHandlerListener 6 | 7 | # Function: createHandlerListener() 8 | 9 | > **createHandlerListener**(`obj`, `handler`): (`message`) => `void` 10 | 11 | Defined in: [Signalling/src/LoggingUtils.ts:74](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/LoggingUtils.ts#L74) 12 | 13 | We don't want to log every incoming and outgoing messages. This is because some messages are simply 14 | forwarded to other connections. This results in duplicated spam. So we only want to log incoming 15 | messages that we handle internally, and any messages that we forward we only log once for the recv 16 | and send events. 17 | This creation method allows a simple way to enforce this. Any events we handle directly will 18 | be preceded by the logging call. 19 | 20 | ## Parameters 21 | 22 | ### obj 23 | 24 | [`IMessageLogger`](../interfaces/IMessageLogger.md) 25 | 26 | ### handler 27 | 28 | (`message`) => `void` 29 | 30 | ## Returns 31 | 32 | `Function` 33 | 34 | ### Parameters 35 | 36 | #### message 37 | 38 | `BaseMessage` 39 | 40 | ### Returns 41 | 42 | `void` 43 | -------------------------------------------------------------------------------- /Signalling/docs/LoggingUtils/functions/logForward.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [LoggingUtils](../README.md) / logForward 6 | 7 | # Function: logForward() 8 | 9 | > **logForward**(`recvr`, `target`, `message`): `void` 10 | 11 | Defined in: [Signalling/src/LoggingUtils.ts:56](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/LoggingUtils.ts#L56) 12 | 13 | Call this for messages being forwarded to this connection. That is messages received on 14 | one connection and being sent to another with only minor changes being made. 15 | 16 | ## Parameters 17 | 18 | ### recvr 19 | 20 | [`IMessageLogger`](../interfaces/IMessageLogger.md) 21 | 22 | The connection the message was received on. 23 | 24 | ### target 25 | 26 | [`IMessageLogger`](../interfaces/IMessageLogger.md) 27 | 28 | The connection the message is being sent to. 29 | 30 | ### message 31 | 32 | `BaseMessage` 33 | 34 | ## Returns 35 | 36 | `void` 37 | -------------------------------------------------------------------------------- /Signalling/docs/LoggingUtils/functions/logIncoming.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [LoggingUtils](../README.md) / logIncoming 6 | 7 | # Function: logIncoming() 8 | 9 | > **logIncoming**(`recvr`, `message`): `void` 10 | 11 | Defined in: [Signalling/src/LoggingUtils.ts:26](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/LoggingUtils.ts#L26) 12 | 13 | Call to log messages received on a connection that we will handle here at the server. 14 | Do not call this for messages being forwarded to another connection. 15 | 16 | ## Parameters 17 | 18 | ### recvr 19 | 20 | [`IMessageLogger`](../interfaces/IMessageLogger.md) 21 | 22 | IMessageLogger The connection the message was received on. 23 | 24 | ### message 25 | 26 | `BaseMessage` 27 | 28 | ## Returns 29 | 30 | `void` 31 | -------------------------------------------------------------------------------- /Signalling/docs/LoggingUtils/functions/logOutgoing.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [LoggingUtils](../README.md) / logOutgoing 6 | 7 | # Function: logOutgoing() 8 | 9 | > **logOutgoing**(`sender`, `message`): `void` 10 | 11 | Defined in: [Signalling/src/LoggingUtils.ts:41](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/LoggingUtils.ts#L41) 12 | 13 | Call to log messages created here at the server and being sent to the connection. 14 | Do not call this for messages being forwarded to this connection. 15 | 16 | ## Parameters 17 | 18 | ### sender 19 | 20 | [`IMessageLogger`](../interfaces/IMessageLogger.md) 21 | 22 | IMessageLogger The connection the message is being sent to. 23 | 24 | ### message 25 | 26 | `BaseMessage` 27 | 28 | ## Returns 29 | 30 | `void` 31 | -------------------------------------------------------------------------------- /Signalling/docs/LoggingUtils/interfaces/IMessageLogger.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [LoggingUtils](../README.md) / IMessageLogger 6 | 7 | # Interface: IMessageLogger 8 | 9 | Defined in: [Signalling/src/LoggingUtils.ts:17](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/LoggingUtils.ts#L17) 10 | 11 | Most methods in here rely on connections implementing this interface so we can identify 12 | who is sending or receiving etc. 13 | 14 | ## Extended by 15 | 16 | - [`IPlayer`](../../PlayerRegistry/interfaces/IPlayer.md) 17 | - [`IStreamer`](../../StreamerRegistry/interfaces/IStreamer.md) 18 | 19 | ## Methods 20 | 21 | ### getReadableIdentifier() 22 | 23 | > **getReadableIdentifier**(): `string` 24 | 25 | Defined in: [Signalling/src/LoggingUtils.ts:18](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/LoggingUtils.ts#L18) 26 | 27 | #### Returns 28 | 29 | `string` 30 | -------------------------------------------------------------------------------- /Signalling/docs/PlayerConnection/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / PlayerConnection 6 | 7 | # PlayerConnection 8 | 9 | ## Classes 10 | 11 | - [PlayerConnection](classes/PlayerConnection.md) 12 | -------------------------------------------------------------------------------- /Signalling/docs/PlayerRegistry/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / PlayerRegistry 6 | 7 | # PlayerRegistry 8 | 9 | ## Classes 10 | 11 | - [PlayerRegistry](classes/PlayerRegistry.md) 12 | 13 | ## Interfaces 14 | 15 | - [IPlayer](interfaces/IPlayer.md) 16 | - [IPlayerInfo](interfaces/IPlayerInfo.md) 17 | -------------------------------------------------------------------------------- /Signalling/docs/PlayerRegistry/interfaces/IPlayerInfo.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [PlayerRegistry](../README.md) / IPlayerInfo 6 | 7 | # Interface: IPlayerInfo 8 | 9 | Defined in: [Signalling/src/PlayerRegistry.ts:22](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/PlayerRegistry.ts#L22) 10 | 11 | Used by the API to describe the current state of the player. 12 | 13 | ## Properties 14 | 15 | ### playerId 16 | 17 | > **playerId**: `string` 18 | 19 | Defined in: [Signalling/src/PlayerRegistry.ts:23](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/PlayerRegistry.ts#L23) 20 | 21 | *** 22 | 23 | ### remoteAddress 24 | 25 | > **remoteAddress**: `undefined` \| `string` 26 | 27 | Defined in: [Signalling/src/PlayerRegistry.ts:26](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/PlayerRegistry.ts#L26) 28 | 29 | *** 30 | 31 | ### subscribedTo 32 | 33 | > **subscribedTo**: `undefined` \| `string` 34 | 35 | Defined in: [Signalling/src/PlayerRegistry.ts:25](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/PlayerRegistry.ts#L25) 36 | 37 | *** 38 | 39 | ### type 40 | 41 | > **type**: `string` 42 | 43 | Defined in: [Signalling/src/PlayerRegistry.ts:24](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/PlayerRegistry.ts#L24) 44 | -------------------------------------------------------------------------------- /Signalling/docs/README.md: -------------------------------------------------------------------------------- 1 | **@epicgames-ps/lib-pixelstreamingsignalling-ue5.5** 2 | 3 | *** 4 | 5 | # @epicgames-ps/lib-pixelstreamingsignalling-ue5.5 6 | 7 | ## Modules 8 | 9 | - [Logger](Logger/README.md) 10 | - [LoggingUtils](LoggingUtils/README.md) 11 | - [pixelstreamingsignalling](pixelstreamingsignalling/README.md) 12 | - [PlayerConnection](PlayerConnection/README.md) 13 | - [PlayerRegistry](PlayerRegistry/README.md) 14 | - [SFUConnection](SFUConnection/README.md) 15 | - [SignallingServer](SignallingServer/README.md) 16 | - [StreamerConnection](StreamerConnection/README.md) 17 | - [StreamerRegistry](StreamerRegistry/README.md) 18 | - [Utils](Utils/README.md) 19 | - [WebServer](WebServer/README.md) 20 | -------------------------------------------------------------------------------- /Signalling/docs/SFUConnection/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / SFUConnection 6 | 7 | # SFUConnection 8 | 9 | ## Classes 10 | 11 | - [SFUConnection](classes/SFUConnection.md) 12 | -------------------------------------------------------------------------------- /Signalling/docs/SignallingServer/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / SignallingServer 6 | 7 | # SignallingServer 8 | 9 | ## Classes 10 | 11 | - [SignallingServer](classes/SignallingServer.md) 12 | 13 | ## Interfaces 14 | 15 | - [IServerConfig](interfaces/IServerConfig.md) 16 | 17 | ## Type Aliases 18 | 19 | - [ProtocolConfig](type-aliases/ProtocolConfig.md) 20 | -------------------------------------------------------------------------------- /Signalling/docs/SignallingServer/type-aliases/ProtocolConfig.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [SignallingServer](../README.md) / ProtocolConfig 6 | 7 | # Type Alias: ProtocolConfig 8 | 9 | > **ProtocolConfig**: `object` 10 | 11 | Defined in: [Signalling/src/SignallingServer.ts:49](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/SignallingServer.ts#L49) 12 | 13 | ## Index Signature 14 | 15 | \[`key`: `string`\]: `any` 16 | -------------------------------------------------------------------------------- /Signalling/docs/StreamerConnection/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / StreamerConnection 6 | 7 | # StreamerConnection 8 | 9 | ## Classes 10 | 11 | - [StreamerConnection](classes/StreamerConnection.md) 12 | -------------------------------------------------------------------------------- /Signalling/docs/StreamerRegistry/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / StreamerRegistry 6 | 7 | # StreamerRegistry 8 | 9 | ## Classes 10 | 11 | - [StreamerRegistry](classes/StreamerRegistry.md) 12 | 13 | ## Interfaces 14 | 15 | - [IStreamer](interfaces/IStreamer.md) 16 | - [IStreamerInfo](interfaces/IStreamerInfo.md) 17 | -------------------------------------------------------------------------------- /Signalling/docs/Utils/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / Utils 6 | 7 | # Utils 8 | 9 | ## Functions 10 | 11 | - [beautify](functions/beautify.md) 12 | - [stringify](functions/stringify.md) 13 | -------------------------------------------------------------------------------- /Signalling/docs/Utils/functions/beautify.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [Utils](../README.md) / beautify 6 | 7 | # Function: beautify() 8 | 9 | > **beautify**(`obj`): `string` 10 | 11 | Defined in: [Signalling/src/Utils.ts:13](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Utils.ts#L13) 12 | 13 | Circular reference save version of JSON.stringify with extra formatting. 14 | 15 | ## Parameters 16 | 17 | ### obj 18 | 19 | `any` 20 | 21 | ## Returns 22 | 23 | `string` 24 | -------------------------------------------------------------------------------- /Signalling/docs/Utils/functions/stringify.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../../README.md) / [Utils](../README.md) / stringify 6 | 7 | # Function: stringify() 8 | 9 | > **stringify**(`obj`): `string` 10 | 11 | Defined in: [Signalling/src/Utils.ts:6](https://github.com/EpicGamesExt/PixelStreamingInfrastructure/blob/4dc9339cfc185a91d37d078aa9dd0951dfbae1a5/Signalling/src/Utils.ts#L6) 12 | 13 | Cirular reference safe version of JSON.stringify 14 | 15 | ## Parameters 16 | 17 | ### obj 18 | 19 | `any` 20 | 21 | ## Returns 22 | 23 | `string` 24 | -------------------------------------------------------------------------------- /Signalling/docs/WebServer/README.md: -------------------------------------------------------------------------------- 1 | [**@epicgames-ps/lib-pixelstreamingsignalling-ue5.5**](../README.md) 2 | 3 | *** 4 | 5 | [@epicgames-ps/lib-pixelstreamingsignalling-ue5.5](../README.md) / WebServer 6 | 7 | # WebServer 8 | 9 | ## Classes 10 | 11 | - [WebServer](classes/WebServer.md) 12 | 13 | ## Interfaces 14 | 15 | - [IWebServerConfig](interfaces/IWebServerConfig.md) 16 | -------------------------------------------------------------------------------- /Signalling/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import tseslint from 'typescript-eslint'; 4 | import tsdocPlugin from 'eslint-plugin-tsdoc'; 5 | import baseConfig from '../eslint.config.mjs' 6 | 7 | export default tseslint.config( 8 | baseConfig, 9 | { 10 | ignores: [], 11 | }, 12 | { 13 | languageOptions: { 14 | parser: tseslint.parser, 15 | parserOptions: { 16 | project: 'tsconfig.cjs.json', 17 | }, 18 | }, 19 | files: ["src/**/*.ts"], 20 | plugins: { 21 | 'tsdoc': tsdocPlugin, 22 | }, 23 | rules: { 24 | "tsdoc/syntax": "warn", 25 | "@typescript-eslint/require-array-sort-compare": "error", 26 | "no-unused-vars": "off", 27 | "@typescript-eslint/no-misused-promises": "off", // http.createServer(app) is throwing this 28 | "@typescript-eslint/no-unused-vars": [ 29 | "error", 30 | { 31 | "argsIgnorePattern": "^_", 32 | "varsIgnorePattern": "^_", 33 | "caughtErrorsIgnorePattern": "^_" 34 | } 35 | ] 36 | } 37 | } 38 | ); 39 | -------------------------------------------------------------------------------- /Signalling/src/Utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { jsonc } from 'jsonc'; 3 | 4 | /** 5 | * Cirular reference safe version of JSON.stringify 6 | */ 7 | export function stringify(obj: any): string { 8 | return jsonc.stringify(obj); 9 | } 10 | 11 | /** 12 | * Circular reference save version of JSON.stringify with extra formatting. 13 | */ 14 | export function beautify(obj: any): string { 15 | return jsonc.stringify(obj, undefined, '\t'); 16 | } 17 | -------------------------------------------------------------------------------- /Signalling/src/pixelstreamingsignalling.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | export * from './Logger'; 3 | export * from './LoggingUtils'; 4 | export * from './PlayerConnection'; 5 | export * from './PlayerRegistry'; 6 | export * from './SFUConnection'; 7 | export * from './SignallingServer'; 8 | export * from './StreamerConnection'; 9 | export * from './StreamerRegistry'; 10 | export * from './WebServer'; 11 | // keep Utils internal for now 12 | -------------------------------------------------------------------------------- /Signalling/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/cjs", 5 | "module": "node16", 6 | "moduleResolution": "node16" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Signalling/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/esm", 5 | "module": "es6", 6 | "moduleResolution": "bundler" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Signalling/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "esModuleInterop": true, 5 | "target": "ES6", 6 | "sourceMap": true, 7 | "allowJs": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noImplicitOverride": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "noPropertyAccessFromIndexSignature": true, 14 | "declaration": true, 15 | "declarationDir": "./dist/types", 16 | "moduleResolution": "bundler" // helps IDEs 17 | }, 18 | "include": ["./src/*.ts"], 19 | "typedocOptions": { 20 | "entryPoints": ["src/**/*.ts"], 21 | "out": "docs", 22 | "excludeExternals": true, 23 | "excludePrivate": true, 24 | "excludeInternal": true, 25 | "cleanOutputDir": false, 26 | "plugin": "typedoc-plugin-markdown", 27 | "readme": "none" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SignallingWebServer/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | node_modules/ 4 | www/ 5 | config.json 6 | ssl/ 7 | certs/ 8 | 9 | -------------------------------------------------------------------------------- /SignallingWebServer/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '../.lintstagedrc.mjs' 2 | 3 | export default { 4 | ...baseConfig, 5 | '*.ts': 'eslint --fix', 6 | } 7 | 8 | -------------------------------------------------------------------------------- /SignallingWebServer/.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/PixelStreamingInfrastructure/28e89962b90f69dfd9ac4bbbf703df8631e022c1/SignallingWebServer/.prettierignore -------------------------------------------------------------------------------- /SignallingWebServer/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @epicgames-ps/wilbur 2 | 3 | ## 2.2.0 4 | 5 | ### Minor Changes 6 | 7 | - cf8e737: Adds command line options to wilbur to allow for configuring the reverse proxy: 8 | 9 | --reverse-proxy Enables reverse proxy mode. This will 10 | trust the X-Forwarded-For header. 11 | (default: false) 12 | --reverse-proxy-num-proxies Sets the number of proxies to trust. 13 | This is used to calculate the real 14 | client IP address. (default: 1) 15 | -------------------------------------------------------------------------------- /SignallingWebServer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the current Long Term Support (LTS) version of Node.js 2 | FROM node:lts 3 | # Copy the signalling server and frontend source code from the build context 4 | WORKDIR /SignallingWebServer 5 | COPY NODE_VERSION ./NODE_VERSION 6 | COPY package.json ./package.json 7 | COPY package-lock.json ./package-lock.json 8 | COPY /Common ./Common 9 | COPY /Signalling ./Signalling 10 | COPY /SignallingWebServer ./SignallingWebServer 11 | COPY /Frontend ./Frontend 12 | # Install the dependencies for the signalling server and build the frontend 13 | RUN apt-get update 14 | RUN SignallingWebServer/platform_scripts/bash/setup.sh --build 15 | 16 | # Expose TCP ports 80 and 443 for player WebSocket connections and web server HTTP(S) access 17 | EXPOSE 80 18 | EXPOSE 443 19 | 20 | # Expose TCP port 8888 for streamer WebSocket connections 21 | EXPOSE 8888 22 | EXPOSE 8888/udp 23 | 24 | # Expose TCP port 8889 for connections from the SFU 25 | EXPOSE 8889 26 | 27 | # Expose TCP port 19302 for connections to Google's stun server 28 | EXPOSE 19302 29 | 30 | # Expose TCP port 19302 for connections from coturn 31 | EXPOSE 3478 32 | EXPOSE 3479 33 | 34 | # Set the signalling server as the container's entrypoint 35 | ENTRYPOINT ["bash", "SignallingWebServer/platform_scripts/bash/start.sh", "--nosudo"] 36 | -------------------------------------------------------------------------------- /SignallingWebServer/apidoc/api-definition-base.yml: -------------------------------------------------------------------------------- 1 | openapi: "3.1.0" 2 | info: 3 | title: "Pixel Streaming Signalling Server API" 4 | version: "1.0.0" 5 | servers: 6 | - url: "/api" 7 | paths: {} 8 | components: 9 | schemas: 10 | Streamer: 11 | type: object 12 | properties: 13 | streamerId: 14 | type: string 15 | description: The streamer's unique identifier 16 | streaming: 17 | type: boolean 18 | description: True if the streamer is accepting players 19 | required: 20 | - streamerId 21 | - streaming 22 | Player: 23 | type: object 24 | properties: 25 | playerId: 26 | type: string 27 | description: The player's unique identifier 28 | required: 29 | - playerId 30 | -------------------------------------------------------------------------------- /SignallingWebServer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "log_folder": "logs", 3 | "log_level_console": "info", 4 | "log_level_file": "info", 5 | "streamer_port": "8888", 6 | "player_port": "80", 7 | "sfu_port": "8889", 8 | "serve": true, 9 | "http_root": "D:\\PixelStreamingInfrastructure\\SignallingWebServer\\www", 10 | "homepage": "player.html", 11 | "https": false, 12 | "https_port": 443, 13 | "ssl_key_path": "certificates/client-key.pem", 14 | "ssl_cert_path": "certificates/client-cert.pem", 15 | "https_redirect": true, 16 | "rest_api": false, 17 | "reverse_proxy": false, 18 | "reverse_proxy_num_proxies": 1, 19 | "peer_options": "", 20 | "log_config": true, 21 | "stdin": false, 22 | "console_messages": "verbose" 23 | } 24 | -------------------------------------------------------------------------------- /SignallingWebServer/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import tseslint from 'typescript-eslint'; 4 | import tsdocPlugin from 'eslint-plugin-tsdoc'; 5 | import baseConfig from '../eslint.config.mjs' 6 | 7 | 8 | export default tseslint.config( 9 | baseConfig, 10 | { 11 | ignores: [], 12 | }, 13 | { 14 | languageOptions: { 15 | parser: tseslint.parser, 16 | parserOptions: { 17 | project: 'tsconfig.json', 18 | }, 19 | }, 20 | files: ["src/**/*.ts"], 21 | plugins: { 22 | 'tsdoc': tsdocPlugin 23 | }, 24 | rules: { 25 | "tsdoc/syntax": "warn", 26 | "@typescript-eslint/require-array-sort-compare": "error", 27 | "no-unused-vars": "off", 28 | "@typescript-eslint/no-unused-vars": [ 29 | "error", 30 | { 31 | "argsIgnorePattern": "^_", 32 | "varsIgnorePattern": "^_", 33 | "caughtErrorsIgnorePattern": "^_" 34 | } 35 | ] 36 | } 37 | } 38 | ); -------------------------------------------------------------------------------- /SignallingWebServer/from_cirrus.md: -------------------------------------------------------------------------------- 1 | # Cirrus to Wilbur Guide 2 | 3 | This is just a small brief to describe the differences between the now deprecated `cirrus` signalling server and the new `wilbur` signalling server. 4 | 5 | - Configuration is handled by CLI options or the same options in a `config.json` 6 | - By default web serving is disabled but can be enabled by supplying `--serve` 7 | - Convenience scripts in `platform_scripts` will append `--serve` and try to reproduce the old `cirrus.js` behaviour. 8 | - The frontend will be placed in `www` instead of `Public` when using convenience scripts. 9 | - Messages are now described by protobufs in the [Common](../Common/protobuf/signalling_messages.proto) library. 10 | - The server is built on top of the [Common](../Common) library which is provided as a tool for developers to build their own applications. 11 | - Logs from `wilbur` are now structured JSON so they can be easily ingested into external tools. 12 | - Messages sent and received are no longer echoed to the terminal by default. The `--console_messages` argument can control this behaviour. 13 | - The `config.json` file will not be created or recreated (if deleted), if you want the config.json to be generated based on current arguments use `--save`. 14 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/README.txt: -------------------------------------------------------------------------------- 1 | How to use files in this directory: 2 | 3 | - setup.sh : Ensures the correct node is installed and builds the frontend if it isn't already 4 | - start.sh : Starts the signalling server with basic settings 5 | - common.sh : Contains a bunch of helper functions for the contained scripts. Shouldn't be run directly. 6 | 7 | The following are provided as handy shortcuts but mostly leverage start.bat functionality 8 | - start_turn.sh : Starts the turn server only with basic settings 9 | - start_with_stun.sh : Starts the signalling server with basic STUN settings 10 | - start_with_turn.sh : Starts the TURN server and then the signalling server with STUN and TURN parameters 11 | 12 | Tips: 13 | 14 | - Please note that scripts intended to run need to be executable: $ chmod +x *.sh will do that job. 15 | - You can provide --help to start.sh to get a list of customizable arguments. 16 | - start_with_turn.sh has issues terminating with CTRL+C on Ubuntu 22.04 when run with the default port. Run start_with_stun.sh and start_turn.sh separately instead or set the player port above port 1024 and run with `SERVER_ARGS="player_port=8000" ./start_with_turn.sh --nosudo`. 17 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-build-wilbur.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | # 4 | cd -P -- "$(dirname -- "$0")" 5 | pushd "../../.." > /dev/null 6 | 7 | # When run from SignallingWebServer/platform_scripts/bash, this uses the SignallingWebServer 8 | # directory as the build context so the Cirrus files can be successfully copied into the 9 | # container image 10 | docker build --network=host -t "wilbur:latest" -f SignallingWebServer/Dockerfile . 11 | 12 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-start-turn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | SCRIPT_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 4 | 5 | # Get stun server data for passing to the container 6 | . ${SCRIPT_DIR}/common.sh 7 | 8 | parse_args $@ 9 | set_public_ip 10 | START_TURN=0 11 | setup_turn_stun 12 | 13 | # If we don't have a turnserver config in the signalling dir then just create one so that docker 14 | # will not create an empty folder when we try to mount the volume 15 | if [[ ! -f "${SCRIPT_DIR}/../../turnserver.conf" ]]; then 16 | touch "${SCRIPT_DIR}/../../turnserver.conf" 17 | fi 18 | 19 | # Start the TURN server 20 | #docker run --name coturn_latest --network host -it --entrypoint /bin/bash coturn/coturn 21 | #docker run --name coturn_latest --network host --rm -a stdin -a stdout -a stderr --entrypoint "sudo mkdir -p /var/run" coturn/coturn "" 22 | #docker run --name coturn_latest --network host --rm -a stdin -a stdout -a stderr --entrypoint "/bin/ls" coturn/coturn "/var/" 23 | 24 | docker run --name coturn_latest --network host --rm -a stdin -a stdout -a stderr -v "$PWD/turnserver.conf:${SCRIPT_DIR}/../../turnserver.conf" --entrypoint "turnserver" coturn/coturn "${TURN_ARGUMENTS}" 25 | 26 | #docker run --name coturn_latest --network host --rm -a stdin -a stdout -a stderr --entrypoint "/bin/bash" coturn/coturn "ls -latr /var/run/" 27 | #docker run --name coturn_latest --network host --rm -a stdin -a stdout -a stderr --entrypoint "sudo chown ubuntu:ubuntu /var/run/turnserver.pid | sudo chmod +x /var/run/turnserver.pid | ${process}" coturn/coturn "${arguments}" 28 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-start-wilbur-local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | docker run --name wilbur_latest --network host --rm wilbur 5 | 6 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-start-wilbur-with-turn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | docker run --name wilbur_latest --network host --rm wilbur 5 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-start-wilbur.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | SCRIPT_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 4 | 5 | # Get stun server data for passing to the container 6 | . ${SCRIPT_DIR}/common.sh 7 | 8 | parse_args $@ 9 | set_public_ip 10 | if [[ -z "${STUN_SERVER}" ]]; then 11 | DEFAULT_STUN=1 12 | fi 13 | START_TURN=0 14 | setup_turn_stun 15 | 16 | # Start docker container by name using host networking 17 | if [[ ! -z "${TURN_SERVER}" ]]; then 18 | PEER_OPTIONS="{\""iceServers\"":[{\""urls\"":[\""stun:"${STUN_SERVER}"\"",\""turn":"${TURN_SERVER}\""],\""username\"":\""${TURN_USER}\"",\""credential\"":\""${TURN_PASS}\""}]}" 19 | else 20 | PEER_OPTIONS="{\""iceServers\"":[{\""urls\"":[\""stun:"${STUN_SERVER}"\""]}]}" 21 | fi 22 | 23 | docker run --name wilbur_latest --network host --rm wilbur --peerConnectionOptions="${PEER_OPTIONS}" --publicIp="${PUBLIC_IP}" 24 | 25 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-stop-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | pushd "$(dirname ${BASH_SOURCE[0]})" 5 | ./docker-stop-wilbur.sh 6 | ./docker-stop-turn.sh 7 | popd 8 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-stop-turn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | # Stop the docker container 5 | PSID=$(docker ps -a -q --filter="name=coturn_latest") 6 | if [ -z "$PSID" ]; then 7 | echo "Docker turn is not running, no stopping will be done" 8 | exit 1; 9 | fi 10 | echo "Stopping turn server..." 11 | docker stop coturn_latest 12 | 13 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/docker-stop-wilbur.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | # Stop the docker container 5 | PSID=$(docker ps -a -q --filter="name=wilbur_latest") 6 | if [ -z "$PSID" ]; then 7 | echo "Docker wilbur is not running, no stopping will be done" 8 | exit 1; 9 | fi 10 | echo "Stopping wilbur server ..." 11 | docker stop wilbur_latest 12 | 13 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright Epic Games, Inc. All Rights Reserved. 4 | SCRIPT_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 5 | 6 | . "${SCRIPT_DIR}/common.sh" 7 | 8 | parse_args $@ 9 | setup $@ 10 | build_wilbur 11 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | SCRIPT_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 4 | 5 | . "${SCRIPT_DIR}/common.sh" 6 | 7 | parse_args $@ 8 | setup $@ 9 | set_public_ip 10 | setup_turn_stun "bg" 11 | 12 | TEST_ARGS=($SERVER_ARGS) 13 | SKIP_PEER_ARGS=false 14 | for arg in "${TEST_ARGS[@]}"; do 15 | if [[ "$arg" == --peer_options* ]]; then 16 | SKIP_PEER_ARGS=true 17 | break; 18 | fi 19 | done 20 | 21 | SERVER_ARGS+=" --serve --https_redirect --console_messages verbose --log_config --public_ip=${PUBLIC_IP}" 22 | if [[ $SKIP_PEER_ARGS == false ]]; then 23 | if [[ ! -z "$STUN_SERVER" && ! -z "$TURN_SERVER" ]]; then 24 | PEER_OPTIONS="{\"iceServers\":[{\"urls\":[\"stun:${STUN_SERVER}\",\"turn:${TURN_SERVER}\"],\"username\":\"${TURN_USER}\",\"credential\":\"${TURN_PASS}\"}]}" 25 | elif [[ ! -z "$STUN_SERVER" ]]; then 26 | PEER_OPTIONS="{\"iceServers\":[{\"urls\":[\"stun:${STUN_SERVER}\"]}]}" 27 | elif [[ ! -z "$TURN_SERVER" ]]; then 28 | PEER_OPTIONS="{\"iceServers\":[{\"urls\":[\"turn:${TURN_SERVER}\"],\"username\":\"${TURN_USER}\",\"credentials\":\"${TURN_PASS}\"}]}" 29 | fi 30 | fi 31 | if [[ ! -z "$PEER_OPTIONS" ]]; then 32 | SERVER_ARGS+=" --peer_options='${PEER_OPTIONS}'" 33 | fi 34 | if [[ ! -z "$FRONTEND_DIR" ]]; then 35 | SERVER_ARGS+=" --http_root='$FRONTEND_DIR'" 36 | fi 37 | 38 | build_wilbur 39 | print_config 40 | start_wilbur 41 | 42 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/start_turn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Epic Games, Inc. All Rights Reserved. 3 | 4 | SCRIPT_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 5 | 6 | . "${SCRIPT_DIR}/common.sh" 7 | parse_args $@ 8 | setup $@ 9 | set_public_ip 10 | DEFAULT_TURN=1 11 | START_TURN=1 12 | setup_turn_stun 13 | 14 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/start_with_stun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | . $(dirname "$0")/start.sh $* 3 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/bash/start_with_turn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . $(dirname "$0")/start.sh --start-turn $* 4 | 5 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/cmd/README.txt: -------------------------------------------------------------------------------- 1 | How to use files in this directory: 2 | 3 | - setup.bat : Ensures the correct node is installed and builds the frontend if it isn't already 4 | - start.bat : Starts the signalling server with basic settings 5 | - common.bat : Contains a bunch of helper functions for the contained scripts. Shouldn't be run directly. 6 | 7 | The following are provided as handy shortcuts but mostly leverage start.bat functionality 8 | - start_turn.bat : Starts the turn server only with basic settings 9 | - start_with_stun.bat : Starts the signalling server with basic STUN settings 10 | - start_with_turn.bat : Starts the TURN server and then the signalling server with STUN and TURN parameters 11 | 12 | Tips: 13 | 14 | - You can provide --help to start.bat to get a list of customizable arguments. 15 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/cmd/setup.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | @echo off 3 | setlocal enabledelayedexpansion 4 | 5 | call :Init 6 | call :ParseArgs %* 7 | 8 | IF "%CONTINUE%"=="1" ( 9 | call :Setup 10 | ) 11 | 12 | goto :eof 13 | 14 | :Init 15 | :ParseArgs 16 | :Setup 17 | :SetPublicIP 18 | :SetupTurnStun 19 | :PrintConfig 20 | :StartWilbur 21 | %~dp0common.bat %* 22 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/cmd/start_turn.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | @echo off 3 | setlocal enabledelayedexpansion 4 | 5 | title turnserver 6 | 7 | call :Init 8 | call :ParseArgs %* 9 | IF "%CONTINUE%"=="1" ( 10 | call :Setup 11 | call :SetPublicIP 12 | set DEFAULT_TURN=1 13 | set START_TURN=1 14 | call :SetupTurnStun 15 | ) 16 | 17 | goto :eof 18 | 19 | :Init 20 | :ParseArgs 21 | :Setup 22 | :SetPublicIP 23 | :SetupTurnStun 24 | :PrintConfig 25 | :StartWilbur 26 | "%~dp0common.bat" %* 27 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/cmd/start_with_stun.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | @echo off 3 | setlocal enabledelayedexpansion 4 | 5 | call "%~dp0start.bat" %* 6 | -------------------------------------------------------------------------------- /SignallingWebServer/platform_scripts/cmd/start_with_turn.bat: -------------------------------------------------------------------------------- 1 | @Rem Copyright Epic Games, Inc. All Rights Reserved. 2 | @echo off 3 | setlocal enabledelayedexpansion 4 | 5 | call "%~dp0start.bat" --start-turn %* 6 | -------------------------------------------------------------------------------- /SignallingWebServer/src/Utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { jsonc } from 'jsonc'; 3 | 4 | // A simple interface to describe the options from commander.js 5 | export type IProgramOptions = Record; 6 | 7 | /** 8 | * Cirular reference safe version of JSON.stringify 9 | */ 10 | export function stringify(obj: any): string { 11 | return jsonc.stringify(obj); 12 | } 13 | 14 | /** 15 | * Circular reference save version of JSON.stringify with extra formatting. 16 | */ 17 | export function beautify(obj: any): string { 18 | return jsonc.stringify(obj, undefined, '\t'); 19 | } 20 | -------------------------------------------------------------------------------- /SignallingWebServer/src/paths/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { SignallingServer } from '@epicgames-ps/lib-pixelstreamingsignalling-ue5.6'; 3 | 4 | /* eslint-disable @typescript-eslint/no-unsafe-call, 5 | @typescript-eslint/no-unsafe-member-access */ 6 | 7 | export default function (signallingServer: SignallingServer) { 8 | const operations = { 9 | GET 10 | }; 11 | 12 | function GET(req: any, res: any, _next: any) { 13 | res.status(200).json({ 14 | config: signallingServer.config, 15 | protocolConfig: signallingServer.protocolConfig 16 | }); 17 | } 18 | 19 | GET.apiDoc = { 20 | summary: 'Returns the current configuration of the server.', 21 | operationId: 'getConfig', 22 | responses: { 23 | 200: { 24 | description: 'The current configuration of the server.', 25 | content: { 26 | 'application/json': { 27 | schema: { 28 | type: 'object', 29 | properties: { 30 | config: { 31 | type: 'object' 32 | }, 33 | protocol: { 34 | type: 'object' 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | 44 | return operations; 45 | } 46 | -------------------------------------------------------------------------------- /SignallingWebServer/src/paths/players.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { SignallingServer } from '@epicgames-ps/lib-pixelstreamingsignalling-ue5.6'; 3 | 4 | /* eslint-disable @typescript-eslint/no-unsafe-call, 5 | @typescript-eslint/no-unsafe-member-access */ 6 | 7 | export default function (signallingServer: SignallingServer) { 8 | const operations = { 9 | GET 10 | }; 11 | 12 | function GET(req: any, res: any, _next: any) { 13 | res.status(200).json( 14 | signallingServer.playerRegistry.listPlayers().map((player) => player.getPlayerInfo()) 15 | ); 16 | } 17 | 18 | GET.apiDoc = { 19 | summary: 'Returns list of players', 20 | operationId: 'getPlayers', 21 | responses: { 22 | 200: { 23 | description: 'List of player IDs', 24 | content: { 25 | 'application/json': { 26 | schema: { 27 | type: 'array', 28 | items: { 29 | type: 'string' 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } 36 | }; 37 | 38 | return operations; 39 | } 40 | -------------------------------------------------------------------------------- /SignallingWebServer/src/paths/players/{playerId}.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { SignallingServer } from '@epicgames-ps/lib-pixelstreamingsignalling-ue5.6'; 3 | 4 | /* eslint-disable @typescript-eslint/no-unsafe-argument, 5 | @typescript-eslint/no-unsafe-call, 6 | @typescript-eslint/no-unsafe-member-access */ 7 | 8 | export default function (signallingServer: SignallingServer) { 9 | const operations = { 10 | GET 11 | }; 12 | 13 | function GET(req: any, res: any, _next: any) { 14 | const player = signallingServer.playerRegistry.get(req.params.playerId); 15 | if (!player) { 16 | throw new Error(`No player ID matches ${req.params.playerId}.`); 17 | } 18 | res.status(200).json(player.getPlayerInfo()); 19 | } 20 | 21 | GET.apiDoc = { 22 | summary: 'Returns a single player', 23 | operationId: 'getOnePlayer', 24 | parameters: [ 25 | { 26 | name: 'playerId', 27 | in: 'path', 28 | required: true, 29 | schema: { 30 | type: 'string' 31 | } 32 | } 33 | ], 34 | responses: { 35 | 200: { 36 | description: 'Player data', 37 | content: { 38 | 'application/json': { 39 | schema: { 40 | $ref: '#/components/schemas/Player' 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }; 47 | 48 | return operations; 49 | } 50 | -------------------------------------------------------------------------------- /SignallingWebServer/src/paths/streamers.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { SignallingServer } from '@epicgames-ps/lib-pixelstreamingsignalling-ue5.6'; 3 | 4 | /* eslint-disable @typescript-eslint/no-unsafe-call, 5 | @typescript-eslint/no-unsafe-member-access */ 6 | 7 | export default function (signallingServer: SignallingServer) { 8 | const operations = { 9 | GET 10 | }; 11 | 12 | function GET(req: any, res: any, _next: any) { 13 | res.status(200).json( 14 | signallingServer.streamerRegistry.streamers.map((streamer) => streamer.getStreamerInfo()) 15 | ); 16 | } 17 | 18 | GET.apiDoc = { 19 | summary: 'Returns list of streamers', 20 | operationId: 'getStreamers', 21 | responses: { 22 | 200: { 23 | description: 'List of streamers', 24 | content: { 25 | 'application/json': { 26 | schema: { 27 | type: 'array', 28 | items: { 29 | type: 'string' 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } 36 | }; 37 | 38 | return operations; 39 | } 40 | -------------------------------------------------------------------------------- /SignallingWebServer/src/paths/streamers/{streamerId}.ts: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | import { SignallingServer } from '@epicgames-ps/lib-pixelstreamingsignalling-ue5.6'; 3 | 4 | /* eslint-disable @typescript-eslint/no-unsafe-argument, 5 | @typescript-eslint/no-unsafe-call, 6 | @typescript-eslint/no-unsafe-member-access */ 7 | 8 | export default function (signallingServer: SignallingServer) { 9 | const operations = { 10 | GET 11 | }; 12 | 13 | function GET(req: any, res: any, _next: any) { 14 | const streamer = signallingServer.streamerRegistry.find(req.params.streamerId); 15 | if (!streamer) { 16 | throw new Error(`No streamer id matches ${req.params.streamerId}.`); 17 | } 18 | res.status(200).json(streamer.getStreamerInfo()); 19 | } 20 | 21 | GET.apiDoc = { 22 | summary: 'Returns a single streamer', 23 | operationId: 'getOneStreamer', 24 | parameters: [ 25 | { 26 | name: 'streamerId', 27 | in: 'path', 28 | required: true, 29 | schema: { 30 | type: 'string' 31 | } 32 | } 33 | ], 34 | responses: { 35 | 200: { 36 | description: 'Streamer data', 37 | content: { 38 | 'application/json': { 39 | schema: { 40 | $ref: '#/components/schemas/Streamer' 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }; 47 | 48 | return operations; 49 | } 50 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import eslint from '@eslint/js'; 4 | import prettierPluginRecommended from 'eslint-plugin-prettier/recommended'; 5 | import tseslint from 'typescript-eslint'; 6 | import checkCopyrightPlugin from './Extras/eslint/plugin-check-copyright/index.js' 7 | 8 | export default tseslint.config( 9 | eslint.configs.recommended, 10 | tseslint.configs.recommendedTypeCheckedOnly, 11 | prettierPluginRecommended, 12 | { 13 | plugins: { 14 | 'copyright': checkCopyrightPlugin 15 | }, 16 | rules: { 17 | "copyright/copyright": [ 18 | "error", 19 | { 20 | notice: "Copyright Epic Games, Inc. All Rights Reserved." 21 | } 22 | ] 23 | } 24 | } 25 | ); 26 | --------------------------------------------------------------------------------