diff --git a/.github/workflows/container-images.yml b/.github/workflows/container-images.yml index d5d95b42..cca00ab4 100644 --- a/.github/workflows/container-images.yml +++ b/.github/workflows/container-images.yml @@ -31,3 +31,12 @@ jobs: tags: 'ghcr.io/epicgames/pixel-streaming-signalling-server:5.4' push: true file: SignallingWebServer/Dockerfile + - + name: Build and push the SFU container image + uses: docker/build-push-action@v3 + with: + context: . + tags: 'ghcr.io/epicgames/pixel-streaming-sfu:5.4' + push: true + file: SFU/Dockerfile + \ No newline at end of file diff --git a/README.md b/README.md index 2f3ec3e6..059df609 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ The following container images are built from this repository: - [ghcr.io/epicgames/pixel-streaming-signalling-server](https://github.com/orgs/EpicGames/packages/container/package/pixel-streaming-signalling-server) (since Unreal Engine 5.1) ( This link requires you to join Epic's Github org ) +- [ghcr.io/epicgames/pixel-streaming-sfu](https://github.com/orgs/EpicGames/packages/container/package/pixel-streaming-sfu) (since Unreal Engine 5.4) +( This link requires you to join Epic's Github org ) ### NPM Packages The following are `unofficial` NPM packages (official ones coming soon): diff --git a/SFU/Dockerfile b/SFU/Dockerfile new file mode 100644 index 00000000..a3bdf566 --- /dev/null +++ b/SFU/Dockerfile @@ -0,0 +1,13 @@ +# Use the current Long Term Support (LTS) version of Node.js +FROM node:lts + +COPY /SFU /SFU + +RUN SFU/platform_scripts/bash/setup.sh + +ENV SIGNALLING_URL ws://localhost:8889 + +EXPOSE 40000-49999/tcp +EXPOSE 40000-49999/udp + +CMD node /SFU/sfu_server.js --signallingURL=${SIGNALLING_URL} diff --git a/SFU/README.md b/SFU/README.md index 753384c4..e2300a51 100644 --- a/SFU/README.md +++ b/SFU/README.md @@ -57,3 +57,11 @@ Launch the streaming app with the following arguments This tells the Pixel Streaming plugin to stream simulcast with 3 streams, each one scaling video resolution by half. The sequence of values is as follows, `scale_down_factor,min_bitrate,max_bitrate,...repeating for each stream` When this streams to the SFU, the SFU will detect these 3 streams and then selectively stream these out to connected peers based on their connection quality. + +## Running the Docker image + +The Docker image needs to know where the signalling server to connect to is. You will need to set the `SIGNALLING_URL` environment variable to the URL for your signalling server. This URL needs to point to the configured SFU port (default 8889). +You will also need to use the `host` network driver on docker because of the way the SFU collects and reports its available ports. +An example for running might be as follows. + +```docker run -e SIGNALLING_URL=ws://192.168.1.10:8889 --network="host" ghcr.io/epicgames/pixel-streaming-sfu:5.4``` diff --git a/SFU/package-lock.json b/SFU/package-lock.json index 210a79d2..cf480ada 100644 --- a/SFU/package-lock.json +++ b/SFU/package-lock.json @@ -1,19 +1,35 @@ { - "name": "pixelstreaming-sfu", + "name": "@epicgames-ps/pixelstreaming-sfu", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "pixelstreaming-sfu", + "name": "@epicgames-ps/pixelstreaming-sfu", "version": "1.0.0", "dependencies": { "mediasoup_prebuilt": "^3.8.4", "mediasoup-sdp-bridge": "file:mediasoup-sdp-bridge", + "minimist": "^1.2.8", "run-script-os": "^1.1.6", "ws": "^7.1.2" } }, + "mediasoup-sdp-bridge": { + "name": "@epicgames-ps/mediasoup-sdp-bridge", + "version": "3.6.5", + "license": "ISC", + "dependencies": { + "mediasoup-client": "^3.6.41" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mediasoup" + } + }, "node_modules/@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -142,18 +158,15 @@ } }, "node_modules/mediasoup-sdp-bridge": { - "version": "3.6.5", - "resolved": "file:mediasoup-sdp-bridge", - "license": "ISC", - "dependencies": { - "mediasoup-client": "^3.6.41" - }, - "engines": { - "node": ">=10" - }, + "resolved": "mediasoup-sdp-bridge", + "link": true + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mediasoup" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/ms": { @@ -333,11 +346,16 @@ } }, "mediasoup-sdp-bridge": { - "version": "3.6.5", + "version": "file:mediasoup-sdp-bridge", "requires": { "mediasoup-client": "^3.6.41" } }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/SFU/package.json b/SFU/package.json index a918cf22..7a6d39e5 100644 --- a/SFU/package.json +++ b/SFU/package.json @@ -5,20 +5,20 @@ "private": true, "scripts": { "start-local": "run-script-os --", - "start-local:windows": ".\\platform_scripts\\cmd\\run.bat", - "start-local:default": "./platform_scripts/bash/run_local.sh", + "start-local:windows": ".\\platform_scripts\\cmd\\run.bat", + "start-local:default": "./platform_scripts/bash/run_local.sh", "start-cloud": "run-script-os --", - "start-cloud:windows": ".\\platform_scripts\\cmd\\run_cloud.bat", - "start-cloud:default": "./platform_scripts/bash/run_cloud.sh", + "start-cloud:windows": ".\\platform_scripts\\cmd\\run_cloud.bat", + "start-cloud:default": "./platform_scripts/bash/run_cloud.sh", "start": "run-script-os", - "start:windows": "platform_scripts\\cmd\\node\\node.exe sfu_server.js", - "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 " - + "start:windows": "platform_scripts\\cmd\\node\\node.exe sfu_server.js", + "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 " }, "dependencies": { - "mediasoup-sdp-bridge": "file:mediasoup-sdp-bridge", - "ws": "^7.1.2", "mediasoup_prebuilt": "^3.8.4", - "run-script-os": "^1.1.6" + "mediasoup-sdp-bridge": "file:mediasoup-sdp-bridge", + "minimist": "^1.2.8", + "run-script-os": "^1.1.6", + "ws": "^7.1.2" } } diff --git a/SFU/sfu_server.js b/SFU/sfu_server.js index cc26cfa2..462f4ca4 100644 --- a/SFU/sfu_server.js +++ b/SFU/sfu_server.js @@ -2,6 +2,7 @@ const config = require('./config'); const WebSocket = require('ws'); const mediasoup = require('mediasoup_prebuilt'); const mediasoupSdp = require('mediasoup-sdp-bridge'); +const minimist = require('minimist'); if (!config.retrySubscribeDelaySecs) { config.retrySubscribeDelaySecs = 10; @@ -351,6 +352,12 @@ async function createWebRtcTransport(identifier) { } async function main() { + var argv = minimist(process.argv.slice(2)); + + if ('signallingURL' in argv) { + config.signallingURL = argv['signallingURL']; + } + console.log('Starting Mediasoup...'); console.log("Config = "); console.log(config); diff --git a/SignallingWebServer/platform_scripts/bash/common_utils.sh b/SignallingWebServer/platform_scripts/bash/common_utils.sh index ab82a777..c8ccf361 100755 --- a/SignallingWebServer/platform_scripts/bash/common_utils.sh +++ b/SignallingWebServer/platform_scripts/bash/common_utils.sh @@ -75,7 +75,7 @@ function use_args() { } function call_setup_sh() { - bash "setup.sh" + bash "setup.sh" $* } function start_process() { diff --git a/SignallingWebServer/platform_scripts/bash/run_local.sh b/SignallingWebServer/platform_scripts/bash/run_local.sh index cfb80938..f60869e2 100755 --- a/SignallingWebServer/platform_scripts/bash/run_local.sh +++ b/SignallingWebServer/platform_scripts/bash/run_local.sh @@ -7,8 +7,8 @@ pushd "${BASH_LOCATION}" > /dev/null source common_utils.sh set_start_default_values "n" "n" # No server specific defaults -use_args "$@" -call_setup_sh +use_args "$*" +call_setup_sh $* print_parameters process="${BASH_LOCATION}/node/lib/node_modules/npm/bin/npm-cli.js run start:default --" @@ -33,4 +33,5 @@ start_process $process $arguments popd > /dev/null # ../.. -popd > /dev/null # BASH_SOURCE \ No newline at end of file +popd > /dev/null # BASH_SOURCE + diff --git a/SignallingWebServer/platform_scripts/bash/setup.sh b/SignallingWebServer/platform_scripts/bash/setup.sh index b0da33be..89418c6f 100755 --- a/SignallingWebServer/platform_scripts/bash/setup.sh +++ b/SignallingWebServer/platform_scripts/bash/setup.sh @@ -7,7 +7,7 @@ pushd "${BASH_LOCATION}" > /dev/null source common_utils.sh -use_args $@ +use_args $* # Azure specific fix to allow installing NodeJS from NodeSource if test -f "/etc/apt/sources.list.d/azure-cli.list"; then sudo touch /etc/apt/sources.list.d/nodesource.list