diff --git a/examples/bigmutebutton.html b/examples/bigmutebutton.html new file mode 100644 index 0000000..44b8e47 --- /dev/null +++ b/examples/bigmutebutton.html @@ -0,0 +1,121 @@ + +Twitch + Video + + + + + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/examples/obs_remote/index.html b/examples/obs_remote/index.html new file mode 100644 index 0000000..58c3d63 --- /dev/null +++ b/examples/obs_remote/index.html @@ -0,0 +1,401 @@ + + + + + OBS Controller Demo using VDO.Ninja + + + +
+

OBS remote (server)

+ + + + + +
+ + + + +
+ + +
+ +
+ Code available on GitHub: https://github.com/steveseguin/remote_ninja +
+ + + \ No newline at end of file diff --git a/examples/obs_remote/interface.html b/examples/obs_remote/interface.html new file mode 100644 index 0000000..7d37875 --- /dev/null +++ b/examples/obs_remote/interface.html @@ -0,0 +1,474 @@ + + + + + + + OBS Controller Demo using VDO.NInja + + +
+

OBS remote (client)

+
+
+

Scenes

+
+
+
+ +
+

Output

+
+ +
+
+
+

Active Sources

+
+
+
+
+

All Sources

+
+
+
+ + +
+

Custom Commands

+ +
+ A list of possible commands available here:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/examples/obs_remote/thirdparty/obs-websocket.min.js b/examples/obs_remote/thirdparty/obs-websocket.min.js new file mode 100644 index 0000000..7c390d8 --- /dev/null +++ b/examples/obs_remote/thirdparty/obs-websocket.min.js @@ -0,0 +1,10 @@ +/*! + * OBS WebSocket Javascript API (obs-websocket-js) v4.0.2 + * Author: Brendan Hagan (haganbmj) + * License: MIT + * Repository: https://github.com/haganbmj/obs-websocket-js + * Build Timestamp: 2020-09-24 01:45:11+00:00 + * Built from Commit: https://github.com/haganbmj/obs-websocket-js/commit/7a89c8ae9d02e9edaa0f878e0d93aa934e422cfe + */ +(function(e,t){'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports.OBSWebSocket=t():e.OBSWebSocket=t()})(window,function(){var t=Math.abs,n=Math.floor,o=Math.pow,e=Math.min;return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},t.r=function(e){'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(e,'__esModule',{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&'object'==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,'default',{enumerable:!0,value:e}),2&n&&'string'!=typeof e)for(var r in e)t.d(o,r,function(t){return e[t]}.bind(null,r));return o},t.n=function(e){var n=e&&e.__esModule?function(){return e['default']}:function(){return e};return t.d(n,'a',n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p='',t(t.s=0)}([function(e,t,n){function o(){return l++ +''}const r=n(1),s=n(14),i=n(15)('obs-websocket-js:Core');let l=0;e.exports=class extends r{send(e,t={}){return t=t||{},new Promise((n,r)=>{const l=o();let a;if(e||(a=s.REQUEST_TYPE_NOT_SPECIFIED),this._connected||(a=s.NOT_CONNECTED),this.once(`obs:internal:message:id-${l}`,(e,t)=>{e?(i('[send:reject] %o',e),r(e)):(i('[send:resolve] %o',t),n(t))}),!a){t['request-type']=e,t['message-id']=l,i('[send] %s %s %o',l,e,t);try{this._socket.send(JSON.stringify(t))}catch(e){a=s.SOCKET_EXCEPTION}}a&&this.emit(`obs:internal:message:id-${l}`,a)})}sendCallback(e,t={},n){n===void 0&&'function'==typeof t&&(n=t,t={}),this.send(e,t).then((...e)=>{n(null,...e)}).catch((e)=>{n(e)})}}},function(e,t,n){const o=n(2),r=n(4),s=n(5),i=n(14),l=n(15)('obs-websocket-js:Socket'),a=n(19),u=n(20);e.exports=class extends r{constructor(){super(),this._connected=!1,this._socket=void 0;const e=this.emit;this.emit=function(...t){l('[emit] %s err: %o data: %o',...t),e.apply(this,t)}}async connect(e={}){e=e||{};const t=e.address||'localhost:4444';if(this._socket)try{this._socket.close()}catch(e){l('Failed to close previous WebSocket:',e.message)}return new Promise(async(n,o)=>{try{await this._connect(t,!!e.secure),await this._authenticate(e.password),n()}catch(e){this._socket.close(),this._connected=!1,a(l,'Connection failed:',e),o(e)}})}async _connect(e,t){return new Promise((n,r)=>{let s=!1;l('Attempting to connect to: %s (secure: %s)',e,t),this._socket=new o((t?'wss://':'ws://')+e),this._socket.onerror=(e)=>{return s?(a(l,'Unknown Socket Error',e),void this.emit('error',e)):void(s=!0,a(l,'Websocket Connection failed:',e),r(i.CONNECTION_ERROR))},this._socket.onopen=()=>{s||(this._connected=!0,s=!0,l('Connection opened: %s',e),this.emit('ConnectionOpened'),n())},this._socket.onclose=()=>{this._connected=!1,l('Connection closed: %s',e),this.emit('ConnectionClosed')},this._socket.onmessage=(e)=>{l('[OnMessage]: %o',e);const t=u(JSON.parse(e.data));let n,o;'error'===t.status?n=t:o=t,t.messageId?this.emit(`obs:internal:message:id-${t.messageId}`,n,o):t.updateType?this.emit(t.updateType,o):(a(l,'Unrecognized Socket Message:',t),this.emit('message',t))}})}async _authenticate(e=''){if(!this._connected)throw i.NOT_CONNECTED;const t=await this.send('GetAuthRequired');if(!t.authRequired)return l('Authentication not Required'),this.emit('AuthenticationSuccess'),i.AUTH_NOT_REQUIRED;try{await this.send('Authenticate',{auth:s(t.salt,t.challenge,e)})}catch(t){throw l('Authentication Failure %o',t),this.emit('AuthenticationFailure'),t}l('Authentication Success'),this.emit('AuthenticationSuccess')}disconnect(){l('Disconnect requested.'),this._socket&&this._socket.close()}}},function(e,t,n){(function(t){var n=null;'undefined'==typeof WebSocket?'undefined'==typeof MozWebSocket?'undefined'==typeof t?'undefined'==typeof window?'undefined'!=typeof self&&(n=self.WebSocket||self.MozWebSocket):n=window.WebSocket||window.MozWebSocket:n=t.WebSocket||t.MozWebSocket:n=MozWebSocket:n=WebSocket,e.exports=n}).call(this,n(3))},function(e){var t=function(){return this}();try{t=t||new Function('return this')()}catch(n){'object'==typeof window&&(t=window)}e.exports=t},function(e){'use strict';function t(e){console&&console.warn&&console.warn(e)}function n(){n.init.call(this)}function o(e){return void 0===e._maxListeners?n.defaultMaxListeners:e._maxListeners}function r(e,n,r,s){var i,l,a;if('function'!=typeof r)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof r);if(l=e._events,void 0===l?(l=e._events=Object.create(null),e._eventsCount=0):(void 0!==l.newListener&&(e.emit('newListener',n,r.listener?r.listener:r),l=e._events),a=l[n]),void 0===a)a=l[n]=r,++e._eventsCount;else if('function'==typeof a?a=l[n]=s?[r,a]:[a,r]:s?a.unshift(r):a.push(r),i=o(e),0i&&!a.warned){a.warned=!0;var u=new Error('Possible EventEmitter memory leak detected. '+a.length+' '+(n+' listeners added. Use emitter.setMaxListeners() to increase limit'));u.name='MaxListenersExceededWarning',u.emitter=e,u.type=n,u.count=a.length,t(u)}return e}function s(){for(var e=[],t=0;te||h(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+'.');_=e}}),n.init=function(){(this._events===void 0||this._events===Object.getPrototypeOf(this)._events)&&(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},n.prototype.setMaxListeners=function(e){if('number'!=typeof e||0>e||h(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+'.');return this._maxListeners=e,this},n.prototype.getMaxListeners=function(){return o(this)},n.prototype.emit=function(e){for(var t=[],n=1;nr)return this;0===r?n.shift():p(n,r),1===n.length&&(o[e]=n[0]),void 0!==o.removeListener&&this.emit('removeListener',e,i||t)}return this},n.prototype.off=n.prototype.removeListener,n.prototype.removeAllListeners=function(e){var t,n,o;if(n=this._events,void 0===n)return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var r,s=Object.keys(n);for(o=0;o>>2|e<<30)^(e>>>13|e<<19)^(e>>>22|e<<10)}function l(e){return(e>>>6|e<<26)^(e>>>11|e<<21)^(e>>>25|e<<7)}function a(e){return(e>>>7|e<<25)^(e>>>18|e<<14)^e>>>3}function u(e){return(e>>>17|e<<15)^(e>>>19|e<<13)^e>>>10}var p=n(7),d=n(8),c=n(9).Buffer,_=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],f=Array(64);p(o,d),o.prototype.init=function(){return this._a=1779033703,this._b=3144134277,this._c=1013904242,this._d=2773480762,this._e=1359893119,this._f=2600822924,this._g=528734635,this._h=1541459225,this},o.prototype._update=function(t){for(var n=this._w,o=0|this._a,p=0|this._b,m=0|this._c,c=0|this._d,d=0|this._e,e=0|this._f,f=0|this._g,g=0|this._h,h=0;16>h;++h)n[h]=t.readInt32BE(4*h);for(;64>h;++h)n[h]=0|u(n[h-2])+n[h-7]+a(n[h-15])+n[h-16];for(var y=0;64>y;++y){var C=0|g+l(d)+r(d,e,f)+_[y]+n[y],b=0|i(o)+s(o,p,m);g=f,f=e,e=d,d=0|c+C,c=m,m=p,p=o,o=0|C+b}this._a=0|o+this._a,this._b=0|p+this._b,this._c=0|m+this._c,this._d=0|c+this._d,this._e=0|d+this._e,this._f=0|e+this._f,this._g=0|f+this._g,this._h=0|g+this._h},o.prototype._hash=function(){var e=c.allocUnsafe(32);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e.writeInt32BE(this._h,28),e},e.exports=o},function(e){e.exports='function'==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(t,n,o){function r(e,t){this._block=s.alloc(e),this._finalSize=t,this._blockSize=e,this._len=0}var s=o(9).Buffer;r.prototype.update=function(t,n){'string'==typeof t&&(n=n||'utf8',t=s.from(t,n));for(var o=this._block,r=this._blockSize,l=t.length,a=this._len,u=0;u=this._finalSize&&(this._update(this._block),this._block.fill(0));var n=8*this._len;if(4294967295>=n)this._block.writeUInt32BE(n,this._blockSize-4);else{var o=(4294967295&n)>>>0;this._block.writeUInt32BE((n-o)/4294967296,this._blockSize-8),this._block.writeUInt32BE(o,this._blockSize-4)}this._update(this._block);var r=this._hash();return e?r.toString(e):r},r.prototype._update=function(){throw new Error('_update must be implemented by subclass')},t.exports=r},function(e,t,n){function o(e,t){for(var n in e)t[n]=e[n]}function r(e,t,n){return i(e,t,n)}var s=n(10),i=s.Buffer;i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=s:(o(s,t),t.Buffer=r),o(i,r),r.from=function(e,t,n){if('number'==typeof e)throw new TypeError('Argument must not be a number');return i(e,t,n)},r.alloc=function(e,t,n){if('number'!=typeof e)throw new TypeError('Argument must be a number');var o=i(e);return void 0===t?o.fill(0):'string'==typeof n?o.fill(t,n):o.fill(t),o},r.allocUnsafe=function(e){if('number'!=typeof e)throw new TypeError('Argument must be a number');return i(e)},r.allocUnsafeSlow=function(e){if('number'!=typeof e)throw new TypeError('Argument must be a number');return s.SlowBuffer(e)}},function(t,r,s){'use strict';(function(t){function i(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function l(e,t){if(i()e)throw new RangeError('"size" argument must not be negative')}function d(e,t,n,o){return p(t),0>=t?l(e,t):void 0===n?l(e,t):'string'==typeof o?l(e,t).fill(n,o):l(e,t).fill(n)}function c(e,t){if(p(t),e=l(e,0>t?0:0|m(t)),!u.TYPED_ARRAY_SUPPORT)for(var n=0;nt.length?0:0|m(t.length);e=l(e,n);for(var o=0;on||t.byteLength=i())throw new RangeError('Attempt to allocate Buffer larger than maximum size: 0x'+i().toString(16)+' bytes');return 0|e}function y(e,t){if(u.isBuffer(e))return e.length;if('undefined'!=typeof ArrayBuffer&&'function'==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;'string'!=typeof e&&(e=''+e);var n=e.length;if(0===n)return 0;for(var o=!1;;)switch(t){case'ascii':case'latin1':case'binary':return n;case'utf8':case'utf-8':case void 0:return Q(e).length;case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return 2*n;case'hex':return n>>>1;case'base64':return H(e).length;default:if(o)return Q(e).length;t=(''+t).toLowerCase(),o=!0;}}function C(e,t,n){var o=!1;if((void 0===t||0>t)&&(t=0),t>this.length)return'';if((void 0===n||n>this.length)&&(n=this.length),0>=n)return'';if(n>>>=0,t>>>=0,n<=t)return'';for(e||(e='utf8');;)switch(e){case'hex':return x(this,t,n);case'utf8':case'utf-8':return k(this,t,n);case'ascii':return L(this,t,n);case'latin1':case'binary':return I(this,t,n);case'base64':return S(this,t,n);case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return O(this,t,n);default:if(o)throw new TypeError('Unknown encoding: '+e);e=(e+'').toLowerCase(),o=!0;}}function b(e,t,n){var o=e[t];e[t]=e[n],e[n]=o}function E(e,t,n,o,r){if(0===e.length)return-1;if('string'==typeof n?(o=n,n=0):2147483647n&&(n=-2147483648),n=+n,isNaN(n)&&(n=r?0:e.length-1),0>n&&(n=e.length+n),n>=e.length){if(r)return-1;n=e.length-1}else if(0>n)if(r)n=0;else return-1;if('string'==typeof t&&(t=u.from(t,o)),u.isBuffer(t))return 0===t.length?-1:A(e,t,n,o,r);if('number'==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&'function'==typeof Uint8Array.prototype.indexOf?r?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):A(e,[t],n,o,r);throw new TypeError('val must be string, number or Buffer')}function A(e,t,n,o,r){function s(e,t){return 1==l?e[t]:e.readUInt16BE(t*l)}var l=1,a=e.length,u=t.length;if(void 0!==o&&(o=(o+'').toLowerCase(),'ucs2'===o||'ucs-2'===o||'utf16le'===o||'utf-16le'===o)){if(2>e.length||2>t.length)return-1;l=2,a/=2,u/=2,n/=2}var p;if(r){var i=-1;for(p=n;pa&&(n=a-u),p=n;0<=p;p--){for(var d=!0,c=0;cr&&(o=r)):o=r;var s=t.length;if(0!=s%2)throw new TypeError('Invalid hex string');o>s/2&&(o=s/2);for(var l,a=0;ai&&(l=i):2==a?(u=t[s+1],128==(192&u)&&(c=(31&i)<<6|63&u,127c||57343c&&(l=c))):void 0}null===l?(l=65533,a=1):65535>>10),l=56320|1023&l),r.push(l),s+=a}return B(r)}function B(e){var t=e.length;if(t<=ne)return J.apply(String,e);for(var n='',o=0;ot)&&(t=0),(!n||0>n||n>o)&&(n=o);for(var r='',s=t;se)throw new RangeError('offset is not uint');if(e+t>n)throw new RangeError('Trying to access beyond buffer length')}function Y(e,t,n,o,r,s){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>r||te.length)throw new RangeError('Index out of range')}function D(t,n,o,r){0>n&&(n=65535+n+1);for(var s=0,i=e(t.length-o,2);s>>8*(r?s:1-s)}function N(t,n,o,r){0>n&&(n=4294967295+n+1);for(var s=0,i=e(t.length-o,4);s>>8*(r?s:3-s)}function z(e,t,n,o){if(n+o>e.length)throw new RangeError('Index out of range');if(0>n)throw new RangeError('Index out of range')}function j(e,t,n,o,r){return r||z(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),ee.write(e,t,n,o,23,4),n+4}function M(e,t,n,o,r){return r||z(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),ee.write(e,t,n,o,52,8),n+8}function W(e){if(e=q(e).replace(oe,''),2>e.length)return'';for(;0!=e.length%4;)e+='=';return e}function q(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,'')}function K(e){return 16>e?'0'+e.toString(16):e.toString(16)}function Q(e,t){t=t||Infinity;for(var n,o=e.length,r=null,s=[],l=0;ln){if(!r){if(56319n){-1<(t-=3)&&s.push(239,191,189),r=n;continue}n=(r-55296<<10|n-56320)+65536}else r&&-1<(t-=3)&&s.push(239,191,189);if(r=null,128>n){if(0>(t-=1))break;s.push(n)}else if(2048>n){if(0>(t-=2))break;s.push(192|n>>6,128|63&n)}else if(65536>n){if(0>(t-=3))break;s.push(224|n>>12,128|63&n>>6,128|63&n)}else if(1114112>n){if(0>(t-=4))break;s.push(240|n>>18,128|63&n>>12,128|63&n>>6,128|63&n)}else throw new Error('Invalid code point')}return s}function X(e){for(var t=[],n=0;n(t-=2));++l)n=e.charCodeAt(l),o=n>>8,r=n%256,s.push(r),s.push(o);return s}function H(e){return Z.toByteArray(W(e))}function G(e,t,n,o){for(var r=0;r=t.length||r>=e.length);++r)t[r+n]=e[r];return r}function $(e){return e!==e}var J=String.fromCharCode,Z=s(11),ee=s(12),te=s(13);r.Buffer=u,r.SlowBuffer=function(e){return+e!=e&&(e=0),u.alloc(+e)},r.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=t.TYPED_ARRAY_SUPPORT===void 0?function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&'function'==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(t){return!1}}():t.TYPED_ARRAY_SUPPORT,r.kMaxLength=i(),u.poolSize=8192,u._augment=function(e){return e.__proto__=u.prototype,e},u.from=function(e,t,n){return a(null,e,t,n)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,'undefined'!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(e,t,n){return d(null,e,t,n)},u.allocUnsafe=function(e){return c(null,e)},u.allocUnsafeSlow=function(e){return c(null,e)},u.isBuffer=function(e){return!!(null!=e&&e._isBuffer)},u.compare=function(t,n){if(!u.isBuffer(t)||!u.isBuffer(n))throw new TypeError('Arguments must be Buffers');if(t===n)return 0;for(var o=t.length,r=n.length,s=0,i=e(o,r);st&&(e+=' ... ')),''},u.prototype.compare=function(t,n,o,r,s){if(!u.isBuffer(t))throw new TypeError('Argument must be a Buffer');if(void 0===n&&(n=0),void 0===o&&(o=t?t.length:0),void 0===r&&(r=0),void 0===s&&(s=this.length),0>n||o>t.length||0>r||s>this.length)throw new RangeError('out of range index');if(r>=s&&n>=o)return 0;if(r>=s)return-1;if(n>=o)return 1;if(n>>>=0,o>>>=0,r>>>=0,s>>>=0,this===t)return 0;for(var l=s-r,a=o-n,p=e(l,a),d=this.slice(r,s),c=t.slice(n,o),f=0;fr)&&(n=r),0n||0>t)||t>this.length)throw new RangeError('Attempt to write outside buffer bounds');o||(o='utf8');for(var s=!1;;)switch(o){case'hex':return w(this,e,t,n);case'utf8':case'utf-8':return P(this,e,t,n);case'ascii':return F(this,e,t,n);case'latin1':case'binary':return R(this,e,t,n);case'base64':return v(this,e,t,n);case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return T(this,e,t,n);default:if(s)throw new TypeError('Unknown encoding: '+o);o=(''+o).toLowerCase(),s=!0;}},u.prototype.toJSON=function(){return{type:'Buffer',data:Array.prototype.slice.call(this._arr||this,0)}};var ne=4096;u.prototype.slice=function(e,t){var n=this.length;e=~~e,t=t===void 0?n:~~t,0>e?(e+=n,0>e&&(e=0)):e>n&&(e=n),0>t?(t+=n,0>t&&(t=0)):t>n&&(t=n),t=s&&(r-=o(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||U(e,t,this.length);for(var r=t,s=1,i=this[e+--r];0=s&&(i-=o(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||U(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||U(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||U(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||U(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||U(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||U(e,4,this.length),ee.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||U(e,4,this.length),ee.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||U(e,8,this.length),ee.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||U(e,8,this.length),ee.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t|=0,n|=0,!r){var s=o(2,8*n)-1;Y(this,e,t,n,s,0)}var l=1,a=0;for(this[t]=255&e;++a>>8):D(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):D(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):N(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var s=o(2,8*n-1);Y(this,e,t,n,s-1,-s)}var l=0,i=1,a=0;for(this[t]=255&e;++le&&0==a&&0!==this[t+l-1]&&(a=1),this[t+l]=255&(e/i>>0)-a;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var s=o(2,8*n-1);Y(this,e,t,n,s-1,-s)}var l=n-1,i=1,a=0;for(this[t+l]=255&e;0<=--l&&(i*=256);)0>e&&0==a&&0!==this[t+l+1]&&(a=1),this[t+l]=255&(e/i>>0)-a;return t+n},u.prototype.writeInt8=function(e,t,o){return e=+e,t|=0,o||Y(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=n(e)),0>e&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):D(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):D(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):N(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||Y(this,e,t,4,2147483647,-2147483648),0>e&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return j(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return j(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return M(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return M(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,o){if(n||(n=0),o||0===o||(o=this.length),t>=e.length&&(t=e.length),t||(t=0),0t)throw new RangeError('targetStart out of bounds');if(0>n||n>=this.length)throw new RangeError('sourceStart out of bounds');if(0>o)throw new RangeError('sourceEnd out of bounds');o>this.length&&(o=this.length),e.length-ts||!u.TYPED_ARRAY_SUPPORT)for(r=0;rr&&(e=r)}if(void 0!==o&&'string'!=typeof o)throw new TypeError('encoding must be a string');if('string'==typeof o&&!u.isEncoding(o))throw new TypeError('Unknown encoding: '+o)}else'number'==typeof e&&(e&=255);if(0>t||this.length>>=0,n=n===void 0?this.length:n>>>0,e||(e=0);var s;if('number'==typeof e)for(s=t;s>18]+l[63&e>>12]+l[63&e>>6]+l[63&e]}function s(e,t,n){for(var o,s=[],l=t;l>16,p[d++]=255&t>>8,p[d++]=255&t;return 2===l&&(t=a[e.charCodeAt(r)]<<2|a[e.charCodeAt(r+1)]>>4,p[d++]=255&t),1===l&&(t=a[e.charCodeAt(r)]<<10|a[e.charCodeAt(r+1)]<<4|a[e.charCodeAt(r+2)]>>2,p[d++]=255&t>>8,p[d++]=255&t),p},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,r=[],a=16383,u=0,i=n-o;ui?i:u+a));return 1==o?(t=e[n-1],r.push(l[t>>2]+l[63&t<<4]+'==')):2==o&&(t=(e[n-2]<<8)+e[n-1],r.push(l[t>>10]+l[63&t>>4]+l[63&t<<2]+'=')),r.join('')};for(var l=[],a=[],u='undefined'==typeof Uint8Array?Array:Uint8Array,p='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',d=0,i=p.length;d>1,g=-7,h=r?a-1:0,i=r?-1:1,d=t[n+h];for(h+=i,u=d&(1<<-g)-1,d>>=-g,g+=p;0>=-g,g+=l;0>1,C=23===p?5.960464477539063e-8-6.617444900424222e-24:0,b=u?0:f-1,i=u?1:-1,d=0>l||0===l&&0>1/l?1:0;for(l=t(l),isNaN(l)||l===Infinity?(h=isNaN(l)?1:0,g=m):(g=n(Math.log(l)/Math.LN2),1>l*(_=o(2,-g))&&(g--,_*=2),l+=1<=g+y?C/_:C*o(2,1-y),2<=l*_&&(g++,_/=2),g+y>=m?(h=0,g=m):1<=g+y?(h=(l*_-1)*o(2,p),g+=y):(h=l*o(2,y-1)*o(2,p),g=0));8<=p;r[a+b]=255&h,b+=i,h/=256,p-=8);for(g=g<{'%%'===e||(o++,'%c'===e&&(r=o))}),t.splice(r,0,n)},t.save=function(e){try{e?t.storage.setItem('debug',e):t.storage.removeItem('debug')}catch(e){}},t.load=function(){let e;try{e=t.storage.getItem('debug')}catch(e){}return!e&&'undefined'!=typeof o&&'env'in o&&(e=o.env.DEBUG),e},t.useColors=function(){return'undefined'!=typeof window&&window.process&&('renderer'===window.process.type||window.process.__nwjs)||('undefined'!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)?!1:'undefined'!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||'undefined'!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||'undefined'!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&31<=parseInt(RegExp.$1,10)||'undefined'!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))},t.storage=function(){try{return localStorage}catch(e){}}(),t.colors=['#0000CC','#0000FF','#0033CC','#0033FF','#0066CC','#0066FF','#0099CC','#0099FF','#00CC00','#00CC33','#00CC66','#00CC99','#00CCCC','#00CCFF','#3300CC','#3300FF','#3333CC','#3333FF','#3366CC','#3366FF','#3399CC','#3399FF','#33CC00','#33CC33','#33CC66','#33CC99','#33CCCC','#33CCFF','#6600CC','#6600FF','#6633CC','#6633FF','#66CC00','#66CC33','#9900CC','#9900FF','#9933CC','#9933FF','#99CC00','#99CC33','#CC0000','#CC0033','#CC0066','#CC0099','#CC00CC','#CC00FF','#CC3300','#CC3333','#CC3366','#CC3399','#CC33CC','#CC33FF','#CC6600','#CC6633','#CC9900','#CC9933','#CCCC00','#CCCC33','#FF0000','#FF0033','#FF0066','#FF0099','#FF00CC','#FF00FF','#FF3300','#FF3333','#FF3366','#FF3399','#FF33CC','#FF33FF','#FF6600','#FF6633','#FF9900','#FF9933','#FFCC00','#FFCC33'],e.exports=n(17)(t);const{formatters:r}=e.exports;r.j=function(e){try{return JSON.stringify(e)}catch(e){return'[UnexpectedJSONParseError]: '+e.message}}}).call(this,n(16))},function(e){function t(){throw new Error('setTimeout has not been defined')}function n(){throw new Error('clearTimeout has not been defined')}function o(e){if(u===setTimeout)return setTimeout(e,0);if((u===t||!u)&&setTimeout)return u=setTimeout,setTimeout(e,0);try{return u(e,0)}catch(t){try{return u.call(null,e,0)}catch(t){return u.call(this,e,0)}}}function r(e){if(p===clearTimeout)return clearTimeout(e);if((p===n||!p)&&clearTimeout)return p=clearTimeout,clearTimeout(e);try{return p(e)}catch(t){try{return p.call(null,e)}catch(t){return p.call(this,e)}}}function s(){g&&c&&(g=!1,c.length?f=c.concat(f):h=-1,f.length&&l())}function l(){if(!g){var e=o(s);g=!0;for(var t=f.length;t;){for(c=f,f=[];++h{if('%%'===t)return t;l++;const s=r.formatters[o];if('function'==typeof s){const o=e[l];t=s.call(n,o),e.splice(l,1),l--}return t}),r.formatArgs.call(n,e);const a=n.log||r.log;a.apply(n,e)}let o;return t.namespace=e,t.enabled=r.enabled(e),t.useColors=r.useColors(),t.color=n(e),t.destroy=s,t.extend=i,'function'==typeof r.init&&r.init(t),r.instances.push(t),t}function s(){const e=r.instances.indexOf(this);return-1!==e&&(r.instances.splice(e,1),!0)}function i(e,t){const n=r(this.namespace+('undefined'==typeof t?':':t)+e);return n.log=this.log,n}function l(e){return e.toString().substring(2,e.toString().length-2).replace(/\.\*\?$/,'*')}return r.debug=r,r.default=r,r.coerce=function(e){return e instanceof Error?e.stack||e.message:e},r.disable=function(){const e=[...r.names.map(l),...r.skips.map(l).map((e)=>'-'+e)].join(',');return r.enable(''),e},r.enable=function(e){r.save(e),r.names=[],r.skips=[];let t;const n=('string'==typeof e?e:'').split(/[\s,]+/),o=n.length;for(t=0;t{r[t]=e[t]}),r.instances=[],r.names=[],r.skips=[],r.formatters={},r.selectColor=n,r.enable(r.load()),r}},function(e){function n(e){if(e+='',!(100=p?l(e/p)+'d':n>=u?l(e/u)+'h':n>=s?l(e/s)+'m':n>=a?l(e/a)+'s':e+'ms'}function r(e){var n=t(e);return n>=p?i(e,n,p,'day'):n>=u?i(e,n,u,'hour'):n>=s?i(e,n,s,'minute'):n>=a?i(e,n,a,'second'):e+' ms'}function i(e,t,o,n){return l(e/o)+' '+n+(t>=1.5*o?'s':'')}var l=Math.round,a=1e3,s=60*a,u=60*s,p=24*u,d=7*p,c=365.25*p;e.exports=function(e,t){t=t||{};var s=typeof e;if('string'==s&&0{return t.toUpperCase()});e[n]=e[t]}return e}}])}); +//# sourceMappingURL=obs-websocket.min.js.map \ No newline at end of file diff --git a/examples/readme.md b/examples/readme.md new file mode 100644 index 0000000..e46702f --- /dev/null +++ b/examples/readme.md @@ -0,0 +1,23 @@ +p2p is a sample of how to use vdo.ninja as a data transport tunneling service + +twitch is an example of how to have a twitch live chat side-by-side with VDO.NInja on the same screen + +dual is an example of how to have two VDO.Ninja windows (or any windows really) open on the same page; Picture-in-Picture style + +sensors is an example of how to transmit sensor and video data from a phone to a computer, drawing it to canvas: youtube video for this exists + +midi demonstrates the MIDI API for VDO.Ninja + +draggable demonstrates how to drag multiple windows around, if you wanted to create a custom layout of elements. (experimental) + +chat.html is an example of a chat-only interface for VDO.NInja; maybe dockable into OBS even + +iframe.outbound-stats.html demostrates how to get stats from VDO.Ninja using the IFRAME API + +changepass lets you create passwords and related HASH values for VDO.NInja rooms + +webhid demonstrates how to interface with a USB device, like a streamdeck (mouse/keyboard not supported) + +zoom.html is a tool for letting you publish into VDO.Ninja, but then full-screen the window once setup, allowing for window-capturing into zoom. + +obs_remote is also hosted on github elsewhere, but it's an example of how to remotely control OBS using VDO.Ninja's tunneling abilities diff --git a/iframe.html b/iframe.html index 28df0bd..6b6b416 100644 --- a/iframe.html +++ b/iframe.html @@ -12,8 +12,8 @@ iframe { padding:0; display:block; margin:10px; - width:640px; - height:320px; + width:100%; + height:520px; } #viewlink { width:400px; @@ -77,312 +77,523 @@ function loadIframe(){ // this is pretty important if you want to avoid camera document.getElementById("container").appendChild(iframeContainer); - var button = document.createElement("button"); - button.innerHTML = "Mute Speaker"; - button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; // "speaker" also works in the same way. - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Un-Mute Speaker"; - button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Toggle Speaker"; - button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}; // open to a better suggestion here. - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Mute Mic"; - button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Un-Mute Mic"; - button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Toggle Mic"; - button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');}; - iframeContainer.appendChild(button); - - - var button = document.createElement("button"); - button.innerHTML = "Mute Camera"; - button.onclick = function(){iframe.contentWindow.postMessage({"camera":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Unmute Camera"; - button.onclick = function(){iframe.contentWindow.postMessage({"camera":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Toggle Camera"; - button.onclick = function(){iframe.contentWindow.postMessage({"camera":"toggle"}, '*');}; - iframeContainer.appendChild(button); - - - - var button = document.createElement("button"); - button.innerHTML = "Disconnect"; - button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Low Bitrate"; - button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "High Bitrate"; - button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Default Bitrate"; - button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Reload"; - button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "50% Volume"; - button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "100% Volume"; - button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Pan Left"; - button.title = "Requires &panning to be added to the view link"; - button.onclick = function(){iframe.contentWindow.postMessage({"panning":0}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Pan right"; - button.title = "Requires &panning to be added to the view link"; - button.onclick = function(){iframe.contentWindow.postMessage({"panning":180}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Pan Center"; - button.title = "Requires &panning to be added to the view link"; - button.onclick = function(){iframe.contentWindow.postMessage({"panning":90}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Request Loudness Levels"; - button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Stop Sending Loudness Levels"; - button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Start Recording"; - button.onclick = function(){iframe.contentWindow.postMessage({"record":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Stop Recording"; - button.onclick = function(){iframe.contentWindow.postMessage({"record":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Say Hello"; - button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Send Keyframe"; - button.onclick = function(){iframe.contentWindow.postMessage({"keyframe":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Insert Style Sheet"; - var stylesheet = "#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}"; - button.onclick = function(){iframe.contentWindow.postMessage({"style":stylesheet}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "get StreamIDs and labels"; - button.onclick = function(){iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Start AutoMixer"; - button.onclick = function(){iframe.contentWindow.postMessage({"automixer":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Stop AutoMixer"; - button.onclick = function(){iframe.contentWindow.postMessage({"automixer":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "ENABLE TALLY LIGHT"; - button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "STOP TALLY LIGHT"; - button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Add Target Video"; - button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "add":true, "settings":{"style":{"width":"640px", "height":"360px", "float":"left", "border":"10px solid red", "display":"block"}}}, '*');}; // target can be a stream ID or * for all. - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Remove Target Video"; - button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "remove": true}, '*');}; // target can be a stream ID or * for all. - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "previewWebcam()"; - button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; // publishScreen - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Change to Camera #2"; - button.onclick = function(){iframe.contentWindow.postMessage({"changeVideoDevice":2}, '*');}; // change text of add camera button - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Change to Microphone #4"; - button.onclick = function(){iframe.contentWindow.postMessage({"changeAudioDevice":4}, '*');}; // change text of add camera button - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "eval('alert(\"DANGERUS\")'"; - button.onclick = function(){iframe.contentWindow.postMessage({"function":"eval", "value":'alert(\"DANGERUS\")'}, '*');}; // publishScreen - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Change Add Camera text"; - button.onclick = function(){iframe.contentWindow.postMessage({"function":"changeHTML", "target":"add_camera", "value":"NEW CAMERA TEXT"}, '*');}; // change text of add camera button - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "CLOSE IFRAME"; - button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; - iframeContainer.appendChild(button); - - - - - - //////////// LISTEN FOR EVENTS + var h3 = document.createElement("h3"); + h3.innerText = "The following commands are exclusive to the IFRAME API."; + iframeContainer.appendChild(h3); - var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; - var eventer = window[eventMethod]; - var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; + var button = document.createElement("button"); + button.innerHTML = "Mute Speaker"; + button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; // "speaker" also works in the same way. + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Un-Mute Speaker"; + button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Toggle Speaker"; + button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}; // open to a better suggestion here. + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Mute Mic"; + button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Un-Mute Mic"; + button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Toggle Mic"; + button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Mute Camera"; + button.onclick = function(){iframe.contentWindow.postMessage({"camera":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Unmute Camera"; + button.onclick = function(){iframe.contentWindow.postMessage({"camera":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Toggle Camera"; + button.onclick = function(){iframe.contentWindow.postMessage({"camera":"toggle"}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Disconnect"; + button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Low Bitrate"; + button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "High Bitrate"; + button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Default Bitrate"; + button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Reload"; + button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "50% Volume"; + button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "100% Volume"; + button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Pan Left"; + button.title = "Requires &panning to be added to the view link"; + button.onclick = function(){iframe.contentWindow.postMessage({"panning":0}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Pan right"; + button.title = "Requires &panning to be added to the view link"; + button.onclick = function(){iframe.contentWindow.postMessage({"panning":180}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Pan Center"; + button.title = "Requires &panning to be added to the view link"; + button.onclick = function(){iframe.contentWindow.postMessage({"panning":90}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Request Loudness Levels"; + button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Stop Sending Loudness Levels"; + button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Start Recording"; + button.onclick = function(){iframe.contentWindow.postMessage({"record":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Stop Recording"; + button.onclick = function(){iframe.contentWindow.postMessage({"record":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Say Hello"; + button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Send Keyframe"; + button.onclick = function(){iframe.contentWindow.postMessage({"keyframe":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Insert Style Sheet"; + var stylesheet = "#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}"; + button.onclick = function(){iframe.contentWindow.postMessage({"style":stylesheet}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "get StreamIDs and labels"; + button.onclick = function(){iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Start AutoMixer"; + button.onclick = function(){iframe.contentWindow.postMessage({"automixer":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Stop AutoMixer"; + button.onclick = function(){iframe.contentWindow.postMessage({"automixer":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "ENABLE TALLY LIGHT"; + button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":true}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "STOP TALLY LIGHT"; + button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":false}, '*');}; + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Add Target Video"; + button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "add":true, "settings":{"style":{"width":"640px", "height":"360px", "float":"left", "border":"10px solid red", "display":"block"}}}, '*');}; // target can be a stream ID or * for all. + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Remove Target Video"; + button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "remove": true}, '*');}; // target can be a stream ID or * for all. + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "previewWebcam()"; + button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; // publishScreen + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Change to Camera #2"; + button.onclick = function(){iframe.contentWindow.postMessage({"changeVideoDevice":2}, '*');}; // change text of add camera button + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Change to Microphone #4"; + button.onclick = function(){iframe.contentWindow.postMessage({"changeAudioDevice":4}, '*');}; // change text of add camera button + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "eval('alert(\"DANGERUS\")'"; + button.onclick = function(){iframe.contentWindow.postMessage({"function":"eval", "value":'alert(\"DANGERUS\")'}, '*');}; // publishScreen + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Change Add Camera text"; + button.onclick = function(){iframe.contentWindow.postMessage({"function":"changeHTML", "target":"add_camera", "value":"NEW CAMERA TEXT"}, '*');}; // change text of add camera button + iframeContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "CLOSE IFRAME"; + button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; + iframeContainer.appendChild(button); + + //////////// LISTEN FOR EVENTS + + var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; + var eventer = window[eventMethod]; + var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; - /// If you have a routing system setup, you could have just one global listener for all iframes instead. + /// If you have a routing system setup, you could have just one global listener for all iframes instead. + + eventer(messageEvent, function (e) { + if (e.source != iframe.contentWindow){return} // reject messages send from other iframes - eventer(messageEvent, function (e) { - if (e.source != iframe.contentWindow){return} // reject messages send from other iframes + if ("stats" in e.data){ + var outputWindow = document.createElement("div"); + console.log(e.data.stats); - if ("stats" in e.data){ - var outputWindow = document.createElement("div"); - console.log(e.data.stats); - - - var out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; - out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; - - for (var streamID in e.data.stats.inbound_stats){ - out += "

streamID: "+streamID+"
"; - out += printValues(e.data.stats.inbound_stats[streamID]); - } - - outputWindow.innerHTML = out; - iframeContainer.appendChild(outputWindow); + + var out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; + out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; + + for (var streamID in e.data.stats.inbound_stats){ + out += "

streamID: "+streamID+"
"; + out += printValues(e.data.stats.inbound_stats[streamID]); } - if ("gotChat" in e.data){ + outputWindow.innerHTML = out; + iframeContainer.appendChild(outputWindow); + } + + if ("gotChat" in e.data){ + var outputWindow = document.createElement("div"); + outputWindow.innerHTML = e.data.gotChat.msg; + outputWindow.style.border="1px dotted black"; + iframeContainer.appendChild(outputWindow); + } + + if ("action" in e.data){ + var outputWindow = document.createElement("div"); + outputWindow.innerHTML = "child-page-action: "+e.data.action+"
"; + outputWindow.style.border="1px dotted black"; + iframeContainer.appendChild(outputWindow); + } + + + if ("streamIDs" in e.data){ + var outputWindow = document.createElement("div"); + outputWindow.innerHTML = "child-page-action: streamIDs
"; + for (var key in e.data.streamIDs) { + outputWindow.innerHTML += "streamID: " + key + ", label:"+e.data.streamIDs[key] + "\n"; + } + outputWindow.style.border="1px dotted black"; + iframeContainer.appendChild(outputWindow); + } + + if ("loudness" in e.data){ + console.log(e.data); + if (document.getElementById("loudness")){ + outputWindow = document.getElementById("loudness"); + } else { var outputWindow = document.createElement("div"); - outputWindow.innerHTML = e.data.gotChat.msg; outputWindow.style.border="1px dotted black"; iframeContainer.appendChild(outputWindow); + outputWindow.id = "loudness"; } + outputWindow.innerHTML = "child-page-action: loudness
"; + for (var key in e.data.loudness) { + outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; + } + outputWindow.style.border="1px black"; - if ("action" in e.data){ + } + + if ("sensors" in e.data){ + console.log(e.data); + if (document.getElementById("sensors")){ + outputWindow = document.getElementById("sensors"); + } else { var outputWindow = document.createElement("div"); - outputWindow.innerHTML = "child-page-action: "+e.data.action+"
"; outputWindow.style.border="1px dotted black"; iframeContainer.appendChild(outputWindow); + outputWindow.id = "sensors"; } - - - if ("streamIDs" in e.data){ - var outputWindow = document.createElement("div"); - outputWindow.innerHTML = "child-page-action: streamIDs
"; - for (var key in e.data.streamIDs) { - outputWindow.innerHTML += "streamID: " + key + ", label:"+e.data.streamIDs[key] + "\n"; - } - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - } - - if ("loudness" in e.data){ - console.log(e.data); - if (document.getElementById("loudness")){ - outputWindow = document.getElementById("loudness"); - } else { - var outputWindow = document.createElement("div"); - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - outputWindow.id = "loudness"; - } - outputWindow.innerHTML = "child-page-action: loudness
"; - for (var key in e.data.loudness) { - outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; - } - outputWindow.style.border="1px black"; + outputWindow.innerHTML = "child-page-action: sensors

"; + for (var key in e.data.sensors.lin) { + outputWindow.innerHTML += key + " linear: " + e.data.sensors.lin[key] + "
"; } + for (var key in e.data.sensors.acc) { + outputWindow.innerHTML += key + " acceleration: " + e.data.sensors.acc[key] + "
"; + } + for (var key in e.data.sensors.gyro) { + outputWindow.innerHTML += key + " gyro: " + e.data.sensors.gyro[key] + "
"; + } + for (var key in e.data.sensors.mag) { + outputWindow.innerHTML += key + " magnet: " + e.data.sensors.mag[key] + "
"; + } + outputWindow.style.border="1px black"; - if ("sensors" in e.data){ - console.log(e.data); - if (document.getElementById("sensors")){ - outputWindow = document.getElementById("sensors"); - } else { - var outputWindow = document.createElement("div"); - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - outputWindow.id = "sensors"; - } - outputWindow.innerHTML = "child-page-action: sensors

"; - - for (var key in e.data.sensors.lin) { - outputWindow.innerHTML += key + " linear: " + e.data.sensors.lin[key] + "
"; - } - for (var key in e.data.sensors.acc) { - outputWindow.innerHTML += key + " acceleration: " + e.data.sensors.acc[key] + "
"; - } - for (var key in e.data.sensors.gyro) { - outputWindow.innerHTML += key + " gyro: " + e.data.sensors.gyro[key] + "
"; - } - for (var key in e.data.sensors.mag) { - outputWindow.innerHTML += key + " magnet: " + e.data.sensors.mag[key] + "
"; - } - outputWindow.style.border="1px black"; - - } - }); + } + }); + + function loadSelfCommands(){ + var commands = {} + commands.speaker = function(value){sendSelfCommand("speaker",value)}; // "speaker" also works in the same way + + commands.mic = function(value){sendSelfCommand("mic",value)}; + + commands.camera = function(value){sendSelfCommand("camera",value)}; + + commands.bitrate = function(value){sendSelfCommand("bitrate",value)}; + + commands.volume = function(value){sendSelfCommand("volume",value)}; + + commands.record = function(value){sendSelfCommand("record",value)}; + + commands.sayHello = function(value){sendSelfCommand("sendChat","Hello")}; + + var target_self = document.body; + + var hr = document.createElement("hr"); + target_self.appendChild(hr); + + var h3 = document.createElement("h3"); + h3.innerText = "The following commands re-use the Companion.Ninja HTTP/WSS API, except you can send them via this Iframe interface."; + target_self.appendChild(h3); + + var a = document.createElement("a"); + a.innerText = "More details of the below IFRAME API details are here: https://github.com/steveseguin/Companion-Ninja#api-commands"; + a.href = "https://github.com/steveseguin/Companion-Ninja#api-commands"; + a.target = "_blank"; + target_self.appendChild(a); + + var hr = document.createElement("hr"); + target_self.appendChild(hr); + + + for (var k in commands) { + + var button = document.createElement("button"); + button.innerHTML = k + ":
TRUE"; + button.dataset.command = k; + button.onclick = function(){commands[this.dataset.command](true);} + target_self.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = k + ":
FALSE"; + button.dataset.command = k; + button.onclick = function(){commands[this.dataset.command](false);} + target_self.appendChild(button); + + } // list available commands to console + + commands.reload = function(){sendSelfCommand("reload",true);}; + + commands.hangup = function(){sendSelfCommand("hangup",true);}; + + + var button = document.createElement("button"); + button.innerHTML = k + ":
TRUE"; + button.onclick = function(){commands["reload"](true);} + target_self.appendChild(button); + + + var button = document.createElement("button"); + button.innerHTML = k + ":
TRUE"; + button.onclick = function(){commands["hangup"](true);} + target_self.appendChild(button); + + return commands; + + } + + function loadGuestCommands(guestid, streamID=false){ // this is the same as the Companion API, but can be issued to the IFRAME API + + var container = document.createElement("div"); + container.id = "guest_"+guestid+"_container"; + document.body.appendChild(container); + + var hr = document.createElement("hr"); + container.appendChild(hr); + var h3 = document.createElement("h3"); + if (streamID){ + h3.innerHTML = "These target guest with the streamID: "+guestid+ " (if a director)"; + } else { + h3.innerText = "These target the guest in slot "+guestid+ " (if you are director)"; + } + container.appendChild(h3); + + var button = document.createElement("button"); + button.innerHTML = "transfer popup"; + button.onclick = function(){sendGuestCommand(guestid, "forward");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "transfer to 'room321'"; + button.onclick = function(){sendGuestCommand(guestid, "forward", 'room321');}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 1"; + button.onclick = function(){sendGuestCommand(guestid, "addScene");}; /// SCENE 1 or specify a custom scene name as a value + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "mute in scene"; + button.onclick = function(){sendGuestCommand(guestid, "muteScene");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "mute everywhere"; + button.onclick = function(){sendGuestCommand(guestid, "mic");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "hang up"; + button.onclick = function(){sendGuestCommand(guestid, "hangup");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "solo chat"; + button.onclick = function(){sendGuestCommand(guestid, "soloChat");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "remote speaker"; + button.onclick = function(){sendGuestCommand(guestid, "speaker");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "remote display"; + button.onclick = function(){sendGuestCommand(guestid, "display");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "rainbow puke fix"; + button.onclick = function(){sendGuestCommand(guestid, "forceKeyframe");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "highlight"; + button.onclick = function(){sendGuestCommand(guestid, "soloVideo");}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 2"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 2);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 3"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 3);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 4"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 4);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 5"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 5);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 6"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 6);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = " scene 7"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 7);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 8"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 8);}; + container.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "scene 'test'"; + button.onclick = function(){sendGuestCommand(guestid, "addScene", 'test');}; // specifying a custom scene; it needs to be active for this to work.. + container.appendChild(button); + + + var input = document.createElement("label"); + input.innerHTML = "mic volume:"; + container.appendChild(input); + var input = document.createElement("input"); + input.type = "range"; + input.title = "volume"; + input.min = 0; + input.max = 200; + input.value = 100; + input.onchange = function(){sendGuestCommand(guestid, "volume", this.value);}; + container.appendChild(input); + + } + + function sendGuestCommand(target, action, value=null){ // + iframe.contentWindow.postMessage({"target":target, "action":action, "value":value}, '*'); // + //sendMessage(JSON.stringify({"target":target, "action":action, "value":value})); // if using the Companion API.. + } + + function sendSelfCommand(action, value=null){ + iframe.contentWindow.postMessage({"target":null, "action":action, "value":value}, '*'); + //sendMessage(JSON.stringify({"target":target, "action":action, "value":value})); // if using the Companion API.. + } + + loadSelfCommands(); + loadGuestCommands(1); + loadGuestCommands(2); + loadGuestCommands(3); + var randomGuest = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); + loadGuestCommands(randomGuest, true); } @@ -407,8 +618,8 @@ function printValues( obj) { -Clean Output -Transparent +Clean Output +Transparent Hide Menu
diff --git a/index.html b/index.html index b4489da..b26fa93 100644 --- a/index.html +++ b/index.html @@ -22,7 +22,7 @@ - + VDO.Ninja @@ -34,8 +34,8 @@ - - + + @@ -44,7 +44,7 @@ - + - - + - + - + - + @@ -273,7 +272,7 @@ -

@@ -381,14 +380,14 @@

-