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.
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>
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/[email protected]"></script><script>(function(){// Replace with your asset's playback IDvar playbackId = "{{this.playback_id}}";var url = "https://stream.mux.com/"+playbackId+".m3u8";// HLS.js-specific setup codeif (Hls.isSupported()) {var video = document.getElementById("liveStream");var hls = new Hls();hls.loadSource(url);hls.attachMedia(video);}})();</script>
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 Callbackfunction onVidyoClientLoaded(status) {switch (status.state) {case "READY":// Create VidyoconnectorVC.CreateVidyoConnector({viewId: null, //"renderer",viewStyle: "VIDYO_CONNECTORVIEWSTYLE_Default",remoteParticipants: 3,logFileFilter: "warning [email protected] [email protected]",logFileName: "",userData: "",}).then(function (vidyoConnector) {//For acessing camera, microphone and speaker in chrome for latest vidyo library 4.1.24.15 register this device listenervidyoConnector.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 systemvidyoConnector.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 systemvidyoConnector.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 NameonSuccess: 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
exports.vidyoToken = (req, res) => {const cors = require("cors")();​cors(req, res, () => {exportVidyoToken(req, res);});};​const exportVidyoToken = async (req, res) => {if (!req.hasOwnProperty('query') && !req.query.hasOwnProperty('userName')) {return res.status(400).send("Error: expected userName param.");}​jsSHA = require('jssha');btoa = require('btoa');fs = require('fs');var tokenGenerated = false;function generateToken(key, appID, userName, expiresInSeconds, vCard) {var EPOCH_SECONDS = 62167219200;var expires = Math.floor(Date.now() / 1000) + expiresInSeconds + EPOCH_SECONDS;var shaObj = new jsSHA("SHA-384", "TEXT");shaObj.setHMACKey(key, "TEXT");jid = userName + '@' + appID;var body = 'provision' + '\x00' + jid + '\x00' + expires + '\x00' + vCard;shaObj.update(body);var mac = shaObj.getHMAC("HEX");var serialized = body + '\0' + mac;return btoa(serialized);}​let userName = req.query.userNamelet expiresInSeconds = 99999;let expiresAt = '';let appID = process.env.APP_IDlet key = process.env.DEVELOPER_KEYlet vCard = ''​let token = generateToken(key, appID, userName, expiresInSeconds, "");return res.status(200).json({'token': token,'user': userName});}​​​​
Here is a list of 3rd party service options for peer to peer streaming through a website or mobile app.
​Zoom - $100 for 4000 minutes ($0.025/minute)
Pros - Large-scale, reliable company with solid, proven tech, robust API
Cons - Expensive, lots of features, could potentially restrict content
​Vidyo - $3000 for 250,000 minutes ($0.012/minute)
Pros - Simple html code to get started
Cons - Company is focused on medical, large-scale accounts, weak support
​EasyRTC - Free if you host your own
Pros - Do it yourself, more control, free
Cons - Bare bones, no support
​Twilio Video - $0.0015/minute for peer-to-peer, $0.01/minutes for room features
Pros - Great price for peer-to-peer only meaning you don’t get server-based room features
Cons - Only 10 people per room max, no group room features like recording, messaging, etc
​AppRTC - Free, DIY
Pros - The ultimate bare bones, google sample app for WebRTC
Cons - Online demo had maybe 1- 1.5s delay, probably harder to implement
​Agora.io - $2.50 per/1,000 minutes ($0.0025/minute) for 720p
Pros - No limit on rooms, inexpensive, lots of features such as broadcasting, solid codebase
Cons - Website not as enticing as Twilio but not bad either