zesty.io

Product

Use Cases

Integrations

Learn

Video Embedding or Streaming Capabilities

Zesty.io can display video through 3rd party video services or self hosted videos uploaded to the media service.

Embedding Video from Youtube, Instagram and Vimeo

Standard embed codes provided by social media sites may be copy and pasted into a WYSIWYG Editor or directly into the content model HTML view file.

In youtube, click share, then click the embed option to get this view.Video Embed

Web Developers can take advantage of parsley by adding a field to a content model called "youtube_id" (for example), and can make dynamic template views by using code like this:

<iframe
  width="560"
  height="315"
  src="https://www.youtube.com/embed/{{ this.youtube_id }}"
  frameborder="0"
  allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
></iframe>

Streaming Video

For running your own stream, we suggest using a third party like Mux.com. A Mux stream can be put into any Zesty.io view, and a content model field and parsley can be used to give the Content Editor control of the stream id. In this example, we use the field name playback_id for the Mux stream ID

<video id="liveStream" autoplay controls height="900" width="1600"></video>
<!-- Use HLS.js to support the HLS format in browsers. -->
<script src="https://cdn.jsdelivr.net/npm/hls.js@0.8.2"></script>
<script>
  (function () {
    // Replace with your asset's playback ID
    var playbackId = "{{this.playback_id}}";
    var url = "https://stream.mux.com/" + playbackId + ".m3u8"; // HLS.js-specific setup code
    if (Hls.isSupported()) {
      var video = document.getElementById("liveStream");
      var hls = new Hls();
      hls.loadSource(url);
      hls.attachMedia(video);
    }
  })();
</script>

Video Conferencing

You can run your own video conferencing setup on Zesty.io using Vidyo (https://www.vidyo.com/), create an account. The setup requires view editing with javascript and an external server server call to issue a connection token.

View Code Example

<script>
  function makeid(length) {
    var result = "";
    var characters =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
  } // Add Vidyo Libray Callback
  function onVidyoClientLoaded(status) {
    switch (status.state) {
      case "READY": // Create Vidyoconnector
        VC.CreateVidyoConnector({
          viewId: null, //"renderer",
          viewStyle: "VIDYO_CONNECTORVIEWSTYLE_Default",
          remoteParticipants: 3,
          logFileFilter: "warning info@VidyoClient info@VidyoConnector",
          logFileName: "",
          userData: "",
        }).then(function (vidyoConnector) {
          //For acessing camera, microphone and speaker in chrome for latest vidyo library 4.1.24.15 register this device listener
          vidyoConnector
            .RegisterLocalCameraEventListener({
              onAdded: function (localCamera) {
                // New camera is available
              },
              onRemoved: function (localCamera) {
                // Existing camera became unavailable
              },
              onSelected: function (localCamera) {
                // Camera was selected/unselected by you or automatically
              },
              onStateUpdated: function (localCamera, state) {
                // Camera state was updated
              },
            })
            .then(function () {
              console.log("RegisterLocalCameraEventListener Success");
            })
            .catch(function () {
              console.error("RegisterLocalCameraEventListener Failed");
            }); // Handle appearance and disappearance of microphone devices in the system
          vidyoConnector
            .RegisterLocalMicrophoneEventListener({
              onAdded: function (localMicrophone) {
                // New microphone is available
              },
              onRemoved: function (localMicrophone) {
                // Existing microphone became unavailable
              },
              onSelected: function (localMicrophone) {
                // Microphone was selected/unselected by you or automatically
              },
              onStateUpdated: function (localMicrophone, state) {
                // Microphone state was updated
              },
            })
            .then(function () {
              console.log("RegisterLocalMicrophoneEventListener Success");
            })
            .catch(function () {
              console.error("RegisterLocalMicrophoneEventListener Failed");
            }); // Handle appearance and disappearance of speaker devices in the system
          vidyoConnector
            .RegisterLocalSpeakerEventListener({
              onAdded: function (localSpeaker) {
                // New speaker is available
              },
              onRemoved: function (localSpeaker) {
                // Existing speaker became unavailable
              },
              onSelected: function (localSpeaker) {
                // Speaker was selected/unselected by you or automatically
              },
              onStateUpdated: function (localSpeaker, state) {
                // Speaker state was updated
              },
            })
            .then(function () {
              console.log("RegisterLocalSpeakerEventListener Success");
            })
            .catch(function () {
              console.error("RegisterLocalSpeakerEventListener Failed");
            });
          let user = makeid(5);
          let tokenEndpoint =
            "https://XXXXX.cloudfunctions.net/vidyo-token-generator?userName=" +
            user;
          fetch(tokenEndpoint)
            .then((response) => {
              return response.json();
            })
            .then((data) => {
              var token = data.token;
              vidyoConnector
                .Connect({
                  host: "prod.vidyo.io",
                  token: token,
                  displayName: user,
                  resourceId: "testRoom", //Conference Name
                  onSuccess: function () {
                    console.log("Sucessfully connected");
                  },
                  onFailure: function (reason) {
                    console.log("Error while connecting ", reason);
                  },
                  onDisconnected: function (reason) {
                    console.log("Disconnected ", reason);
                  },
                })
                .then(function (status) {})
                .catch(function () {});
            });
        });
        break;
      case "RETRYING":
        console.log("Retrying");
        break;
      case "FAILED":
        console.log("Failed");
        break;
      case "FAILEDVERSION":
        console.log("Failed Version");
        break;
      case "NOTAVAILABLE":
        console.log("Not Available");
        break;
    }
    return true;
  }
</script>
<div
  id="renderer"
  style="
    position: absolute;
    top: 50px;
    left: 0px;
    bottom: 0px;
    z-index: 99;
    height: 100%;
    width: 100%;
  "
></div>
<script src="https://static.vidyo.io/latest/javascript/VidyoClient/VidyoClient.js?onload=onVidyoClientLoaded&webrtc=true&plugin=false"></script>

GCP Cloud Function that issues a Token

const cors = require("cors");
const { exportVidyoToken } = require("./exportVidyoToken");
const jsSHA = require("jssha");
const btoa = require("btoa");
const fs = require("fs");

exports.vidyoToken = (req, res) => {
  cors(req, res, () => {
    exportVidyoToken(req, res);
  });
};

const generateToken = (key, appID, userName, expiresInSeconds, vCard) => {
  const EPOCH_SECONDS = 62167219200;
  const expires =
    Math.floor(Date.now() / 1000) + expiresInSeconds + EPOCH_SECONDS;
  const shaObj = new jsSHA("SHA-384", "TEXT");
  shaObj.setHMACKey(key, "TEXT");
  const jid = userName + "@" + appID;
  const body = "provision" + "\x00" + jid + "\x00" + expires + "\x00" + vCard;
  shaObj.update(body);
  const mac = shaObj.getHMAC("HEX");
  const serialized = body + "\0" + mac;
  return btoa(serialized);
};

exports.exportVidyoToken = async (req, res) => {
  if (!req.hasOwnProperty("query") && !req.query.hasOwnProperty("userName")) {
    return res.status(400).send("Error: expected userName param.");
  }

  const userName = req.query.userName;
  const expiresInSeconds = 99999;
  const appID = process.env.APP_ID;
  const key = process.env.DEVELOPER_KEY;
  const vCard = "";
  const token = generateToken(key, appID, userName, expiresInSeconds, "");

  return res.status(200).json({
    token: token,
    user: userName,
  });
};

WebRTC Options

Here is a list of 3rd party service options for peer to peer streaming through a website or mobile app.

  1. Zoom - $100 for 4000 minutes ($0.025/minute)
    1. Pros - Large-scale, reliable company with solid, proven tech, robust API
    2. Cons - Expensive, lots of features, could potentially restrict content
  2. Vidyo - $3000 for 250,000 minutes ($0.012/minute)
    1. Pros - Simple html code to get started
    2. Cons - Company is focused on medical, large-scale accounts, weak support
  3. EasyRTC - Free if you host your own
    1. Pros - Do it yourself, more control, free
    2. Cons - Bare bones, no support
  4. Twilio Video - $0.0015/minute for peer-to-peer, $0.01/minutes for room features
    1. Pros - Great price for peer-to-peer only meaning you don’t get server-based room features
    2. Cons - Only 10 people per room max, no group room features like recording, messaging, etc
  5. AppRTC - Free, DIY
    1. Pros - The ultimate bare bones, google sample app for WebRTC
    2. Cons - Online demo had maybe 1- 1.5s delay, probably harder to implement
  6. Agora.io - $2.50 per/1,000 minutes ($0.0025/minute) for 720p
    1. Pros - No limit on rooms, inexpensive, lots of features such as broadcasting, solid codebase
    2. Cons - Website not as enticing as Twilio but not bad either

Start Here

We will listen to your needs and walk you through how Zesty can help your team.

Connect with Content Experts

Book a free 15-minute consultation with a content expert. Discuss your application, pain points and requirements. Understand how Zesty's lower total cost of ownership, features, functionality can elevate your business by creating extraordinary digital experiences.

Trusted By

zesty customer logo Sonyzesty customer logo Rocket Leaguezesty customer logo Singlifezesty customer logo Acornszesty customer logo Phoenix Sunszesty customer logo Wattpadzesty customer logo Corner Shopzesty customer logo Bjs

G2 MOMENTUM LEADER

zesty customer logo zesty customer logo zesty customer logo zesty customer logo

Enter your details to connect with a Content Expert

First Name

Last Name

Email

Phone (optional)

Company

Please tell us about your project (optional)