Add Group Chat to OBS
Rooms allow for simplified group-chat and the advanced management of multiple streams at once.
@@ -116,7 +135,7 @@
Add your Camera to OBS
@@ -164,12 +183,12 @@
Remote Screenshare into OBS
note: Do not forget to click "Share audio" in Chrome.
(Firefox does not support audio sharing.)

@@ -205,7 +224,7 @@
Create Reusable Invite
@@ -276,7 +295,7 @@
- Site last updated: June 7th, 2020. The previous version can be found at https://obs.ninja/v5/ if you are having new issues. + Site last updated: June 15th, 2020. The previous version can be found at https://obs.ninja/v5/ if you are having new issues.
Check out the sub-reddit for help and advanced info. I'm also on Discord and you can email me at steve@seguin.email
@@ -316,9 +335,14 @@Attempting\x20to\x20load\x20video\x20stream.
','div','select','startsWith','button','nocursor','Click\x20Here\x20for\x20a\x20quick\x20overview\x20and\x20help','offsetWidth','float4','keyCode','getTracks','NotReadableError','value','
','Mirror\x20all\x20videos','HxcfX','substring','then','\x20-\x20Link\x20to\x20Invite\x20users\x20to\x20broadcast\x20their\x20feeds\x20to\x20the\x20group.\x20These\x20users\x20will\x20not\x20see\x20or\x20hear\x20any\x20feed\x20from\x20the\x20group.
','childNodes','https:','targetBandwidth','An\x20error\x20occured.\x20Upgrading\x20to\x20at\x20least\x20iOS\x2013.4\x20should\x20fix\x20this\x20glitch\x20from\x20happening\x20again','.webm','click','scale','applyConstraints','Error:\x20Media\x20stream\x20creation\x20failed.','toLowerCase','An\x20OBS\x20Virtual\x20Camera\x20was\x20detected;\x20Success!','push','IyRLM','forceios','download','color','metaKey','
Please\x20select\x20an\x20option\x20to\x20join.','select#audioSourceScreenshare','header','hidden','camera\x20','checkbox','controls','stopping\x20old\x20track','enumerated','mutetoggle','mouseover','UzoiG','text','LSctz','trying\x20to\x20list\x20webcam\x20again','recorder','getVideoTracks','secure','NavigatorUserMediaError','TTTOx','roomid','userAgent','max','pluginVersion','obs.ninja','-\x20Please\x20accept\x20any\x20camera\x20permissions','webcam','configuration','fontWeight','yfbjb','security','view=','removeChild','noiseSuppression','OBS\x20STATUS:','clientX','AAhJv','enumerateDevices','CliCb','mousedown','float','&codec=vp9','Task\x20ID\x20-\x20','event','documentElement','[?&]','directorsgrid','Mute','GOT\x20IT\x20BUT\x20WITH\x20NO\x20AUDIO','bottom\x20center','scrollTo','channels','contextmenu','got\x20devices!','connect','videoElement','wxogg','width','Share\x20your\x20Camera','invite_quality','XRelz','fa\x20fa-eye\x20my-float','Recorded\x20Blobs:\x20','deviceId','left','get','Mac\x20OS\x20X','touchcancel','YEacf','removeAttribute','status','getAttribute','streamID\x20is:\x20','Press\x20OK\x20to\x20start\x20recording.\x20Press\x20again\x20to\x20stop\x20and\x20download.\x0a\x0aWarning:\x20Keep\x20this\x20browser\x20tab\x20active\x20to\x20continue\x20recording.\x0a\x0aYou\x20can\x20change\x20the\x20default\x20video\x20bitrate\x20if\x20desired\x20below\x20(kbps)','Update\x20should\x20not\x20be\x20called\x20on\x20DIRECTORs\x20view?\x20sorta\x20at\x20least','keyup','&stereo','Got\x20second\x20stream','session:\x20myself','mainmenu','view','SAiFZ','50px','addEventListener','sendroom','innerWidth','copy','rpcs','videoname4','dirroomid','which','mouseleave','request','RTC\x20already\x20connected','detail','fa\x20fa-microphone-slash\x20my-float','=([^]*)','HfzsN','ended','Record','gear_webcam','absolute','setSelectionRange','originalEvent','red','invite_hidescreen','codec','QSHMQ','Camera\x20failed\x20to\x20load.\x20\x0a\x0aPlease\x20make\x20sure\x20it\x20is\x20not\x20already\x20in\x20use\x20by\x20another\x20application.\x0a\x0aPlease\x20make\x20sure\x20you\x20have\x20accepted\x20the\x20camera\x20permissions.','tPlAA','Hide\x20This','data-translation','getStatus','touchend','resolution\x20found','Leaving\x20the\x20page\x20now\x20will\x20terminate\x20your\x20stream\x20','claim','mozvisibilitychange','privacy','previewWebcam','myself\x20set\x20fullscreen','XkERn','pushState','get\x20media\x20sources;\x20request\x20audio\x20stream','qkpYm','#3C3','block','Download','lONql','STEREO\x20ENABLED','drag\x20on','for','video\x20source\x20changed','mouseup','json','#DDDDDD','changing\x20title;\x20if\x20connected\x20at\x20least','catch','onmousedown','invite_vp9','videosource','onmousemove','\x20id\x20=\x20','contains','onpopstate','trying\x20with\x20quality:','ZZZ','Resolution\x20didn\x27t\x20work','isSecureContext','mbyIN','onclick','JwCvI','addTrack','buffer\x20Changed:\x20','#audioSource','activeated\x20preview\x20return\x201','obsoff','Unmute','invite_remotecontrol','muted','video\x20{transform:\x20scale(-1,\x201);webkit-transform:\x20scale(-1,\x201);-o-transform:\x20scale(-1,\x201);-moz-transform:\x20scale(-1,\x201);}','session:','remove','head3','ROOM\x20ID\x20ENABLED','pageY','pageX','Chat\x20message','outerHTML','\x22\x20/>\x20\x09\x09\x09
\x09\x09Please\x20also\x20note,\x20the\x20invite\x20link\x20and\x20OBS\x20ingestion\x20link\x20created\x20is\x20reusable,\x20but\x20only\x20one\x20person\x20may\x20use\x20a\x20specific\x20invite\x20at\x20a\x20time.','','dataset','start','enumerated\x20failed\x202','scrollTop','head4','SSL\x20(https)\x20is\x20not\x20enabled.\x20This\x20site\x20will\x20not\x20work\x20without\x20it!','auto\x20playing','Chrome','https://','resolution','style','invite_group_chat_type','getSources','OBS-Camera','mediaDevices','?scene=1&room=','OBS\x20SCENE','pathname','\x20set\x20fullscreen','chat','cursor','container-4','srcObject','buffer','
-\x20Please\x20select\x20which\x20you\x20wish\x20to\x20share','','getElementById','body','clientY','\x20is\x20not\x20defined;\x20skipping.','indexOf','revokeObjectURL','&novideo','info','maxframerate','frameRate','container-1','Trying\x20Constraints','IFgiL','never','getSettings','gencontent','querySelectorAll','min','OverconstrainedError','ALREADY\x20RECORDING!','OBS\x20VERSION:','none','visibility','mutevideobutton','Join\x20room','Waiting\x20for\x20Camera\x20to\x20load','stop','TURN\x20server\x20parameters\x20were\x20wrong.','input','max\x20channels\x20is\x2032;\x20channels\x20offset','host','hostname','saved','drag','float2','getAudioTracks','pcs','url(\x27data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHdpZHRoPSI0MHB4IiBoZWlnaHQ9IjQwcHgiIHZpZXdCb3g9IjAgMCA0MCA0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7IiB4PSIwcHgiIHk9IjBweCI+CiAgICA8ZGVmcz4KICAgICAgICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWwogICAgICAgICAgICBALXdlYmtpdC1rZXlmcmFtZXMgc3BpbiB7CiAgICAgICAgICAgICAgZnJvbSB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoLTM1OWRlZykKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQGtleWZyYW1lcyBzcGluIHsKICAgICAgICAgICAgICBmcm9tIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKC0zNTlkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHN2ZyB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybS1vcmlnaW46IDUwJSA1MCU7CiAgICAgICAgICAgICAgICAtd2Via2l0LWFuaW1hdGlvbjogc3BpbiAxLjVzIGxpbmVhciBpbmZpbml0ZTsKICAgICAgICAgICAgICAgIC13ZWJraXQtYmFja2ZhY2UtdmlzaWJpbGl0eTogaGlkZGVuOwogICAgICAgICAgICAgICAgYW5pbWF0aW9uOiBzcGluIDEuNXMgbGluZWFyIGluZmluaXRlOwogICAgICAgICAgICB9CiAgICAgICAgXV0+PC9zdHlsZT4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJvdXRlciI+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwwQzIyLjIwNTgsMCAyMy45OTM5LDEuNzg4MTMgMjMuOTkzOSwzLjk5MzlDMjMuOTkzOSw2LjE5OTY4IDIyLjIwNTgsNy45ODc4MSAyMCw3Ljk4NzgxQzE3Ljc5NDIsNy45ODc4MSAxNi4wMDYxLDYuMTk5NjggMTYuMDA2MSwzLjk5MzlDMTYuMDA2MSwxLjc4ODEzIDE3Ljc5NDIsMCAyMCwwWiIgc3R5bGU9ImZpbGw6YmxhY2s7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNNS44NTc4Niw1Ljg1Nzg2QzcuNDE3NTgsNC4yOTgxNSA5Ljk0NjM4LDQuMjk4MTUgMTEuNTA2MSw1Ljg1Nzg2QzEzLjA2NTgsNy40MTc1OCAxMy4wNjU4LDkuOTQ2MzggMTEuNTA2MSwxMS41MDYxQzkuOTQ2MzgsMTMuMDY1OCA3LjQxNzU4LDEzLjA2NTggNS44NTc4NiwxMS41MDYxQzQuMjk4MTUsOS45NDYzOCA0LjI5ODE1LDcuNDE3NTggNS44NTc4Niw1Ljg1Nzg2WiIgc3R5bGU9ImZpbGw6cmdiKDIxMCwyMTAsMjEwKTsiLz4KICAgICAgICA8L2c+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwzMi4wMTIyQzIyLjIwNTgsMzIuMDEyMiAyMy45OTM5LDMzLjgwMDMgMjMuOTkzOSwzNi4wMDYxQzIzLjk5MzksMzguMjExOSAyMi4yMDU4LDQwIDIwLDQwQzE3Ljc5NDIsNDAgMTYuMDA2MSwzOC4yMTE5IDE2LjAwNjEsMzYuMDA2MUMxNi4wMDYxLDMzLjgwMDMgMTcuNzk0MiwzMi4wMTIyIDIwLDMyLjAxMjJaIiBzdHlsZT0iZmlsbDpyZ2IoMTMwLDEzMCwxMzApOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksMjguNDkzOUMzMC4wNTM2LDI2LjkzNDIgMzIuNTgyNCwyNi45MzQyIDM0LjE0MjEsMjguNDkzOUMzNS43MDE5LDMwLjA1MzYgMzUuNzAxOSwzMi41ODI0IDM0LjE0MjEsMzQuMTQyMUMzMi41ODI0LDM1LjcwMTkgMzAuMDUzNiwzNS43MDE5IDI4LjQ5MzksMzQuMTQyMUMyNi45MzQyLDMyLjU4MjQgMjYuOTM0MiwzMC4wNTM2IDI4LjQ5MzksMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxMDEsMTAxLDEwMSk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMy45OTM5LDE2LjAwNjFDNi4xOTk2OCwxNi4wMDYxIDcuOTg3ODEsMTcuNzk0MiA3Ljk4NzgxLDIwQzcuOTg3ODEsMjIuMjA1OCA2LjE5OTY4LDIzLjk5MzkgMy45OTM5LDIzLjk5MzlDMS43ODgxMywyMy45OTM5IDAsMjIuMjA1OCAwLDIwQzAsMTcuNzk0MiAxLjc4ODEzLDE2LjAwNjEgMy45OTM5LDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoMTg3LDE4NywxODcpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTUuODU3ODYsMjguNDkzOUM3LjQxNzU4LDI2LjkzNDIgOS45NDYzOCwyNi45MzQyIDExLjUwNjEsMjguNDkzOUMxMy4wNjU4LDMwLjA1MzYgMTMuMDY1OCwzMi41ODI0IDExLjUwNjEsMzQuMTQyMUM5Ljk0NjM4LDM1LjcwMTkgNy40MTc1OCwzNS43MDE5IDUuODU3ODYsMzQuMTQyMUM0LjI5ODE1LDMyLjU4MjQgNC4yOTgxNSwzMC4wNTM2IDUuODU3ODYsMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxNjQsMTY0LDE2NCk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMzYuMDA2MSwxNi4wMDYxQzM4LjIxMTksMTYuMDA2MSA0MCwxNy43OTQyIDQwLDIwQzQwLDIyLjIwNTggMzguMjExOSwyMy45OTM5IDM2LjAwNjEsMjMuOTkzOUMzMy44MDAzLDIzLjk5MzkgMzIuMDEyMiwyMi4yMDU4IDMyLjAxMjIsMjBDMzIuMDEyMiwxNy43OTQyIDMzLjgwMDMsMTYuMDA2MSAzNi4wMDYxLDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoNzQsNzQsNzQpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksNS44NTc4NkMzMC4wNTM2LDQuMjk4MTUgMzIuNTgyNCw0LjI5ODE1IDM0LjE0MjEsNS44NTc4NkMzNS43MDE5LDcuNDE3NTggMzUuNzAxOSw5Ljk0NjM4IDM0LjE0MjEsMTEuNTA2MUMzMi41ODI0LDEzLjA2NTggMzAuMDUzNiwxMy4wNjU4IDI4LjQ5MzksMTEuNTA2MUMyNi45MzQyLDkuOTQ2MzggMjYuOTM0Miw3LjQxNzU4IDI4LjQ5MzksNS44NTc4NloiIHN0eWxlPSJmaWxsOnJnYig1MCw1MCw1MCk7Ii8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4K\x27)','head2','./translations/','inherit','\x0a\x09video{\x0a\x09\x09margin:\x200;\x0a\x09\x09padding:\x200;\x0a\x09\x09overflow:\x20hidden;\x0a\x09\x09cursor:\x20url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=),\x20none;\x0a\x09\x09user-select:\x20none;\x0a\x09}\x0a\x09','#audioSource\x20input[type=\x27checkbox\x27]','OfDml','[data-translate]','Error\x20handling\x20QR\x20Code\x20failure','quality','makeCode','getUserMedia','label=','Copied\x20to\x20Clipboard','Fnmpm','joinroomID','disable\x20audio\x20playback','framerate\x20Changed','enable','#context-menu','alignSelf','height','streamID','Looks\x20like\x20there\x20was\x20a\x20problem.\x20Status\x20Code:\x20','kind','audioinput','turn','Privacy\x20mode\x20failed\x20to\x20configure.','Record\x20Video\x20queued','data-action','KhJHS','JBdqp','The\x20stream\x20is\x20not\x20available\x20yet\x20or\x20an\x20error\x20occured.
','readyState','300px','optimize','querySelector','Zoom\x20is\x20not\x20supported\x20by\x20','mute','sendMsg','yEQzu','&remote=','top','?room=','&layer-height=720','video','
GUEST\x20SLOT\x20#1
(A\x20video\x20will\x20appear\x20here\x20when\x20a\x20guest\x20joins)
A\x20Solo-Link\x20for\x20OBS\x20will\x20appear\x20here.
GUEST\x20SLOT\x20#2
(A\x20video\x20will\x20appear\x20here\x20when\x20a\x20guest\x20joins)
A\x20Solo\x20Link\x20for\x20OBS\x20will\x20appear\x20here
GUEST\x20SLOT\x20#3
(A\x20video\x20will\x20appear\x20here\x20when\x20a\x20guest\x20joins)
A\x20Solo\x20Link\x20for\x20OBS\x20will\x20appear\x20here
GUEST\x20SLOT\x20#4
(A\x20video\x20will\x20appear\x20here\x20when\x20a\x20guest\x20joins)
A\x20Solo\x20Link\x20for\x20OBS\x20will\x20appear\x20here
and\x20don\x27t\x20forget\x20the
OBS\x20Browser\x20Source\x20Link:
\x09Welcome.\x20This\x20is\x20the\x20control-room\x20for\x20the\x20group-chat.\x20There\x20are\x20different\x20things\x20you\x20can\x20use\x20this\x20room\x20for:
\x09
\x09As\x20guests\x20join,\x20their\x20videos\x20will\x20appear\x20below.\x20You\x20can\x20bring\x20their\x20video\x20streams\x20into\x20OBS\x20as\x20solo-scenes\x20or\x20you\x20can\x20add\x20them\x20to\x20the\x20Group\x20Scene.\x09
The\x20Group\x20Scene\x20auto-mixes\x20videos\x20that\x20have\x20been\x20added\x20to\x20the\x20group\x20scene.\x20Please\x20note\x20that\x20the\x20Auto-Mixer\x20requires\x20guests\x20be\x20manually\x20added\x20to\x20it\x20for\x20them\x20to\x20appear\x20in\x20it;\x20they\x20are\x20not\x20added\x20automatically.
Apple\x20mobile\x20devices,\x20such\x20as\x20iPhones\x20and\x20iPads,\x20do\x20not\x20fully\x20support\x20Video\x20Group\x20Chat.\x20This\x20is\x20a\x20hardware\x20constraint.
','head1','Current\x20Video\x20Settings:\x20','KEtZw','browser','audiobitrate','microphone\x20','test','trim','streamSrc','fa\x20fa-eye-slash\x20my-float','mousemove','allow\x20iOS\x20to\x20work\x20in\x20video\x20group\x20chat;\x20for\x20this\x20user\x20at\x20least','NgOka','IKsMq','stereo','PRESS\x20WHEN\x20READY!','chSer','backgroundImage','onload','add','container-3','No\x20OBS\x20Virtual\x20Camera\x20was\x20found','zoomSlider','some','adding\x20additional\x20audio\x20tracks','fps','minHeight','ceil','videoname1','keydown','AUDIO\x20source\x20CHANGED','AUDIO\x20BITRATE\x20SET','dataTransfer','context-menu__link','BITRATE\x20ENABLED','srcElement','obsSceneChanged','backgroundColor','beforeunload','has','bold','DISABLE\x20CURSOR','getCurrentScene','0px','infocus','RgfLX','videoinput','length','username','relay','ctrlKey','Join\x20Room\x20with\x20Camera','searchString','center','constraints','DONE\x20-\x20found\x20stream','touchmove','requestRateLimit','********Camera\x20failed\x20to\x20work','gridlayout','generateStreamID','&webcam','An\x20error\x20has\x20occured\x20when\x20trying\x20to\x20access\x20the\x20webcam.\x20The\x20reason\x20is\x20not\x20known.','disabled','gowebcam','target','&view','.context-menu__item','history','permaid','position','#CCC','opacity','label','utwKx','\x20-\x20','LoJFr','publishStream','groupId','resize','fullscreen'];(function(_0xdf898,_0xede2ea){var _0x33ecda=function(_0xcff2bd){while(--_0xcff2bd){_0xdf898['push'](_0xdf898['shift']());}};_0x33ecda(++_0xede2ea);}(_0xede2,0x67));var _0x33ec=function(_0xdf898,_0xede2ea){_0xdf898=_0xdf898-0x0;var _0x33ecda=_0xede2[_0xdf898];return _0x33ecda;};var formSubmitting=!![];var activatedPreview=![];function getById(_0x57eeb5){var _0x2a0970=document[_0x33ec('0x141')](_0x57eeb5);if(!_0x2a0970){errorlog(_0x57eeb5+_0x33ec('0x144'));_0x2a0970=document[_0x33ec('0x5b')](_0x33ec('0x19f'));}return _0x2a0970;}if(window[_0x33ec('0x24b')]){log(_0x33ec('0x155')+window[_0x33ec('0x24b')][_0x33ec('0x93')]);log(_0x33ec('0x24a')+navigator[_0x33ec('0x91')][_0x33ec('0x145')](_0x33ec('0xbe'))!=-0x1);log(window['obsstudio']);var ver1=window[_0x33ec('0x24b')]['pluginVersion'];ver1=ver1[_0x33ec('0x2c')]('.');if(ver1[_0x33ec('0x1d4')]==0x3){if(ver1[_0x33ec('0x1d4')]==0x3&&parseInt(ver1[0x0])==0x2&&parseInt(ver1[0x1])>0x4&&navigator[_0x33ec('0x91')][_0x33ec('0x145')](_0x33ec('0xbe'))!=-0x1){getById('main')[_0x33ec('0x52')]='
On\x20macOS,\x20Please\x20use\x20OBS\x20v23,\x20as\x20OBS\x20v24\x20and\x20v25\x20are\x20not\x20supported\x20currently.
\x09\x09\x09\x20Please\x20find\x20details\x20within\x20our\x20wiki\x20guide\x20-\x20https://github.com/steveseguin/obsninja/wiki/FAQ#mac-os
\x09\x09\x09\x20(Version\x20of\x20OBS\x20Plugin\x20Detected:\x20'+window[_0x33ec('0x24b')][_0x33ec('0x93')]+',\x20and\x20should\x20currently\x20be\x202.4.0\x20on\x20macOS)\x09\x09\x09
\x20Please\x20report\x20this\x20problem\x20to\x20steve@seguin.email\x20if\x20you\x20feel\x20it\x20is\x20an\x20error.\x09\x09\x09
Attempting\x20to\x20load\x20video\x20stream.
';getById(_0x33ec('0xcb'))[_0x33ec('0x52')]+=_0x33ec('0x186');}}}catch(_0x53938f){if(window[_0x33ec('0x110')]){alert('An\x20error\x20has\x20occured\x20when\x20trying\x20to\x20access\x20the\x20webcam.\x20The\x20reason\x20is\x20not\x20known.');}else{alert('Error\x20acessing\x20webcam.\x0a\x0aWebsite\x20is\x20loaded\x20in\x20an\x20insecure\x20context.\x0a\x0aPlease\x20see:\x20https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia');}}},0xa);}function checkOBS(){if(!navigator[_0x33ec('0x135')]||!navigator[_0x33ec('0x135')][_0x33ec('0xa1')]){log('enumerateDevices()\x20not\x20supported.');return;}navigator[_0x33ec('0x135')][_0x33ec('0xa1')]()[_0x33ec('0x68')](function(_0x2af5c5){var _0x52ef95=![];_0x2af5c5[_0x33ec('0x7')](function(_0xeec946){if(_0xeec946[_0x33ec('0x1ee')]['startsWith']('OBS-Camera')){alert(_0x33ec('0x75'));log(_0xeec946[_0x33ec('0x17e')]+':\x20'+_0xeec946[_0x33ec('0x1ee')]+_0x33ec('0x10a')+_0xeec946[_0x33ec('0xbb')]);_0x52ef95=!![];}log(_0xeec946['kind']+':\x20'+_0xeec946[_0x33ec('0x1ee')]+_0x33ec('0x10a')+_0xeec946[_0x33ec('0xbb')]);});if(_0x52ef95==![]){if(_0x33ec('0xe7')===_0x33ec('0xb8')){ele[_0x33ec('0x52')]=data[ele[_0x33ec('0x127')]['translate']];}else{alert(_0x33ec('0x1ba'));}}})[_0x33ec('0x105')](function(_0x34dcfb){if(_0x33ec('0x1b5')!==_0x33ec('0x1b5')){getById(_0x33ec('0x1a5'))['innerHTML']='';}else{log(_0x34dcfb['name']+':\x20'+_0x34dcfb['message']);}});}function recordVideo(_0x2b65bc,_0x5abc7e,_0x3edf6c,_0x290286=![]){if(CtrlPressed){_0x2b65bc[_0x33ec('0x52')]=_0x33ec('0x256');Callbacks['push']([recordVideo,_0x2b65bc,_0x5abc7e,_0x3edf6c,0x9c4]);log(_0x33ec('0x182'));return;}log(_0x33ec('0x250'));if(_0x33ec('0x45')in _0x5abc7e){log(_0x33ec('0x154'));_0x2b65bc['style'][_0x33ec('0x1ca')]=null;_0x2b65bc[_0x33ec('0x52')]=_0x33ec('0xdf');_0x5abc7e[_0x33ec('0x8b')][_0x33ec('0x15b')]();session['requestRateLimit'](0x23,_0x3edf6c);delete _0x5abc7e[_0x33ec('0x8b')];delete _0x5abc7e['recording'];return;}else{_0x2b65bc['style'][_0x33ec('0x1ca')]=_0x33ec('0x205');_0x2b65bc[_0x33ec('0x52')]=_0x33ec('0xfb');_0x5abc7e[_0x33ec('0x45')]=!![];}if(_0x290286==![]){_0x290286=0x9c4;_0x290286=prompt(_0x33ec('0xc5'),_0x290286);_0x290286=parseInt(_0x290286);}if(_0x290286<0x23){_0x290286=0x23;}session[_0x33ec('0x1de')](_0x290286,_0x3edf6c);var _0x51c087=Date[_0x33ec('0xd')]()[_0x33ec('0x25a')]();var _0x4d5c16=[];var _0x223100=_0x5abc7e[_0x33ec('0x13d')];var _0x1b1c44=![];if(typeof _0x223100===_0x33ec('0x12')||!_0x223100){return;}this[_0x33ec('0x15b')]=_0x3b6df7;let _0x2d880b={'mimeType':_0x33ec('0x207'),'videoBitsPerSecond':parseInt(_0x290286*0x3e8)};var _0x119d57=new MediaRecorder(_0x223100,_0x2d880b);var _0x36db52=0x0;function _0x4dcb5f(){const _0xc08b54=new Blob(_0x4d5c16,{'type':_0x33ec('0x207')});const _0xa46fb=window[_0x33ec('0x241')][_0x33ec('0x44')](_0xc08b54);const _0x1890d2=document[_0x33ec('0x5b')]('a');_0x1890d2['style'][_0x33ec('0x34')]='none';_0x1890d2[_0x33ec('0x32')]=_0xa46fb;_0x1890d2[_0x33ec('0x79')]=_0x51c087+_0x33ec('0x6f');document[_0x33ec('0x142')][_0x33ec('0x232')](_0x1890d2);_0x1890d2[_0x33ec('0x70')]();setTimeout(()=>{document[_0x33ec('0x142')][_0x33ec('0x9c')](_0x1890d2);window['URL'][_0x33ec('0x146')](_0xa46fb);},0x64);}function _0x10f7a1(_0x251c80){if(_0x251c80[_0x33ec('0x53')]&&_0x251c80[_0x33ec('0x53')]['size']>0x0){_0x4d5c16[_0x33ec('0x76')](_0x251c80[_0x33ec('0x53')]);}}function _0x3b6df7(){_0x119d57[_0x33ec('0x15b')]();_0x1b1c44=!![];log(_0x33ec('0xba'),_0x4d5c16);_0x4dcb5f();}_0x119d57[_0x33ec('0x233')]=_0x10f7a1;_0x119d57[_0x33ec('0x3a')]=function(_0x27f0d3){errorlog(_0x27f0d3);_0x3b6df7();session[_0x33ec('0x1de')](0x23,_0x3edf6c);alert(_0x33ec('0x31'));};_0x223100[_0x33ec('0xde')]=function(_0x3fbd72){_0x3b6df7();session[_0x33ec('0x1de')](0x23,_0x3edf6c);alert(_0x33ec('0x1a'));};_0x119d57[_0x33ec('0x128')](0x64);_0x5abc7e['recorder']=this;return;}function copyFunction(_0x1cf723){_0x1cf723[_0x33ec('0x22a')]();_0x1cf723[_0x33ec('0xe2')](0x0,0x1869f);document['execCommand'](_0x33ec('0xd2'));}function generateQRPage(){try{var _0x5ae200=encodeURI(getById(_0x33ec('0xd4'))[_0x33ec('0x4')]);if(_0x5ae200[_0x33ec('0x1d4')]){_0x5ae200='&label='+_0x5ae200;}var _0x4ea57d=session['generateStreamID']();var _0x1f27be='';var _0x5eec7b='';if(getById(_0x33ec('0x2d'))['checked']){_0x1f27be+='&bitrate=20000';}if(getById(_0x33ec('0x107'))['checked']){_0x1f27be+=_0x33ec('0xa5');}if(getById(_0x33ec('0x35'))['checked']){_0x1f27be+=_0x33ec('0xc8');_0x5eec7b+='&stereo';}if(getById('invite_secure')['checked']){_0x5eec7b+=_0x33ec('0x21a');}if(getById(_0x33ec('0xe5'))[_0x33ec('0x2a')]){_0x5eec7b+=_0x33ec('0x1e2');}if(getById(_0x33ec('0x11a'))[_0x33ec('0x2a')]){var _0x3d4f42=session['generateStreamID']();_0x5eec7b+=_0x33ec('0x18f')+_0x3d4f42;_0x1f27be+=_0x33ec('0x18f')+_0x3d4f42;}if(getById(_0x33ec('0x15'))[_0x33ec('0x4')][_0x33ec('0x1ac')]()[_0x33ec('0x1d4')]){_0x5eec7b+='&room='+getById(_0x33ec('0x15'))[_0x33ec('0x4')][_0x33ec('0x1ac')]();_0x1f27be+='&scene=1&room='+getById(_0x33ec('0x15'))['value']['trim']();}if(getById(_0x33ec('0x132'))['value']){if(getById(_0x33ec('0x132'))[_0x33ec('0x4')]==0x1){_0x5eec7b+=_0x33ec('0x147');}else if(getById(_0x33ec('0x132'))[_0x33ec('0x4')]==0x2){_0x5eec7b+=_0x33ec('0x1e7');}}if(getById(_0x33ec('0xb7'))[_0x33ec('0x4')]){if(_0x33ec('0x87')!=='UzoiG'){return;}else{if(getById(_0x33ec('0xb7'))['value']==0x0){_0x5eec7b+='&quality=0';}else if(getById(_0x33ec('0xb7'))['value']==0x1){_0x5eec7b+=_0x33ec('0x20a');}else if(getById(_0x33ec('0xb7'))[_0x33ec('0x4')]==0x2){_0x5eec7b+='&quality=2';}}}_0x5eec7b='https://'+location[_0x33ec('0x15f')]+location[_0x33ec('0x138')]+'?push='+_0x4ea57d+_0x5eec7b;_0x1f27be=_0x33ec('0x12f')+location[_0x33ec('0x15f')]+location[_0x33ec('0x138')]+_0x33ec('0x201')+_0x4ea57d+_0x1f27be+_0x5ae200;getById(_0x33ec('0x150'))['innerHTML']='Guest\x20Invite\x20Link:
0x1){var _0x3b97e4=Math['pow'](_0x5c1aa1*_0x17c496/_0x3ae42e[_0x33ec('0x1d4')],0.5);var _0x4a300f=Math[_0x33ec('0x1c0')](_0x5c1aa1/_0x3b97e4);var _0x13ea80=Math[_0x33ec('0x1c0')](_0x17c496/_0x3b97e4);}else{var _0x4a300f=0x1;var _0x13ea80=0x1;}_0x52a2f6[_0x33ec('0x52')]='';var _0x563930=0x0;var _0x486cbc=0x0;_0x3ae42e[_0x33ec('0x7')](_0x33e791=>{if('Fnmpm'===_0x33ec('0x174')){_0x33e791[_0x33ec('0x131')][_0x33ec('0x1eb')]=_0x33ec('0xe1');_0x33e791['display']=_0x33ec('0xfa');offsetx=0x0;if(Math[_0x33ec('0x1c0')]((_0x563930+0.1)/_0x4a300f)==_0x13ea80){offsetx=(window[_0x33ec('0xd1')]-(_0x4a300f-_0x3ae42e[_0x33ec('0x1d4')]%_0x13ea80)*Math[_0x33ec('0x1c0')](window[_0x33ec('0xd1')]/_0x4a300f))/0x2;}offsety=(_0x1ce89b-Math['ceil'](_0x3ae42e[_0x33ec('0x1d4')]/_0x4a300f)*Math[_0x33ec('0x1c0')](_0x1ce89b/_0x13ea80))/0x2;_0x33e791[_0x33ec('0x131')]['left']=offsetx+Math[_0x33ec('0x61')]((_0x563930%_0x4a300f+0x0)*_0x909c97/_0x4a300f)+'px';_0x33e791[_0x33ec('0x131')][_0x33ec('0x190')]=offsety+Math[_0x33ec('0x61')]((Math[_0x33ec('0x61')](_0x563930/_0x4a300f)+0x0)*_0x1ce89b/_0x13ea80+_0xcb126e)+'px';_0x33e791[_0x33ec('0x131')][_0x33ec('0xb5')]=Math['ceil'](_0x909c97/_0x4a300f)+'px';_0x33e791[_0x33ec('0x131')][_0x33ec('0x17b')]=Math[_0x33ec('0x1c0')](_0x1ce89b/_0x13ea80)+'px';_0x52a2f6[_0x33ec('0x232')](_0x33e791);try{_0x33e791[_0x33ec('0x1e')]()[_0x33ec('0x68')](_0x215484=>{log(_0x33ec('0x235'));})[_0x33ec('0x105')](errorlog);}catch(_0x3c4d32){errorlog(_0x3c4d32);}var _0x29533f=document[_0x33ec('0x5b')](_0x33ec('0x229'));_0x29533f['id']=_0x33ec('0x23')+_0x33e791['id'];_0x29533f[_0x33ec('0x52')]=_0x33ec('0x126');_0x29533f['style'][_0x33ec('0xb5')]=_0x33ec('0xce');_0x29533f[_0x33ec('0x131')][_0x33ec('0x17b')]=_0x33ec('0xce');_0x29533f[_0x33ec('0x131')][_0x33ec('0x1eb')]=_0x33ec('0xe1');_0x29533f[_0x33ec('0x131')][_0x33ec('0x34')]=_0x33ec('0x156');_0x29533f[_0x33ec('0x131')][_0x33ec('0xbc')]=Math['ceil'](_0x909c97/_0x4a300f)-0x32+offsetx+Math['floor']((_0x563930%_0x4a300f+0x0)*_0x909c97/_0x4a300f)+'px';_0x29533f[_0x33ec('0x131')][_0x33ec('0x190')]=offsety+Math[_0x33ec('0x61')]((Math['floor'](_0x563930/_0x4a300f)+0x0)*_0x1ce89b/_0x13ea80+_0xcb126e)+'px';_0x29533f[_0x33ec('0x131')][_0x33ec('0x7a')]=_0x33ec('0x3d');_0x29533f['style'][_0x33ec('0x13b')]='pointer';_0x52a2f6[_0x33ec('0x232')](_0x29533f);if(_0x33e791['id']==_0x33ec('0x108')){if('wxogg'===_0x33ec('0xb4')){_0x29533f['onclick']=function(){var _0x44cd0a=event[_0x33ec('0x1f')];if(session[_0x33ec('0x1d1')]===!![]){session['infocus']=![];_0x44cd0a[_0x33ec('0x52')]='';}else{session['infocus']=!![];log(_0x33ec('0xca'));_0x44cd0a[_0x33ec('0x52')]=_0x33ec('0x140');}setTimeout(()=>updateMixer(),0xa);};}else{menuState=0x1;menu[_0x33ec('0x24e')][_0x33ec('0x1b8')](_0x33ec('0x4b'));}}else{_0x29533f[_0x33ec('0x127')]['UUID']=_0x33e791['dataset'][_0x33ec('0x1fa')];_0x29533f['onclick']=function(_0x5da660){var _0x19d95d=_0x5da660[_0x33ec('0x1f')];log(_0x33ec('0x1f5'));log(_0x19d95d);if(session[_0x33ec('0x1d1')]===_0x19d95d['dataset']['UUID']){_0x19d95d['innerHTML']=_0x33ec('0x126');session['infocus']=![];}else{_0x19d95d[_0x33ec('0x52')]=_0x33ec('0x140');session['infocus']=_0x19d95d[_0x33ec('0x127')][_0x33ec('0x1fa')];log(_0x33ec('0x11d')+_0x19d95d[_0x33ec('0x127')][_0x33ec('0x1fa')]);}setTimeout(()=>updateMixer(),0xa);};}_0x29533f[_0x33ec('0x225')]=function(){_0x29533f[_0x33ec('0x131')][_0x33ec('0x34')]=_0x33ec('0xfa');};_0x33e791[_0x33ec('0x225')]=function(){_0x29533f['style'][_0x33ec('0x34')]=_0x33ec('0xfa');};_0x33e791[_0x33ec('0x22')]=function(){_0x29533f[_0x33ec('0x131')][_0x33ec('0x34')]=_0x33ec('0x156');};_0x563930+=0x1;}else{log('resolution\x20found');try{getById(_0x33ec('0xf3'))[_0x33ec('0x13d')]['getVideoTracks']()['forEach'](function(_0x5dc248){log(_0x5dc248[_0x33ec('0x14f')]());log(_0x5dc248[_0x33ec('0x14f')]()[_0x33ec('0x14a')]);getById('webcamstats')[_0x33ec('0x52')]=_0x33ec('0x1a6')+(_0x5dc248[_0x33ec('0x14f')]()[_0x33ec('0xb5')]||0x0)+'x'+(_0x5dc248[_0x33ec('0x14f')]()[_0x33ec('0x17b')]||0x0)+'@'+parseInt(_0x5dc248[_0x33ec('0x14f')]()[_0x33ec('0x14a')]*0xa)/0xa+_0x33ec('0x1be');});}catch(_0xf1b74a){errorlog(_0xf1b74a);}}});}var vis=function(){var _0x5c02d2,_0x43c318,_0x47f5a3={'hidden':'visibilitychange','webkitHidden':_0x33ec('0x219'),'mozHidden':_0x33ec('0xf1'),'msHidden':_0x33ec('0x20d')};for(_0x5c02d2 in _0x47f5a3){if(_0x5c02d2 in document){_0x43c318=_0x47f5a3[_0x5c02d2];break;}}return function(_0x298975){if(_0x298975){document[_0x33ec('0xcf')](_0x43c318,_0x298975);}return!document[_0x5c02d2];};}();(function rightclickmenuthing(){'use strict';function _0x24a136(_0x45aa0e,_0x2666f5){var _0x1bac9a=_0x45aa0e[_0x33ec('0x1c8')]||_0x45aa0e[_0x33ec('0x1e6')];if(_0x1bac9a[_0x33ec('0x24e')][_0x33ec('0x10b')](_0x2666f5)){if(_0x33ec('0x1f1')!==_0x33ec('0x8f')){return _0x1bac9a;}else{session[_0x33ec('0x149')]=0x1e;}}else{while(_0x1bac9a=_0x1bac9a['parentNode']){if(_0x1bac9a['classList']&&_0x1bac9a[_0x33ec('0x24e')][_0x33ec('0x10b')](_0x2666f5)){return _0x1bac9a;}}}return![];}function _0x5e1b34(_0x465a08){var _0x33e344=0x0;var _0x1376db=0x0;if(!_0x465a08)var _0x5922e3=window[_0x33ec('0xa7')];if(_0x465a08[_0x33ec('0x122')]||_0x465a08['pageY']){_0x33e344=_0x465a08['pageX'];_0x1376db=_0x465a08['pageY'];}else if(_0x465a08[_0x33ec('0x9f')]||_0x465a08['clientY']){if(_0x33ec('0x66')!==_0x33ec('0x66')){session[_0x33ec('0x1de')](0xc8,i);}else{_0x33e344=_0x465a08[_0x33ec('0x9f')]+document[_0x33ec('0x142')][_0x33ec('0x42')]+document[_0x33ec('0xa8')][_0x33ec('0x42')];_0x1376db=_0x465a08[_0x33ec('0x143')]+document[_0x33ec('0x142')]['scrollTop']+document[_0x33ec('0xa8')]['scrollTop'];}}return{'x':_0x33e344,'y':_0x1376db};}var _0x18895b=_0x33ec('0x251');var _0x569caa='context-menu__item';var _0x35154a=_0x33ec('0x1c6');var _0x4a4e82='context-menu--active';var _0xc6f2ea='task';var _0x31941e;var _0x202413;var _0x53f445;var _0x4cb2fe;var _0x9a9737=document[_0x33ec('0x18a')](_0x33ec('0x179'));var _0x42316b=_0x9a9737[_0x33ec('0x151')](_0x33ec('0x1e8'));var _0x1fb243=0x0;var _0x177722;var _0x37e163;var _0x1315df;var _0x455837;var _0x1e794e;var _0x6851f3;var _0x3cbe68;function _0x32b2c8(){_0xfdaa8c();_0x1f12f8();_0x63d599();_0x31615a();}function _0xfdaa8c(){document[_0x33ec('0xcf')](_0x33ec('0xb0'),function(_0x452a9d){_0x31941e=_0x24a136(_0x452a9d,_0xc6f2ea);if(_0x31941e){_0x452a9d[_0x33ec('0x203')]();_0x87d1c1();_0x1f95b8(_0x452a9d);}else{_0x31941e=null;_0x4418ae();}});}function _0x1f12f8(){document[_0x33ec('0xcf')](_0x33ec('0x70'),function(_0x1d12c6){var _0x24cef1=_0x24a136(_0x1d12c6,_0x35154a);if(_0x24cef1){_0x1d12c6[_0x33ec('0x203')]();_0x11bf14(_0x24cef1);}else{var _0x1dce37=_0x1d12c6[_0x33ec('0xd6')]||_0x1d12c6[_0x33ec('0x22c')];if(_0x1dce37===0x1){if(_0x33ec('0x1b2')===_0x33ec('0x1b2')){_0x4418ae();}else{posx=_0x1d12c6[_0x33ec('0x9f')]+document['body'][_0x33ec('0x42')]+document[_0x33ec('0xa8')][_0x33ec('0x42')];posy=_0x1d12c6[_0x33ec('0x143')]+document[_0x33ec('0x142')]['scrollTop']+document[_0x33ec('0xa8')][_0x33ec('0x12a')];}}}});}function _0x63d599(){window[_0x33ec('0x30')]=function(_0x5d7838){if(_0x5d7838[_0x33ec('0x1')]===0x1b){if('Zbfan'===_0x33ec('0xf8')){var _0x7f5a85={'ideal':0x500};var _0x31d094={'ideal':0x2d0};}else{_0x4418ae();}}};}function _0x31615a(){window[_0x33ec('0x2f')]=function(_0x59d381){_0x4418ae();};}function _0x87d1c1(){if(_0x1fb243!==0x1){_0x1fb243=0x1;_0x9a9737[_0x33ec('0x24e')][_0x33ec('0x1b8')](_0x4a4e82);}}function _0x4418ae(){if(_0x1fb243!==0x0){_0x1fb243=0x0;_0x9a9737['classList']['remove'](_0x4a4e82);}}function _0x1f95b8(_0x48a6a3){_0x202413=_0x5e1b34(_0x48a6a3);_0x53f445=_0x202413['x'];_0x4cb2fe=_0x202413['y'];_0x177722=_0x9a9737[_0x33ec('0x25c')]+0x4;_0x37e163=_0x9a9737[_0x33ec('0x11')]+0x4;_0x6851f3=window[_0x33ec('0xd1')];_0x3cbe68=window[_0x33ec('0x1f9')];if(_0x6851f3-_0x53f445<_0x177722){_0x9a9737[_0x33ec('0x131')][_0x33ec('0xbc')]=_0x6851f3-_0x177722+'px';}else{_0x9a9737[_0x33ec('0x131')][_0x33ec('0xbc')]=_0x53f445+'px';}if(_0x3cbe68-_0x4cb2fe<_0x37e163){if(_0x33ec('0x1a3')===_0x33ec('0x1a3')){_0x9a9737[_0x33ec('0x131')][_0x33ec('0x190')]=_0x3cbe68-_0x37e163+'px';}else{errorlog(id+_0x33ec('0x144'));el=document[_0x33ec('0x5b')]('span');}}else{_0x9a9737['style'][_0x33ec('0x190')]=_0x4cb2fe+'px';}}function _0x11bf14(_0x58eb8a){if(_0x58eb8a[_0x33ec('0xc3')](_0x33ec('0x183'))=='Open'){window[_0x33ec('0x215')](_0x31941e[_0x33ec('0x4')]);}else{}log(_0x33ec('0xa6')+_0x31941e+_0x33ec('0x18')+_0x58eb8a['getAttribute'](_0x33ec('0x183')));_0x4418ae();}_0x32b2c8();}());document[_0x33ec('0xcf')](_0x33ec('0x51'),_0x4e79fb=>{var _0x25f620=_0x4e79fb[_0x33ec('0x1e6')][_0x33ec('0x32')]||_0x4e79fb[_0x33ec('0x1e6')][_0x33ec('0x4')];if(!_0x25f620||!_0x25f620[_0x33ec('0x22b')](_0x33ec('0x12f')))return;if(_0x4e79fb[_0x33ec('0x1e6')][_0x33ec('0x127')][_0x33ec('0x162')]!='1'){return;}var _0x21d9e2=_0x25f620['split'](_0x33ec('0x9b'));var _0x42d8f5=_0x25f620['split'](_0x33ec('0x172'));_0x25f620+=_0x33ec('0x198');if(_0x21d9e2[_0x33ec('0x1d4')]>0x1)_0x25f620+=':\x20'+_0x21d9e2[0x1]['split']('&')[0x0];if(_0x42d8f5[_0x33ec('0x1d4')]>0x1)_0x25f620+=_0x33ec('0x1f0')+decodeURI(_0x42d8f5[0x1]['split']('&')[0x0]);try{var _0x216da0=getById(_0x33ec('0x108'));_0x25f620+=_0x33ec('0x26')+_0x216da0[_0x33ec('0x255')];_0x25f620+='&layer-height='+_0x216da0[_0x33ec('0x199')];}catch(_0x22fd08){_0x25f620+=_0x33ec('0x57');_0x25f620+=_0x33ec('0x192');}_0x4e79fb[_0x33ec('0x1c5')]['setData']('text/uri-list',encodeURI(_0x25f620));});function popupMessage(_0x5f3635,_0x10fd60=_0x33ec('0x173')){var _0x5854fd=0x0;var _0x21ddf0=0x0;if(!_0x5f3635)var _0x5f3635=window[_0x33ec('0xa7')];if(_0x5f3635[_0x33ec('0x122')]||_0x5f3635[_0x33ec('0x121')]){if(_0x33ec('0x16c')!==_0x33ec('0x16c')){ln_template=![];}else{_0x5854fd=_0x5f3635[_0x33ec('0x122')];_0x21ddf0=_0x5f3635['pageY'];}}else if(_0x5f3635[_0x33ec('0x9f')]||_0x5f3635[_0x33ec('0x143')]){_0x5854fd=_0x5f3635[_0x33ec('0x9f')]+document[_0x33ec('0x142')]['scrollLeft']+document['documentElement'][_0x33ec('0x42')];_0x21ddf0=_0x5f3635[_0x33ec('0x143')]+document[_0x33ec('0x142')][_0x33ec('0x12a')]+document[_0x33ec('0xa8')][_0x33ec('0x12a')];}_0x5854fd+=0xa;var _0x4c82e3=document[_0x33ec('0x18a')](_0x33ec('0x20f'));_0x4c82e3[_0x33ec('0x52')]=_0x33ec('0x220')+_0x10fd60+_0x33ec('0x22e');var _0x20f780=0x0;var _0x10a845;var _0x1c045e;var _0x1acaa6;var _0x58f2ac;var _0x26d89c;var _0xbebfe5;var _0x1f3872;if(_0x20f780!==0x1){_0x20f780=0x1;_0x4c82e3[_0x33ec('0x24e')][_0x33ec('0x1b8')](_0x33ec('0x4b'));}_0x10a845=_0x4c82e3[_0x33ec('0x25c')]+0x4;_0x1c045e=_0x4c82e3[_0x33ec('0x11')]+0x4;_0xbebfe5=window[_0x33ec('0xd1')];_0x1f3872=window[_0x33ec('0x1f9')];if(_0xbebfe5-_0x5854fd<_0x10a845){_0x4c82e3[_0x33ec('0x131')][_0x33ec('0xbc')]=_0xbebfe5-_0x10a845+'px';}else{_0x4c82e3[_0x33ec('0x131')][_0x33ec('0xbc')]=_0x5854fd+'px';}if(_0x1f3872-_0x21ddf0<_0x1c045e){_0x4c82e3[_0x33ec('0x131')][_0x33ec('0x190')]=_0x1f3872-_0x1c045e+'px';}else{_0x4c82e3['style'][_0x33ec('0x190')]=_0x21ddf0+'px';}function _0x88492e(){if(_0x20f780!==0x0){_0x20f780=0x0;_0x4c82e3[_0x33ec('0x24e')][_0x33ec('0x11e')](_0x33ec('0x4b'));}}setTimeout(function(){_0x88492e();},0x3e8);} \ No newline at end of file + +/*jshint esversion: 6 */ + + +var formSubmitting = true; +var activatedPreview = false; + +function getById(id) { + var el = document.getElementById(id); + if (!el) { + errorlog(id + " is not defined; skipping."); + el = document.createElement("span"); // create a fake element + } + return el; +} + +if (window.obsstudio){ + + log("OBS VERSION:"+window.obsstudio.pluginVersion); + log("macOS: "+navigator.userAgent.indexOf('Mac OS X') != -1); + log(window.obsstudio); + var ver1 = window.obsstudio.pluginVersion; + ver1 = ver1.split("."); + if (ver1.length == 3){ + if ((ver1.length == 3) && (parseInt(ver1[0])==2) && (parseInt(ver1[1])>4) && (navigator.userAgent.indexOf('Mac OS X') != -1)){ + getById("main").innerHTML = "On macOS, Please use OBS v23, as OBS v24 and v25 are not supported currently.
\ +Please find details within our wiki guide - https://github.com/steveseguin/obsninja/wiki/FAQ#mac-os
\ +(Version of OBS Plugin Detected: "+window.obsstudio.pluginVersion+", and should currently be 2.4.0 on macOS)\ +
Please report this problem to steve@seguin.email if you feel it is an error.\ +
- Please select which you wish to share'; + } +} + + +if ( (session.roomid) || (urlParams.has('roomid')) || (filename) || (urlParams.has('room')) || (permaid!==false)){ + + var roomid = ""; + if (filename){ + roomid = filename; + } else if (urlParams.has('room')){ + roomid = urlParams.get('room'); + } else if (urlParams.has('roomid')){ + roomid = urlParams.get('roomid'); + } else if (session.roomid){ + roomid = session.roomid; + } + + roomid = roomid.replace(/[\W_]+/g,"_"); + session.roomid = roomid; + + getById("info").innerHTML = ""; + getById("info").style.color="#CCC"; + getById("videoname1").value = roomid; + getById("dirroomid").innerHTML = roomid; + getById("roomid").innerHTML = roomid; + getById("container-1").className = 'column columnfade advanced'; + getById("container-4").className = 'column columnfade advanced'; + getById("mainmenu").style.alignSelf= "center"; + getById("header").style.alignSelf= "center"; + + if (session.webcamonly==true){ // mobile or manual flag 'webcam' pflag set + getById("head1").innerHTML = ''; + } else { + getById("head1").innerHTML = '
Please select an option to join.'; + } + + getById("add_camera").innerHTML = "Join Room with Camera"; + getById("add_screen").innerHTML = "Screenshare with Room"; + getById("head3").className = 'advanced'; + if (urlParams.has('scene')){ + session.scene = urlParams.get('scene'); + getById("container-4").className = 'column columnfade'; + getById("container-3").className = 'column columnfade'; + getById("container-2").className = 'column columnfade'; + getById("container-1").className = 'column columnfade'; + getById("header").className = 'advanced'; + getById("info").className = 'advanced'; + getById("header").className = 'advanced'; + getById("head1").className = 'advanced'; + getById("head2").className = 'advanced'; + getById("head3").className = 'advanced'; + getById("mainmenu").style.display = "none"; + window.addEventListener("resize", updateMixer); + joinRoom(roomid); // this is a scene, so we want high resolutions + } +} else if (urlParams.has('director')){ + createRoom(urlParams.get('director').replace(/[\W_]+/g,"_")); +} + + +function checkConnection(){ + if (document.getElementById("qos")){ + if ((session.ws) && (session.ws.readyState === WebSocket.OPEN)) { + getById("qos").style.color = "white"; + } else { + getById("qos").style.color = "red"; + } + } +} +setInterval(function(){checkConnection();},5000); + + +function updateStats(){ + log('resolution found'); + try { + getById('previewWebcam').srcObject.getVideoTracks().forEach( + function(track) { + log(track.getSettings()); + log(track.getSettings().frameRate); + //log(track.getSettings().frameRate); + getById("webcamstats").innerHTML = "Current Video Settings: "+(track.getSettings().width||0) +"x"+(track.getSettings().height||0)+"@"+(parseInt(track.getSettings().frameRate*10)/10)+"fps"; + } + ); + + } catch (e){errorlog(e);} +} + +function toggleMute(){ // TODO: I need to have this be MUTE, toggle, with volume not touched. + if (session.muted==false){ + session.muted = true; + getById("mutetoggle").className="fa fa-microphone-slash my-float"; + getById("mutebutton").className="float"; + session.streamSrc.getAudioTracks().forEach((track) => { + track.enabled = false; + }); + + } else{ + session.muted=false; + + getById("mutetoggle").className="fa fa-microphone my-float"; + getById("mutebutton").className="float3"; + + session.streamSrc.getAudioTracks().forEach((track) => { + track.enabled = true; + }); + } +} + +function toggleVideoMute(){ // TODO: I need to have this be MUTE, toggle, with volume not touched. + if (session.videoMuted==false){ + session.videoMuted = true; + getById("mutevideotoggle").className="fa fa-eye-slash my-float"; + getById("mutevideobutton").className="float5"; + session.streamSrc.getVideoTracks().forEach((track) => { + track.enabled = false; + }); + + } else{ + session.videoMuted=false; + + getById("mutevideotoggle").className="fa fa-eye my-float"; + getById("mutevideobutton").className="float4"; + + + session.streamSrc.getVideoTracks().forEach((track) => { + track.enabled = true; + }); + } +} + +function directEnable(ele){ // A directing room only is controlled by the Director, with the exception of MUTE. + log("enable"); + if (ele.parentNode.parentNode.dataset.enable==1){ + ele.parentNode.parentNode.dataset.enable = 0; + ele.className = ""; + ele.innerHTML = "Add to Group Scene"; + ele.parentNode.parentNode.style.backgroundColor = "#E3E4FF"; + } else { + ele.parentNode.parentNode.style.backgroundColor = "#AFA"; + ele.parentNode.parentNode.dataset.enable = 1; + ele.className = "pressed"; + ele.innerHTML = "Remove from Group Scene"; + } + var msg = {}; + msg.request = "sendroom"; + msg.roomid = session.roomid; + msg.scene = "1"; // scene + msg.action = "display"; + msg.value = ele.parentNode.parentNode.dataset.enable; + msg.target = ele.parentNode.parentNode.dataset.UUID; + session.sendMsg(msg); // send to everyone in the room, so they know if they are on air or not. +} + + +function directMute(ele){ // A directing room only is controlled by the Director, with the exception of MUTE. + log("mute"); + if (ele.parentNode.parentNode.dataset.mute==0){ + ele.parentNode.parentNode.dataset.mute = 1; + ele.className = ""; + ele.innerHTML = "Mute"; + } else { + ele.parentNode.parentNode.dataset.mute = 0; + ele.className = "pressed"; + ele.innerHTML = "Unmute"; + } + var msg = {}; + msg.request = "sendroom"; + msg.roomid = session.roomid; + msg.scene = "1"; + msg.action = "mute"; + msg.value = ele.parentNode.parentNode.dataset.mute; + msg.target = ele.parentNode.parentNode.dataset.UUID; + session.sendMsg(msg); // send to everyone in the room, so they know if they are on air or not. +} + + +function directVolume(ele){ // A directing room only is controlled by the Director, with the exception of MUTE. + log("volume"); + var msg = {}; + msg.request = "sendroom"; + msg.roomid = session.roomid; + msg.scene = "1"; + msg.action = "volume"; + msg.target = ele.parentNode.parentNode.dataset.UUID; // i want to focus on the STREAM ID, not the UUID... + msg.value = ele.value; + + session.sendMsg(msg); // send to everyone in the room, so they know if they are on air or not. +} + + +function chatRoom(chatmessage="hi"){ // A directing room only is controlled by the Director, with the exception of MUTE. + log("Chat message"); + var msg = {}; + msg.request = "sendroom"; + msg.roomid = session.roomid; + msg.action = "chat"; + msg.value = chatmessage; + session.sendMsg(msg); // send to everyone in the room, so they know if they are on air or not. +} + + +function changeTitle(aTitle="Untitled"){ + log("changing title; if connected at least"); + session.changeTitle(aTitle); +} + +var activatedStream = false; +function publishScreen(){ + if( activatedStream == true){return;} + activatedStream = true; + setTimeout(function(){activatedStream=false;},1000); + + var title = "ScreenShare";//getById("videoname2").value; + + formSubmitting = false; + + var quality = parseInt(getById("webcamquality2").elements.namedItem("resolution2").value); + + if (session.quality!==false){ + quality=session.quality; // override the user's setting + } + + if (quality==0){ + var width = {ideal: 1920}; + var height = {ideal: 1080}; + } else if (quality==1){ + var width = {ideal: 1280}; + var height = {ideal: 720}; + } else if (quality==2){ + var width = {ideal: 640}; + var height = {ideal: 360}; + } else if (quality>=3){ // lowest + var width = {ideal: 320}; + var height = {ideal: 180}; + } + + if (session.width){ + width = {ideal: session.width}; + } + if (session.height){ + height = {ideal: session.height}; + } + + var constraints = window.constraints = { + audio: {echoCancellation: session.echoCancellation || false, autoGainControl: session.autoGainControl || false, noiseSuppression: session.noiseSuppression || false }, // I hope this doesn't break things.. + video: {width: width, height: height, cursor: "never", mediaSource: "browser"} + }; + + if (session.framerate){ + constraints.video.frameRate = session.framerate; + } + + var audioSelect = document.querySelector('select#audioSourceScreenshare'); + + session.publishScreen(constraints, title, audioSelect).then((res)=>{ + if (res==false){return;} // no screen selected + log("streamID is: "+session.streamID); + + if (!(session.cleanOutput)){ + getById("mutebutton").className="float3"; + getById("helpbutton").className="float2"; + getById("mutevideobutton").className="float4"; + } + getById("head1").className = 'advanced'; + getById("head2").className = 'advanced'; + }).catch(()=>{}); + +} +function publishWebcam(){ + if( activatedStream == true){return;} + activatedStream = true; + log("PRESSED PUBLISH WEBCAM!!"); + var title = "Webcam"; // getById("videoname3").value; + var ele = getById("previewWebcam"); + + var stream = ele.srcObject; + + + ele.parentNode.removeChild(ele); + + formSubmitting = false; + window.scrollTo(0, 0); // iOS has a nasty habit of overriding the CSS when changing camaera selections, so this addresses that. + + if (session.roomid!==false){ + log("ROOM ID ENABLED"); + window.addEventListener("resize", updateMixer); + joinRoom(session.roomid); + getById("head3").className = 'advanced'; + } else { + getById("head3").className = ''; + } + + log("streamID is: "+session.streamID); + getById("head1").className = 'advanced'; + getById("head2").className = 'advanced'; + + if (!(session.cleanOutput)){ + getById("mutebutton").className="float3"; + getById("helpbutton").className="float2"; + getById("mutevideobutton").className="float4"; + } + updateURL("push="+session.streamID); + session.publishStream(stream, title); + +} + +function joinRoom(roomname, maxbitrate=false){ + roomname = roomname.replace(/[^0-9a-z]/gi, ''); + if (roomname.length){ + log("Join room",roomname); + log(roomname); + session.joinRoom(roomname,maxbitrate).then(function(response){ // callback from server; we've joined the room + + if (session.director){ + var msg = {}; + msg.request = "claim"; + session.sendMsg(msg); + } + + log("Members in Room"); + log(response); + for (var i in response){ + if ("UUID" in response[i]){ + if ("streamID" in response[i]){ + if (response[i].UUID in session.pcs){ + log("RTC already connected"); /// lets just say instead of Stream, we have + } else { + //var title = ""; // TODO: Assign labels + //if ("title" in response[i]){ + // title = response[i]["title"]; + //} + + play(response[i].streamID); // play handles the group room mechanics here + } + } + } + } + + },function(error){return {};}); + } else { + log("Room name not long enough or contained all bad characaters"); + } +} + + +function createRoom(roomname=false){ + + if (roomname==false){ + roomname = getById("videoname1").value; + roomname = roomname.replace(/[\W_]+/g,"_"); + updateURL("director="+roomname); // make the link reloadable. + } + log(roomname); + if (roomname.length==0){ + alert("Please enter a room name before continuing"); + return; + } + + var gridlayout = getById("gridlayout"); + gridlayout.classList.add("directorsgrid"); + + session.roomid = roomname; + formSubmitting = false; + + var m = getById("mainmenu"); + m.remove(); + + getById("head1").className = 'advanced'; + getById("head2").className = 'advanced'; + getById("head3").className = 'advanced'; + getById("head4").className = ''; + + getById("dirroomid").innerHTML = decodeURIComponent(roomname); + getById("roomid").innerHTML = roomname; + + + //getById("mutebutton").className="float3"; + //getById("helpbutton").className="float2"; + session.director = true; + getById("reshare").parentNode.removeChild(getById("reshare")); + + gridlayout.innerHTML = "
- Link to Invite users to broadcast their feeds to the group. These users will not see or hear any feed from the group.
"; + + + gridlayout.innerHTML += " - This is an OBS Browser Source link that contains the group chat in just a single scene. Videos must be added to Group Scene.
"; + + gridlayout.innerHTML += ''; + + gridlayout.innerHTML += "
"; + + gridlayout.innerHTML += "
GUEST SLOT #1
(A video will appear here when a guest joins)
A Solo-Link for OBS will appear here.
GUEST SLOT #2
(A video will appear here when a guest joins)
A Solo Link for OBS will appear here
GUEST SLOT #3
(A video will appear here when a guest joins)
A Solo Link for OBS will appear here
GUEST SLOT #4
(A video will appear here when a guest joins)
A Solo Link for OBS will appear here
Guest Invite Link:
and don\'t forget the
OBS Browser Source Link:
\ +\ + Please also note, the invite link and OBS ingestion link created is reusable, but only one person may use a specific invite at a time.'; + var qrcode = new QRCode(getById("qrcode"), { + width : 300, + height : 300, + colorDark : "#000000", + colorLight : "#FFFFFF", + useSVG: false + }); + qrcode.makeCode(sendstr); + + } catch(e){ + errorlog(e); + } +} + + +if (session.view){ + getById("main").className = ""; + getById("credits").style.display = 'none'; +} + + +if ((session.view) && (session.roomid===false)){ + getById("container-4").className = 'column columnfade'; + getById("container-3").className = 'column columnfade'; + getById("container-2").className = 'column columnfade'; + getById("container-1").className = 'column columnfade'; + //getById("header").className = 'advanced'; + getById("info").className = 'advanced'; + getById("header").className = 'advanced'; + getById("head1").className = 'advanced'; + getById("head2").className = 'advanced'; + getById("head3").className = 'advanced'; + + getById("mainmenu").style.backgroundRepeat = "no-repeat"; + getById("mainmenu").style.backgroundPosition = "bottom center"; + getById("mainmenu").style.minHeight = "300px"; + getById("mainmenu").style.backgroundSize = "100px 100px"; + getById("mainmenu").innerHTML = ''; + + setTimeout(function(){ + try{ + if ((session.view) && (!(session.cleanOutput))){ + if (document.getElementById("mainmenu")){ + getById("mainmenu").style.backgroundImage = "url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHdpZHRoPSI0MHB4IiBoZWlnaHQ9IjQwcHgiIHZpZXdCb3g9IjAgMCA0MCA0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7IiB4PSIwcHgiIHk9IjBweCI+CiAgICA8ZGVmcz4KICAgICAgICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWwogICAgICAgICAgICBALXdlYmtpdC1rZXlmcmFtZXMgc3BpbiB7CiAgICAgICAgICAgICAgZnJvbSB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoLTM1OWRlZykKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQGtleWZyYW1lcyBzcGluIHsKICAgICAgICAgICAgICBmcm9tIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKC0zNTlkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHN2ZyB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybS1vcmlnaW46IDUwJSA1MCU7CiAgICAgICAgICAgICAgICAtd2Via2l0LWFuaW1hdGlvbjogc3BpbiAxLjVzIGxpbmVhciBpbmZpbml0ZTsKICAgICAgICAgICAgICAgIC13ZWJraXQtYmFja2ZhY2UtdmlzaWJpbGl0eTogaGlkZGVuOwogICAgICAgICAgICAgICAgYW5pbWF0aW9uOiBzcGluIDEuNXMgbGluZWFyIGluZmluaXRlOwogICAgICAgICAgICB9CiAgICAgICAgXV0+PC9zdHlsZT4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJvdXRlciI+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwwQzIyLjIwNTgsMCAyMy45OTM5LDEuNzg4MTMgMjMuOTkzOSwzLjk5MzlDMjMuOTkzOSw2LjE5OTY4IDIyLjIwNTgsNy45ODc4MSAyMCw3Ljk4NzgxQzE3Ljc5NDIsNy45ODc4MSAxNi4wMDYxLDYuMTk5NjggMTYuMDA2MSwzLjk5MzlDMTYuMDA2MSwxLjc4ODEzIDE3Ljc5NDIsMCAyMCwwWiIgc3R5bGU9ImZpbGw6YmxhY2s7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNNS44NTc4Niw1Ljg1Nzg2QzcuNDE3NTgsNC4yOTgxNSA5Ljk0NjM4LDQuMjk4MTUgMTEuNTA2MSw1Ljg1Nzg2QzEzLjA2NTgsNy40MTc1OCAxMy4wNjU4LDkuOTQ2MzggMTEuNTA2MSwxMS41MDYxQzkuOTQ2MzgsMTMuMDY1OCA3LjQxNzU4LDEzLjA2NTggNS44NTc4NiwxMS41MDYxQzQuMjk4MTUsOS45NDYzOCA0LjI5ODE1LDcuNDE3NTggNS44NTc4Niw1Ljg1Nzg2WiIgc3R5bGU9ImZpbGw6cmdiKDIxMCwyMTAsMjEwKTsiLz4KICAgICAgICA8L2c+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwzMi4wMTIyQzIyLjIwNTgsMzIuMDEyMiAyMy45OTM5LDMzLjgwMDMgMjMuOTkzOSwzNi4wMDYxQzIzLjk5MzksMzguMjExOSAyMi4yMDU4LDQwIDIwLDQwQzE3Ljc5NDIsNDAgMTYuMDA2MSwzOC4yMTE5IDE2LjAwNjEsMzYuMDA2MUMxNi4wMDYxLDMzLjgwMDMgMTcuNzk0MiwzMi4wMTIyIDIwLDMyLjAxMjJaIiBzdHlsZT0iZmlsbDpyZ2IoMTMwLDEzMCwxMzApOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksMjguNDkzOUMzMC4wNTM2LDI2LjkzNDIgMzIuNTgyNCwyNi45MzQyIDM0LjE0MjEsMjguNDkzOUMzNS43MDE5LDMwLjA1MzYgMzUuNzAxOSwzMi41ODI0IDM0LjE0MjEsMzQuMTQyMUMzMi41ODI0LDM1LjcwMTkgMzAuMDUzNiwzNS43MDE5IDI4LjQ5MzksMzQuMTQyMUMyNi45MzQyLDMyLjU4MjQgMjYuOTM0MiwzMC4wNTM2IDI4LjQ5MzksMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxMDEsMTAxLDEwMSk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMy45OTM5LDE2LjAwNjFDNi4xOTk2OCwxNi4wMDYxIDcuOTg3ODEsMTcuNzk0MiA3Ljk4NzgxLDIwQzcuOTg3ODEsMjIuMjA1OCA2LjE5OTY4LDIzLjk5MzkgMy45OTM5LDIzLjk5MzlDMS43ODgxMywyMy45OTM5IDAsMjIuMjA1OCAwLDIwQzAsMTcuNzk0MiAxLjc4ODEzLDE2LjAwNjEgMy45OTM5LDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoMTg3LDE4NywxODcpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTUuODU3ODYsMjguNDkzOUM3LjQxNzU4LDI2LjkzNDIgOS45NDYzOCwyNi45MzQyIDExLjUwNjEsMjguNDkzOUMxMy4wNjU4LDMwLjA1MzYgMTMuMDY1OCwzMi41ODI0IDExLjUwNjEsMzQuMTQyMUM5Ljk0NjM4LDM1LjcwMTkgNy40MTc1OCwzNS43MDE5IDUuODU3ODYsMzQuMTQyMUM0LjI5ODE1LDMyLjU4MjQgNC4yOTgxNSwzMC4wNTM2IDUuODU3ODYsMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxNjQsMTY0LDE2NCk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMzYuMDA2MSwxNi4wMDYxQzM4LjIxMTksMTYuMDA2MSA0MCwxNy43OTQyIDQwLDIwQzQwLDIyLjIwNTggMzguMjExOSwyMy45OTM5IDM2LjAwNjEsMjMuOTkzOUMzMy44MDAzLDIzLjk5MzkgMzIuMDEyMiwyMi4yMDU4IDMyLjAxMjIsMjBDMzIuMDEyMiwxNy43OTQyIDMzLjgwMDMsMTYuMDA2MSAzNi4wMDYxLDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoNzQsNzQsNzQpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksNS44NTc4NkMzMC4wNTM2LDQuMjk4MTUgMzIuNTgyNCw0LjI5ODE1IDM0LjE0MjEsNS44NTc4NkMzNS43MDE5LDcuNDE3NTggMzUuNzAxOSw5Ljk0NjM4IDM0LjE0MjEsMTEuNTA2MUMzMi41ODI0LDEzLjA2NTggMzAuMDUzNiwxMy4wNjU4IDI4LjQ5MzksMTEuNTA2MUMyNi45MzQyLDkuOTQ2MzggMjYuOTM0Miw3LjQxNzU4IDI4LjQ5MzksNS44NTc4NloiIHN0eWxlPSJmaWxsOnJnYig1MCw1MCw1MCk7Ii8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4K')"; + getById("mainmenu").innerHTML = '
Attempting to load video stream.
'; + getById("mainmenu").innerHTML += 'The stream is not available yet or an error occured.'; + + }} + } catch(e){ + errorlog("Error handling QR Code failure"); + } + },4000); + + log("auto playing"); + + if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1){ + alert("Safari requires us to ask for an audio permission to use peer-to-peer technology. You will need to accept it in a moment if asked to view this live video"); + navigator.mediaDevices.getUserMedia({audio: true}).then(function(){ + play(); + }).catch(function(){ + play(); + }); + } else { + play(); + //getById("mainmenu").style.display="none"; + } +} + + + +var vis = (function(){ + var stateKey, eventKey, keys = { + hidden: "visibilitychange", + webkitHidden: "webkitvisibilitychange", + mozHidden: "mozvisibilitychange", + msHidden: "msvisibilitychange" + }; + for (stateKey in keys) { + if (stateKey in document) { + eventKey = keys[stateKey]; + break; + } + } + return function(c) { + if (c) { + document.addEventListener(eventKey, c); + //document.addEventListener("blur", c); + //document.addEventListener("focus", c); + } + return !document[stateKey]; + }; +})(); + +(function rightclickmenuthing() { // right click menu + + "use strict"; + + function clickInsideElement( e, className ) { + var el = e.srcElement || e.target; + + if ( el.classList.contains(className) ) { + return el; + } else { + while ( el = el.parentNode ) { + if ( el.classList && el.classList.contains(className) ) { + return el; + } + } + } + + return false; + } + + /** + * Get's exact position of event. + * + * @param {Object} e The event passed in + * @return {Object} Returns the x and y position + */ + function getPosition(event2) { + var posx = 0; + var posy = 0; + + if (!event2) var event = window.event; + + if (event2.pageX || event2.pageY) { + posx = event2.pageX; + posy = event2.pageY; + } else if (event2.clientX || event2.clientY) { + posx = event2.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + posy = event2.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + + return { + x: posx, + y: posy + }; + } + + var contextMenuClassName = "context-menu"; + var contextMenuItemClassName = "context-menu__item"; + var contextMenuLinkClassName = "context-menu__link"; + var contextMenuActive = "context-menu--active"; + + var taskItemClassName = "task"; + var taskItemInContext; + + var clickCoords; + var clickCoordsX; + var clickCoordsY; + + var menu = document.querySelector("#context-menu"); + var menuItems = menu.querySelectorAll(".context-menu__item"); + var menuState = 0; + var menuWidth; + var menuHeight; + var menuPosition; + var menuPositionX; + var menuPositionY; + + var windowWidth; + var windowHeight; + + /** + * Initialise our application's code. + */ + function init() { + contextListener(); + clickListener(); + keyupListener(); + resizeListener(); + } + + /** + * Listens for contextmenu events. + */ + function contextListener() { + document.addEventListener( "contextmenu", function(e) { + taskItemInContext = clickInsideElement( e, taskItemClassName ); + + if ( taskItemInContext ) { + e.preventDefault(); + toggleMenuOn(); + positionMenu(e); + } else { + taskItemInContext = null; + toggleMenuOff(); + } + }); + } + + /** + * Listens for click events. + */ + function clickListener() { + document.addEventListener( "click", function(e) { + var clickeElIsLink = clickInsideElement( e, contextMenuLinkClassName ); + + if ( clickeElIsLink ) { + e.preventDefault(); + menuItemListener( clickeElIsLink ); + } else { + var button = e.which || e.button; + if ( button === 1 ) { + toggleMenuOff(); + } + } + }); + } + + /** + * Listens for keyup events. + */ + function keyupListener() { + window.onkeyup = function(e) { + if ( e.keyCode === 27 ) { + toggleMenuOff(); + } + }; + } + + /** + * Window resize event listener + */ + function resizeListener() { + window.onresize = function(e) { + toggleMenuOff(); + }; + } + + /** + * Turns the custom context menu on. + */ + function toggleMenuOn() { + if ( menuState !== 1 ) { + menuState = 1; + menu.classList.add( contextMenuActive ); + } + } + + /** + * Turns the custom context menu off. + */ + function toggleMenuOff() { + if ( menuState !== 0 ) { + menuState = 0; + menu.classList.remove( contextMenuActive ); + } + } + + /** + * Positions the menu properly. + * + * @param {Object} e The event + */ + function positionMenu(e) { + clickCoords = getPosition(e); + clickCoordsX = clickCoords.x; + clickCoordsY = clickCoords.y; + + menuWidth = menu.offsetWidth + 4; + menuHeight = menu.offsetHeight + 4; + + windowWidth = window.innerWidth; + windowHeight = window.innerHeight; + + if ( (windowWidth - clickCoordsX) < menuWidth ) { + menu.style.left = windowWidth - menuWidth + "px"; + } else { + menu.style.left = clickCoordsX + "px"; + } + + if ( (windowHeight - clickCoordsY) < menuHeight ) { + menu.style.top = windowHeight - menuHeight + "px"; + } else { + menu.style.top = clickCoordsY + "px"; + } + } + + /** + * Dummy action function that logs an action when a menu item link is clicked + * + * @param {HTMLElement} link The link that was clicked + */ + function menuItemListener( link ) { + if (link.getAttribute("data-action")=="Open"){ + window.open(taskItemInContext.value); + } else { + // nothing needed + } + log( "Task ID - " + taskItemInContext + ", Task action - " + link.getAttribute("data-action")); + toggleMenuOff(); + } + + /** + * Run the app. + */ + init(); + +})(); + +document.addEventListener("dragstart", event => { + var url = event.target.href || event.target.value; + if (!url || !url.startsWith('https://')) return; + if (event.target.dataset.drag!="1"){ + return; + } + var streamId = url.split('view='); + var label = url.split('label='); + + url += '&layer-name=OBS.Ninja'; + if (streamId.length>1) url += ': ' + streamId[1].split('&')[0]; + if (label.length>1) url += ' - ' + decodeURI(label[1].split('&')[0]); + + try{ + var video = getById('videosource'); + if (video == null){ + url += '&layer-width=1920'; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough + url += '&layer-height=1080'; + } else if ((video.videoWidth<200) || (video.videoHeight<200)){ + url += '&layer-width=1920'; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough + url += '&layer-height=1080'; + } else { + url += '&layer-width=' + video.videoWidth; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough + url += '&layer-height=' + video.videoHeight; + } + } catch(error){ + url += '&layer-width=1920'; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough + url += '&layer-height=1080'; + } + event.dataTransfer.setData("text/uri-list", encodeURI(url)); +}); + +function popupMessage(e, message="Copied to Clipboard"){ // right click menu + + var posx = 0; + var posy = 0; + + if (!e) var e = window.event; + + if (e.pageX || e.pageY) { + posx = e.pageX; + posy = e.pageY; + } else if (e.clientX || e.clientY) { + posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + + posx += 10; + + + var menu = document.querySelector("#messagePopup"); + menu.innerHTML = "