article

AndresGenvid avatar image
AndresGenvid posted

03. Unity Web DataStreams Guide   

Unity Web DataStreams Guide

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


Download the assets

  1. Download the folder containing the assets for this guide

  2. These assets will be referenced as “downloaded assets” when needed


Build the Unity Project

  1. Build the unity project in a folder called “Builds” (or any other folder just adjust the template file below accordingly)

Prepare the Unity config files

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

  2. In this folder create a “config” folder

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

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

  4. version = "1.7.0"
    
    job "unity" {
          
    }
    
    log "unity" {
          
      job      = "unity"
      fileName = "unity.log"
    }
    
    log "unityerr" {
          
      job      = "unity"
      fileName = "stderr"
      logLevel = true
    }
    
    config {
          
      local {
          
          unity {
          
            appdir = "{
          {env `PROJECTDIR` | js}}\\ClockTime"
        }
      }
    }
  5. Change the version and appdir

  6. Check the documentation for an in depth explanation.

    • The Genvid SDK also contains examples in the samples folder

  7. This file tells the local genvid bastion where the unity project is

  8. Create a “sample.hcl” file

  9. version = "1.7.0"
    
    
    settings {
          
      encode {
          
        input {
          
          width  = 1280
          height = 720
        }
        output {
          
          width  = 1280
          height = 720
        }
      }
      info {
          
        description = "Genvid SDK Unity Clock Time Sample"
        game        = "ClockTime"
        name        = "clock time"
      }
    }
  10. If using the example game.hcl file change the description, game, and name to match your game

  11. Change the version

  12. Check the documentation for an in depth explanation.

    • The Genvid SDK also contains examples in the samples folders

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

  14. Create an “events.json” file

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

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


Prepare the Unity template files

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

  2. Create a file named “unity.nomad.tmpl”

  3. job "unity" {
         
      datacenters = [
        # {
          {range $i, $dc := datacenters}}
        "{
          {$dc}}",
        # {
          {end}}
      ]
    
      group "unity" {
          
        network {
          
          port "sdkgui" {}
        }
    
        task "unity" {
          
          driver = "raw_exec"
          config {
          
            command = "{
          {key `local/unity/appdir` | js}}\\Builds\\ClockTime.exe"
    
            args = [
              "-force-d3d11",
              "-logFile",
              "${NOMAD_ALLOC_DIR}/logs/unity.log",
              "-screen-height",
              "{
          {- keyOrDefault `genvid/encode/input/height` `720` -}}",
              "-screen-width",
              "{
          {- keyOrDefault `genvid/encode/input/width` `1280` -}}",
            ]
          }
    
          service {
          
            name = "sdkguiservice"
            port = "sdkgui"
          }
    
          env {
          
            CONSUL_HTTP_ADDR     = "{
          { print (env `GENVID_DEFAULT_IP`) `:8500` }}"
            GLOG_logtostderr     = "1"
            GENVID_LOGGER_PREFIX = "unity"
          }
        }
      }
    }
  4. Change the end of the setting of the “command” value to point \\Builds\\<project name>.exe

  5. Check the documentation for an in depth explanation.

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


Prepare the Unity python file

  1. In the directory above your unity 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 a folder above your Unity 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 and move into the new 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
  4. Change the various “name” variables to be your projects name

  5. Change the version to be your version

  6. Check the documentation for an in depth explanation.

    • The Genvid SDK also contains examples in the samples folders

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

  8. Create a “stream.hcl” file

  9. 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"
      }
    }
  10. Change the appdir to be the folder your unity project is in as well as the name, game, and description to be for your project

  11. Change the version to be your version

  12. Check the documentation for an in depth explanation.

    1. The Genvid SDK also contains examples in the samples folders

  13. This file informs the bastion instance of what streams to expect

  14. Create an “events.json” file

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

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


Prepare the web template files

  1. Create “templates/local” folders in your “web” folder

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

  3. 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 }}
          }
        }
      }
    }
  4. Check the documentation for an in depth explanation.

    • The Genvid SDK also contains examples in the samples folders

  5. 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.js”, “genvid-math.umd.js”, “lib/genvid.es5.js”, and “lib/genvid-math.es5.js”

        • 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 unity 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 unity

  8. Change directory to your “web folder”

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

  10. Change directory back to the folder above your project folder

  11. Run “genvid-sdk monitor”

  12. Hit “Start All” in the top right

    • If you want to use the project as is in editor without having to package - stop the unity service. Pull up Unity then just 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”

1668016839147.pngExample cluster



1668017212329.pngStream with time overlay in sync



Unity
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