article

AndresGenvid avatar image
AndresGenvid posted

03. Unreal C++ Web DataStreams Guide   

Unreal Web DataStreams Guide

This guide was written as a quick reference step by step guide for setting up a simple Unreal Web datastream. For more in depth information on each step please check the documentation at https://www.genvidtech.com/


Download Web Assets

  1. Download the folder containing the assets for this guide

Package the Project (UE5)

  1. Package the unreal project. Note the exe file location in your project folder. For instance: “\\Archives\\Windows\\ClockTime\\Binaries\\Win64\\ClockTime.exe” (or any other folder just adjust the template file below accordingly)

Package the Project (UE4)

  1. Package the unreal project. Note the exe file location in your project folder. For instance: “\\Archives\\WindowsNoEditor\\ClockTime\\Binaries\\Win64\\ClockTime.exe” (or any other folder just adjust the template file below accordingly)


Dealing with changes

  1. If anything changes in the project - it will have to be repackaged. However there is a workaround. If the project is played in editor the local bastion (detailed in putting it all together) will pick up the project currently in play.

Prepare the Unreal config files

  1. Navigate to your unreal project folder - then go up one

  2. In this folder create a “config” folder

    • This will hold all the unreal related config files needed by genvid

  3. In the new folder create a “game.hcl” file

  4. version = "1.7.0"
    
    job "ue4" {}
    
    log "ue4" {
          
      job      = "ue4"
      fileName = "ue4.log"
      logLevel = true
    }
    
    log "ue4_stderr" {
          
      job      = "ue4"
      fileName = "stderr"
      logLevel = true
    }
    
    log "ue4_stdout" {
          
      job      = "ue4"
      fileName = "stdout"
      logLevel = true
    }
    config {
          
      local {
          
        ue4 {
          
            appdir = "{
          {env `PROJECTDIR` | js}}\\App"
        }
      }
    }
    • Change the version and appdir. Change all references of ue4 to ue5 if needed.

    • Check the documentation for an in depth explanation.

      • The Genvid SDK also contains examples in the samples folder

    • This file tells the local genvid bastion where the unreal project is

  5. Create a “sample.hcl” file

  6. version = "1.7.0"
    
    
    settings {
          
      encode {
          
        input {
          
          width  = 1280
          height = 720
        }
        output {
          
          width  = 1280
          height = 720
        }
      }
      info {
          
        description = "Genvid SDK Unreal Clock Time Sample"
        game        = "ClockTime"
        name        = "clock time"
      }
    }
    • Change the description, game, and name to match your game

    • Check the documentation for an in depth explanation.

      • The Genvid SDK also contains examples in the samples folders

    • This file sets the window size and some misc information about the game

  7. Create an “events.json” file

    • This will be mostly empty as we do not have any events:

  8. {
         
    "version": "1.7.0",
     "event": {
          
     "game": {
          
     "maps": [
     ]
     }
     }
    }
    • Change the version to be your version

Prepare the Unreal template files

  1. In the directory above your Unreal project folder create the folders “templates/local”

    • This is why it was recommended to put your unreal project one extra folder deep

  2. Create a file named “ue4.nomad.tmpl” or “ue5.nomad.tmpl”

  3. job "ue4" {
         
      datacenters = [
        # {
          {range $i, $dc := datacenters}}
        "{
          {$dc}}",
        # {
          {end}}
      ]
    
      group "ue4" {
          
    
        network {
          
          port "sdkgui" {}
        }
    
        task "ue4" {
          
          driver = "raw_exec"
          config {
          
            command = "{
          {key `local/ue4/appdir` | js}}\\Archives\\WindowsNoEditor\\ClockTime\\Binaries\\Win64\\ClockTime.exe"
    
            args = [
              "-ResX={
          {- keyOrDefault `genvid/encode/input/width` `1280` -}}",
              "-ResY={
          {- keyOrDefault `genvid/encode/input/height` `720` -}}",
              "-Windowed",
              "-game",
              "-unattended",
              "-nosplash",
              "-nohomedir",
              "-forcelogflush",
              "-logtimes",
              "-ABSLOG=${NOMAD_ALLOC_DIR}/logs/ue4.log",
              "-nopause",
            ]
          }
    
          service {
          
            name = "sdkguiservice"
            port = "sdkgui"
          }
    
          env {
          
            GLOG_logtostderr     = "true"
            GOOGLE_LOGTOSTDERR   = "true"
            GENVID_LOGGER_PREFIX = "ue4"
            GLOG_minloglevel     = "0"
            GLOG_flushloglevel   = "-1"
            GLOG_logbufsecs      = "5"
          }
        }
      }
    }
  4. Change the end of the setting of the “command” value to point to your exe location. Change mentions of ue4 if needed

  5. check the documentation for an in depth explanation

  6. This tells the local genvid instance where the exe is located


Prepare the Unreal python file

  1. In the directory above your unreal project folder copy the downloaded asset named “app.py”

  2. We will use this python file later to load all the config and templates files.

    • You may need to install the genvid toolbox if not done already

      • You can install the genvid toolbox via the python file in the downloaded SDK files (py install-toolbox.py)

    • Check the documentation for an in depth explanation of what this script is doing. The function is named “load”

Prepare the web node_modules folder

  1. In the directory above your Unreal project create a folder called “web” and move into it

  2. Copy the downloaded asset named “package.json” here

    • Check the documentation for an in depth explanation of what this is doing

  3. Run the command “npm install” in powershell in the “web” folder

  4. A “node_modules” folder should be created

Prepare the web backend folder

  1. Create a “backend” folder in the “web” folder and move into the new folder

  2. Copy the following files: “www”, “streams.js”, “config.js”, “commands.js”, “auth.js”, “app.js”, “apiBase.js” from the downloaded assets here

    • See the documentation for a detailed description

Prepare the web config files

  1. Create a “config” folder in the “web” folder

  2. Create a “web.hcl” file

  3. version = "1.7.0"
    
    
    job "web" {}
    
    
    log "web" {
          
      job      = "web"
      task     = "web"
      fileName = "stdout"
    }
    
    log "weberr" {
          
      job      = "web"
      task     = "web"
      fileName = "stderr"
    }
    
    link "web" {
          
      name     = "Clock Time Sample"
      template = "http://${serviceEx `web` `` true}/"
    }
    link "admin" {
          
      name     = "Clock Time Admin"
      template = "http://${serviceEx `web` `` true}/admin"
    }
    
    // {
          {with $url := env `SSLWEBENDPOINT`}}
    link "web" {
          
      name     = "Clock Time Sample"
      template = "https://{
          {$url}}:30000"
    }
    link "admin" {
          
      template = "https://{
          {$url}}:30000/admin"
    }
    // {
          {end}}
    
    // Check if we are using a load balancer
    // {
          {with $url := env `WEBENDPOINT`}}
    link "web" {
          
      name     = "Clock Time Sample"
      template = "https://{
          {$url}}/"
    }
    link "admin" {
          
      name     = "Clock Time Admin"
      template = "https://{
          {$url}}/admin"
    }
    // {
          {end}}
    
    
    config {
          
      local {
          
        website {
          
          root   = "{
          {env `PROJECTDIR` | js}}"
          script = "{
          {env `PROJECTDIR` | js}}\\backend\\www"
        }
        binary {
          
          node {
          
            path = "{
          {plugin `where.exe` `node` | js}}"
          }
        }
      }
      embed_ssl {
          
        enabled = false
      }
    } // end of config
    • Change the various “name” variables to be your projects name

    • Change the version to be your version

    • Check the documentation for an in depth explanation.

      • The Genvid SDK also contains examples in the samples folders

    • This file informs the bastion instance where the various web related files are

  4. Create a “stream.hcl” file

  5. version = "1.7.0"
    
    
    secrets {
          
      disco {
          
        GENVID_DISCO_SECRET = "discosecret"
      }
      studio {
          
        GENVID_STUDIO_SECRET = "studiosecret"
      }
      webgateway {
          
        GENVID_WEBGATEWAY_SECRET = "webgatewaysecret"
      }
    }
    
    
    settings {
          
      encode {
          
        input {
          
          width  = 1280
          height = 720
        }
        output {
          
          width  = 1280
          height = 720
          framerate = 30
        }
      }
      info {
          
        description = "Sample to demonstrate genvid"
        game        = "ClockTime"
        name        = "Clock Time"
      }
    }
    config {
          
      local {
          
        appdir = "{
          {env `PROJECTDIR` | js}}\\ClockTime"
      }
    }
    • Change the appdir to be the folder your unreal project is in as well as the name, game, and description to be for your project

    • Change the version to be your version

    • Check the documentation for an in depth explanation.

      • The Genvid SDK also contains examples in the samples folders

    • This file informs the bastion instance of what streams to expect

  6. Create an “events.json” file

    • This will be mostly empty as we do not have any events:

  • {
         
    "version": "1.7.0",
      "event": {
          
        "game": {
          
          "maps": [
          ]
        }
      }
    }
    • Change the version to be your version


Prepare the web template files

  • Create “templates/local” folders in your “web” folder

  • Create a file named “web.nomad.tmpl”

  • job "web" {
         
      datacenters = [
        # {
          {range $i, $dc := datacenters}}
        "{
          {$dc}}",
        # {
          {end}}
      ]
    
      group "web" {
          
        network {
          
          port "web" {
          
            static = 30000
          }
        }
        task "web" {
          
          driver = "raw_exec"
          config {
          
            command = "{
          {key `local/binary/node/path` | js}}"
            args    = ["{
          {key `local/website/script` | js}}"]
          }
          vault {
          
            policies = ["genvid"]
          }
          env {
          
            GENVID_LIVESERVICE = "{
          {key `/genvid/encode/stream/service`}}"
            GENVID_LIVECHANNEL = "{
          {key `/genvid/encode/stream/channel`}}"
            # {
          {with secret `secret/disco` }}
            GENVID_DISCO_SECRET = "{
          { .Data.GENVID_DISCO_SECRET }}"
            # {
          {end}}
            # {
          {with secret `secret/studio` }}
            GENVID_STUDIO_SECRET = "{
          { .Data.GENVID_STUDIO_SECRET }}"
            # {
          {end}}
            # {
          {with secret `secret/webgateway` }}
            GENVID_WEBGATEWAY_SECRET = "{
          { .Data.GENVID_WEBGATEWAY_SECRET }}"
            # {
          {end}}
            # {
          {if keyExists `/twitch_extension/enabled`}}
            # {
          { if key `/twitch_extension/enabled` | parseBool }}
            # {
          {with secret `secret/twitch` }}
            TWITCH_EXT_CLIENT_SECRET = "{
          { .Data.TWITCH_EXT_CLIENT_SECRET }}"
            # {
          { end }}{
          { end }}{
          {end}}
            // {
          {if keyExists `/embed_ssl/enabled`}}
            // {
          { if key `/embed_ssl/enabled` | parseBool }}
            SSL = true
            // {
          { end }}{
          { end }}
            PORT = "${NOMAD_PORT_web}"
          }
    
          service {
          
            name = "web"
            tags = ["engage", "web"]
            port = "web"
    
    
            // {
          {if keyExists `/embed_ssl/enabled`}}
            // {
          { if key `/embed_ssl/enabled` | parseBool }}
            check {
          
              name            = "HTTPS Check"
              type            = "http"
              path            = "/health"
              protocol        = "https"
              tls_skip_verify = true
              interval        = "5s"
              timeout         = "2s"
            }
            // {
          { else }}
            check {
          
              name     = "HTTP Check"
              type     = "http"
              path     = "/health"
              interval = "5s"
              timeout  = "2s"
            }
            // {
          { end }}{
          { end }}
          }
        }
      }
    }
    • Check the documentation for an in depth explanation.

      • The Genvid SDK also contains examples in the samples folders

    • This file informs the bastion instance of various web related information


Prepare the web public folder

  1. Create a “public” folder in your “web folder” and move into the new folder

    • Copy the following files from the SDK into this folder

      • “Favicon.ico”, “genvid.umd”, “genvid-math.umd”, “lib/genvid.es5”, and “lib/genvid-math.es5”

        • Create a lib folder to put the two es5 files in

        • All the files minus the .ico file can be found in “<SDK root>\api\web\dist\”

        • The .ico file can be found in the root “logo_small.ico”. Copy and rename it

  2. Create the overlay files for the clock datastream in the public folder (a index.html, overlay.js, and style.css file)

  3. The html file will need to set up 3 divs to display the hour, minute, and second stream

  4. <!doctype html>
    <html>
    <head>
        <title>Genvid Overlay</title>
        <link rel="stylesheet" href="style.css">
        <script src="genvid.umd.js"></script>
        <script src="genvid-math.umd.js"></script>
        <script src="overlay.js"></script>
    </head>
    <body style="background:black">
        <div id="video_player"></div>
        <div id="overlay">
            <div class="child" id="hour"></div>
            <div class="child" id="minute"></div>
            <div class="child" id="second"></div>
        </div>    
    </body>
    </html>
  5. The js file will need to parse the stream and set the data in the divs

  6. var genvidClient;
    
    fetch("/api/public/channels/join", { method: "post" })
        .then(function (data) { return data.json() })
        .then(function (response) {
          
            genvidClient = genvid.createGenvidClient(response.info, response.uri, response.token, "video_player");
    
            genvidClient.onStreamsReceived(function (dataStreams) {
          
                for (let stream of [...dataStreams.streams, ...dataStreams.annotations]) {
          
                    for (let frame of stream.frames) {
          
                        try {
          
                            frame.user = JSON.parse(frame.data);
                        }
                        catch (e) {
          
                            console.log(e, frame.data);
                        }
                    }
                }
            });
            
            genvidClient.onVideoPlayerReady(function () {
          
                console.log("Video Player is Ready");
            });
    
            genvidClient.onDraw(function (frame) {
          
                let gameDataFrame = frame.streams["ClockTime"];
                if (gameDataFrame && gameDataFrame.user) {
          
                    update(gameDataFrame.user, genvidClient.videoAspectRatio);
                }
            });
            genvidClient.start();
        })
        .catch(function (e) { console.log(e) });
    
    function update(data, videoAspectRatio) {
          
        document.getElementById("hour").innerHTML = "Hour: " + Math.round(data.hour);
        document.getElementById("minute").innerHTML = "Minute: " + Math.round(data.minute);
        document.getElementById("second").innerHTML = "Second: " + Math.round(data.second);
    }
  7. The css file will need to set the styles for the various elements created above

  8. .label {
         
        position: absolute;
        left:1vw;
        bottom:1vw;
        opacity: 0.7;
        border-radius: 8px;
        padding: 12px;
        background-color:rgb(255, 200, 47);
    }
    
    #overlay {
          
        position: absolute;
        left:1vw;
        top:1vw;
        margin : 0 auto;
        padding : 5px;
        display : flex;
        justify-content : space-between;
        }
    
    .child {
          
        opacity: 0.7;
        border-radius: 8px;
        padding: 12px;
        margin: 12px;
        width:128px;
        background-color:rgb(255, 200, 47);
    }

Prepare the web python file

  1. In the “web” folder copy the downloaded assets “web.py” file

    • This python file will also eventually do what the previous one did but for the web config files. (calls set_config on the various config files)

    • See the documentation, or SDK samples for an example. The function is named “load”

Putting it all together

  1. Return to the folder above your unreal project

  2. Open a powershell instance here

  3. Run “genvid-bastion install --bastionid localbastion --loadconfig” to install bastion

  4. Run “genvid-sdk setup” to create the local cluster

  5. Run “genvid-sdk clean-config” to remove any previously loaded sample configurations

  6. Run “genvid-sdk load-config-sdk” to configure the basic services for the SDK

  7. Run “py app.py load” to load the configuration files created earlier for unreal

  8. Change directory to your “web folder”

  9. Run “py web.py load” to load the configuration files created earlier for web

  10. Run “genvid-sdk monitor”

  11. Hit “Start All” in the top right

  12. If you want to use the project as is in editor without having to package - stop the ue4/ue5 service. Then play in editor. The in editor version will automatically be picked up.

  13. Once everything is started click on the non admin or studio link to open the web view

  14. To stop run “genvid-sdk stop” and “genvid-bastion uninstall”

Example cluster

Example Stream with synced data and video


unreal engineunreal
10 |600

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

Article

Contributors

AndresGenvid contributed to this article