Advertisement
Guest User

Untitled

a guest
May 24th, 2019
533
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 36.52 KB | None | 0 0
  1.  
  2. <!DOCTYPE html>
  3. <html>
  4.     <head>
  5.         <meta charset="UTF-8">
  6.         <title>UV4L WebRTC</title>
  7.         <!--script src="https://raw.githubusercontent.com/dorukeker/gyronorm.js/master/dist/gyronorm.complete.min.js" async></script-->
  8.         <!--script src="https://rawgit.com/dorukeker/gyronorm.js/master/dist/gyronorm.complete.min.js" async></script-->
  9.         <script type="text/javascript">
  10.                 try {
  11.                     var xmlHttp = new XMLHttpRequest();
  12.                     xmlHttp.onreadystatechange = function () {
  13.                         if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
  14.                            callback(xmlHttp.responseText);
  15.                         }
  16.                     };
  17.                     xmlHttp.open("GET", theUrl, true); // true for asynchronous
  18.                     xmlHttp.send(null);
  19.                 } catch (e) {
  20.                     console.error(e);
  21.                 }
  22.             }
  23.                 var srcUrl = "https://rawgit.com/dorukeker/gyronorm.js/master/dist/gyronorm.complete.min.js"
  24.                 httpGetAsync(srcUrl, function (text) {
  25.                     var script = document.createElement("script");
  26.                     script.setAttribute("src", srcUrl);
  27.                     document.getElementsByTagName("head")[0].appendChild(script);
  28.                 });
  29.             }
  30.                 document.getElementById('signalling_server').value = signalling_server_address;
  31.                 var cast_not_allowed = !('MediaSource' in window) || location.protocol !== "https:";
  32.                 if (cast_not_allowed || !isFirefox) {
  33.                     if (document.getElementById('cast_tab'))
  34.                         document.getElementById('cast_tab').disabled = true;
  35.                     if (cast_not_allowed) { // chrome supports if run with --enable-usermedia-screen-capturing
  36.                         document.getElementById('cast_screen').disabled = true;
  37.                     }
  38.                     document.getElementById('cast_window').disabled = true;
  39.                     document.getElementById('cast_application').disabled = true;
  40.                     document.getElementById('note2').style.display = "none";
  41.                     document.getElementById('note4').style.display = "none";
  42.                 } else {
  43.                     document.getElementById('note1').style.display = "none";
  44.                     document.getElementById('note3').style.display = "none";
  45.                 }
  46.                 addGyronormScript();
  47.             });
  48.             var ws = null;
  49.             var pc;
  50.             var gn;
  51.             var datachannel, localdatachannel;
  52.             var audio_video_stream;
  53.             var recorder = null;
  54.             var recordedBlobs;
  55.             var pcConfig = {"iceServers": [
  56.                     {"urls": ["stun:stun.l.google.com:19302", "stun:" + signalling_server_hostname + ":3478"]}
  57.                 ]};
  58.             var pcOptions = {
  59.                 optional: [
  60.                     // Deprecated:
  61.                     //{RtpDataChannels: false},
  62.                     //{DtlsSrtpKeyAgreement: true}
  63.                 ]
  64.             };
  65.             var mediaConstraints = {
  66.                 optional: [],
  67.                 mandatory: {
  68.                     OfferToReceiveAudio: true,
  69.                     OfferToReceiveVideo: true
  70.                 }
  71.             };
  72.             var keys = [];
  73.             var trickle_ice = true;
  74.             var remoteDesc = false;
  75.             var iceCandidates = [];
  76.             function createPeerConnection() {
  77.                 try {
  78.                     var pcConfig_ = pcConfig;
  79.                     try {
  80.                         ice_servers = document.getElementById('ice_servers').value;
  81.                         if (ice_servers) {
  82.                             pcConfig_.iceServers = JSON.parse(ice_servers);
  83.                         }
  84.                     } catch (e) {
  85.                         alert(e + "\nExample: "
  86.                                 + '\n[ {"urls": "stun:stun1.example.net"}, {"urls": "turn:turn.example.org", "username": "user", "credential": "myPassword"} ]'
  87.                                 + "\nContinuing with built-in RTCIceServer array");
  88.                     }
  89.                     console.log(JSON.stringify(pcConfig_));
  90.                     pc = new RTCPeerConnection(pcConfig_, pcOptions);
  91.                     pc.onicecandidate = onIceCandidate;
  92.                     if ('ontrack' in pc) {
  93.                         pc.ontrack = onTrack;
  94.                     } else {
  95.                         pc.onaddstream = onRemoteStreamAdded; // deprecated
  96.                     }
  97.                     pc.onremovestream = onRemoteStreamRemoved;
  98.                     pc.ondatachannel = onDataChannel;
  99.                     console.log("peer connection successfully created!");
  100.                 } catch (e) {
  101.                     console.error("createPeerConnection() failed");
  102.                 }
  103.             }
  104.  
  105.             function onDataChannel(event) {
  106.                 console.log("onDataChannel()");
  107.                 datachannel = event.channel;
  108.  
  109.                 event.channel.onopen = function () {
  110.                     console.log("Data Channel is open!");
  111.                     document.getElementById('datachannels').disabled = false;
  112.                 };
  113.  
  114.                 event.channel.onerror = function (error) {
  115.                     console.error("Data Channel Error:", error);
  116.                 };
  117.  
  118.                 event.channel.onmessage = function (event) {
  119.                     console.log("Got Data Channel Message:", event.data);
  120.                     document.getElementById('datareceived').value = event.data;
  121.                 };
  122.  
  123.                 event.channel.onclose = function () {
  124.                     datachannel = null;
  125.                     document.getElementById('datachannels').disabled = true;
  126.                     console.log("The Data Channel is Closed");
  127.                 };
  128.             }
  129.                 iceCandidates.forEach(function (candidate) {
  130.                     pc.addIceCandidate(candidate,
  131.                         function () {
  132.                             console.log("IceCandidate added: " + JSON.stringify(candidate));
  133.                         },
  134.                         function (error) {
  135.                             console.error("addIceCandidate error: " + error);
  136.                         }
  137.                     );
  138.                 });
  139.                 iceCandidates = [];
  140.             }
  141.            
  142.                 console.log("Remote track!");
  143.                 var remoteVideoElement = document.getElementById('remote-video');
  144.                 remoteVideoElement.srcObject = event.streams[0];
  145.                 //remoteVideoElement.play();
  146.             }
  147.                 var remoteVideoElement = document.getElementById('remote-video');
  148.                 remoteVideoElement.srcObject = null;
  149.                 remoteVideoElement.src = ''; // TODO: remove
  150.             }
  151.             function start() {
  152.                 if ("WebSocket" in window) {
  153.                     document.getElementById("stop").disabled = false;
  154.                     document.getElementById("start").disabled = true;
  155.                     document.documentElement.style.cursor = 'wait';
  156.                     var server = document.getElementById("signalling_server").value.toLowerCase();
  157.  
  158.                     var protocol = location.protocol === "https:" ? "wss:" : "ws:";
  159.                     ws = new WebSocket(protocol + '//' + server + '/stream/webrtc');
  160.  
  161.                     function call(stream) {
  162.                         iceCandidates = [];
  163.                         remoteDesc = false;
  164.                         createPeerConnection();
  165.                         if (stream) {
  166.                             pc.addStream(stream);
  167.                         }
  168.                         var request = {
  169.                             what: "call",
  170.                             options: {
  171.                                 force_hw_vcodec: document.getElementById("remote_hw_vcodec").checked,
  172.                                 vformat: document.getElementById("remote_vformat").value,
  173.                                 trickle_ice: trickleice_selection()
  174.                             }
  175.                         };
  176.                         ws.send(JSON.stringify(request));
  177.                         console.log("call(), request=" + JSON.stringify(request));
  178.                     }
  179.  
  180.                     ws.onopen = function () {
  181.                         console.log("onopen()");
  182.  
  183.                         audio_video_stream = null;
  184.                         var cast_mic = document.getElementById("cast_mic").checked;
  185.                         var cast_tab = document.getElementById("cast_tab") ? document.getElementById("cast_tab").checked : false;
  186.                         var cast_camera = document.getElementById("cast_camera").checked;
  187.                         var cast_screen = document.getElementById("cast_screen").checked;
  188.                         var cast_window = document.getElementById("cast_window").checked;
  189.                         var cast_application = document.getElementById("cast_application").checked;
  190.                         var echo_cancellation = document.getElementById("echo_cancellation").checked;
  191.                         var localConstraints = {};
  192.                         if (cast_mic) {
  193.                             if (echo_cancellation)
  194.                                 localConstraints['audio'] = isFirefox ? {echoCancellation: true} : {optional: [{echoCancellation: true}]};
  195.                             else
  196.                                 localConstraints['audio'] = isFirefox ? {echoCancellation: false} : {optional: [{echoCancellation: false}]};
  197.                         } else if (cast_tab) {
  198.                             localConstraints['audio'] = {mediaSource: "audioCapture"};
  199.                         } else {
  200.                             localConstraints['audio'] = false;
  201.                         }
  202.                         if (cast_camera) {
  203.                             localConstraints['video'] = true;
  204.                         } else if (cast_screen) {
  205.                             if (isFirefox) {
  206.                                 localConstraints['video'] = {frameRate: {ideal: 30, max: 30},
  207.                                     //width: {min: 640, max: 960},
  208.                                     //height: {min: 480, max: 720},
  209.                                     mozMediaSource: "screen",
  210.                                     mediaSource: "screen"};
  211.                             } else {
  212.                                 // chrome://flags#enable-usermedia-screen-capturing
  213.                                 document.getElementById("cast_mic").checked = false;
  214.                                 localConstraints['audio'] = false; // mandatory for chrome
  215.                                 localConstraints['video'] = {'mandatory': {'chromeMediaSource':'screen'}};
  216.                             }
  217.                         } else if (cast_window)
  218.                             localConstraints['video'] = {frameRate: {ideal: 30, max: 30},
  219.                                 //width: {min: 640, max: 960},
  220.                                 //height: {min: 480, max: 720},
  221.                                 mozMediaSource: "window",
  222.                                 mediaSource: "window"};
  223.                         else if (cast_application)
  224.                             localConstraints['video'] = {frameRate: {ideal: 30, max: 30},
  225.                                 //width: {min: 640, max: 960},
  226.                                 //height:  {min: 480, max: 720},
  227.                                 mozMediaSource: "application",
  228.                                 mediaSource: "application"};
  229.                         else
  230.                             localConstraints['video'] = false;
  231.                     };
  232.  
  233.                 } else {
  234.                     alert("Sorry, this browser does not support WebSockets.");
  235.                 }
  236.             }
  237.  
  238.             function stop() {
  239.                 if (datachannel) {
  240.                     console.log("closing data channels");
  241.                     datachannel.close();
  242.                     datachannel = null;
  243.                     document.getElementById('datachannels').disabled = true;
  244.                 }
  245.                 if (localdatachannel) {
  246.                     console.log("closing local data channels");
  247.                     localdatachannel.close();
  248.                     localdatachannel = null;
  249.                 }
  250.                 if (audio_video_stream) {
  251.                     try {
  252.                         if (audio_video_stream.getVideoTracks().length)
  253.                             audio_video_stream.getVideoTracks()[0].stop();
  254.                         if (audio_video_stream.getAudioTracks().length)
  255.                             audio_video_stream.getAudioTracks()[0].stop();
  256.                         audio_video_stream.stop(); // deprecated
  257.                     } catch (e) {
  258.                         for (var i = 0; i < audio_video_stream.getTracks().length; i++)
  259.                            audio_video_stream.getTracks()[i].stop();
  260.                    }
  261.                    audio_video_stream = null;
  262.                }
  263.                stop_record();
  264.                document.getElementById('remote-video').srcObject = null;
  265.                document.getElementById('local-video').srcObject = null;
  266.                document.getElementById('remote-video').src = ''; // TODO; remove
  267.                document.getElementById('local-video').src = ''; // TODO: remove
  268.                if (pc) {
  269.                    pc.close();
  270.                    pc = null;
  271.                }
  272.                if (ws) {
  273.                    ws.close();
  274.                    ws = null;
  275.                }
  276.                document.getElementById("stop").disabled = true;
  277.                document.getElementById("start").disabled = false;
  278.                document.documentElement.style.cursor = 'default';
  279.            }
  280.                var old = document.getElementById(id).checked;
  281.                var elements = document.getElementsByName(name);
  282.                for (var i = 0; i < elements.length; i++) {
  283.                    elements[i].checked = false;
  284.                }
  285.                document.getElementById(id).checked = old ? true : false;
  286.                /*
  287.                 // Disable video hw codec. Not supported at the moment when casting.
  288.                 if (name === 'video_cast') {
  289.                 unselect_remote_hw_vcodec();
  290.                 }
  291.                 */
  292.            }
  293.  
  294.            function send_message() {
  295.                var msg = document.getElementById('datamessage').value;
  296.                datachannel.send(ms);
  297.                console.log("message sent: ", msg);
  298.            }
  299.  
  300.            function create_localdatachannel() {
  301.                if (pc && localdatachannel)
  302.                    return;
  303.                localdatachannel = pc.createDataChannel('datachannel');
  304.                localdatachannel.onopen = function(event) {
  305.                    if (localdatachannel.readyState === "open") {
  306.                        localdatachannel.send("datachannel created!");
  307.                    }
  308.                };
  309.                console.log("data channel created");
  310.            }
  311.  
  312.            function close_localdatachannel() {
  313.                if (localdatachannel) {
  314.                    localdatachannel.close();
  315.                    localdatachannel = null;
  316.                }
  317.                console.log("local data channel closed");
  318.            }
  319.  
  320.            function getKeycodesArray(arr) {
  321.                var newArr = new Array();
  322.                for (var i = 0; i < arr.length; i++) {
  323.                    if (typeof arr[i] == "number") {
  324.                        newArr[newArr.length] = arr[i];
  325.                    }
  326.                }
  327.                return newArr;
  328.            }
  329.  
  330.            function convertKeycodes(arr) {
  331.                var map = {
  332.                    /*Space*/ 32: 57,
  333.                    /*Enter*/13: 28,
  334.                    /*Tab*/ 9: 15,
  335.                    /*Esc*/27: 1,
  336.                    /*Backspace*/8: 14,
  337.                    /*Shift*/16: 42,
  338.                    /*Control*/ 17: 29,
  339.                    /*Alt Left*/ 18: 56,
  340.                    /*Alt Right*/ 225: 100,
  341.                    /*Caps Lock*/ 20: 58,
  342.                    /*Num Lock*/ 144: 69,
  343.                    /*a*/ 65: 30,
  344.                    /*b*/ 66: 48,
  345.                    /*c*/ 67: 46,
  346.                    /*d*/ 68: 32,
  347.                    /*e*/ 69: 18,
  348.                    /*f*/ 70: 33,
  349.                    /*g*/ 71: 34,
  350.                    /*h*/ 72: 35,
  351.                    /*i*/ 73: 23,
  352.                    /*j*/ 74: 36,
  353.                    /*k*/ 75: 37,
  354.                    /*l*/ 76: 38,
  355.                    /*m*/ 77: 50,
  356.                    /*n*/ 78: 49,
  357.                    /*o*/ 79: 24,
  358.                    /*p*/ 80: 25,
  359.                    /*q*/ 81: 16,
  360.                    /*r*/ 82: 19,
  361.                    /*s*/ 83: 31,
  362.                    /*t*/ 84: 20,
  363.                    /*u*/ 85: 22,
  364.                    /*v*/ 86: 47,
  365.                    /*w*/ 87: 17,
  366.                    /*x*/ 88: 45,
  367.                    /*y*/ 89: 21,
  368.                    /*z*/ 90: 44,
  369.                    /*1*/ 49: 2,
  370.                    /*2*/ 50: 3,
  371.                    /*3*/ 51: 4,
  372.                    /*4*/ 52: 5,
  373.                    /*5*/ 53: 6,
  374.                    /*6*/ 54: 7,
  375.                    /*7*/ 55: 8,
  376.                    /*8*/ 56: 9,
  377.                    /*9*/ 57: 10,
  378.                    /*0*/ 48: 11,
  379.                    /*; (firefox)*/ 59: 39,
  380.                    /*; (chrome)*/ 186: 39,
  381.                    /*=(firefox)*/ 61: 13,
  382.                    /*=(chrome)*/ 187: 13,
  383.                    /*,*/ 188: 51,
  384.                    /*-(minus in firefox)*/ 173: 12,
  385.                    /*-(dash in chrome)*/ 189: 12,
  386.                    /*.*/ 190: 52,
  387.                    /*/*/ 191: 53,
  388.                    /*`*/ 192: 41,
  389.                    /*{*/ 219: 26,
  390.                    /*\*/ 220: 43,
  391.                    /*}*/ 221: 27,
  392.                    /*'*/ 222: 40,
  393.                    /*left-arrow*/ 37: 105,
  394.                    /*up-arrow*/ 38: 103,
  395.                    /*right-arrow*/ 39: 106,
  396.                    /*down-arrow*/ 40: 108,
  397.                    /*Insert*/ 45: 110,
  398.                    /*Delete*/ 46: 111,
  399.                    /*Home*/ 36: 102,
  400.                    /*End*/ 35: 107,
  401.                    /*Page Up*/ 33: 104,
  402.                    /*Page Down*/ 34: 109,
  403.                    /*F1 */ 112: 59,
  404.                    /*F2 */ 113: 60,
  405.                    /*F3 */ 114: 61,
  406.                    /*F4 */ 115: 62,
  407.                    /*F5 */ 116: 63,
  408.                    /*F6 */ 117: 64,
  409.                    /*F7 */ 118: 65,
  410.                    /*F8 */ 119: 66,
  411.                    /*F9 */ 120: 67,
  412.                    /*F10 */ 121: 68,
  413.                    /*F11 */ 122: 87,
  414.                    /*F12 */ 123: 88,
  415.                    /*. Del*/ 110: 83,
  416.                    /*0 Ins*/ 96: 82,
  417.                    /*1 End*/ 97: 79,
  418.                    /*2 down-arrow*/ 98: 80,
  419.                    /*3 Pg Dn*/ 99: 81,
  420.                    /*4 left-arrow*/ 100: 75,
  421.                    /*5*/ 101: 76,
  422.                    /*6 right-arrow*/ 102: 77,
  423.                     /*7 Home*/  103: 71,
  424.                    /*8 up-arrow*/ 104: 72,
  425.                    /*9 Pg Up*/ 105: 73,
  426.                    /*+*/ 107: 78,
  427.                    /*-*/ 109: 74,
  428.                    /***/ 106: 55,
  429.                    /*/*/ 111: 98,
  430.                    /*Keypad Enter*/ 13: 28
  431.                };
  432.                var convertedKeys = [];
  433.                arr.forEach(function (a) {
  434.                    if (map[a] !== undefined)
  435.                        convertedKeys.push(map[a]);
  436.                    //else
  437.                    //    convertedKeys.push(a);
  438.                });
  439.                return convertedKeys;
  440.            }
  441.            function convertCharCode(ch) {
  442.                var arr = [];
  443.                if (ch >= 48 && ch <= 57) { /* 0..9 */
  444.                    arr[0] = ch;
  445.                     arr = convertKeycodes(arr);
  446.                 } else if (ch >= 97 && ch <= 122) { /* a..z */
  447.                    arr[0] = ch - 32;
  448.                     arr = convertKeycodes(arr);
  449.                 } else if (ch >= 65 && ch <= 90) { /* A..Z */
  450.                    arr[0] = 16;
  451.                     arr[1] = ch;
  452.                     arr = convertKeycodes(arr);
  453.                 } else if (ch == 46) { // .
  454.                     arr[0] = 52;
  455.                 } else if (ch == 33) { // !
  456.                     arr[0] = 42;
  457.                     arr[1] = 2;
  458.                 } else if (ch == 63) { // ?
  459.                     arr[0] = 42;
  460.                     arr[1] = 53;
  461.                 } else if (ch == 44) { // ,
  462.                     arr[0] = 51;
  463.                 } else if (ch == 34) { // "
  464.                     arr[0] = 42;
  465.                     arr[1] = 40;
  466.                 } else if (ch == 39) { // '
  467.                     arr[0] = 40;
  468.                 } else if (ch == 58) { // :
  469.                     arr[0] = 42;
  470.                     arr[1] = 39;
  471.                 } else if (ch == 40) { // (
  472.                     arr[0] = 42;
  473.                     arr[1] = 10;
  474.                 } else if (ch == 41) { // )
  475.                     arr[0] = 42;
  476.                     arr[1] = 11;
  477.                 } else if (ch == 126) { // ~
  478.                     arr[0] = 42;
  479.                     arr[1] = 41;
  480.                 } else if (ch == 42) { // *
  481.                     arr[0] = 42;
  482.                     arr[1] = 9;
  483.                 } else if (ch == 45) { // -
  484.                     arr[0] = 12;
  485.                 } else if (ch == 47) { // /
  486.                     arr[0] = 53;
  487.                 } else if (ch == 64) { // @
  488.                     arr[0] = 42;
  489.                     arr[1] = 3;
  490.                 } else if (ch == 95) { // _
  491.                     arr[0] = 42;
  492.                     arr[1] = 12;
  493.                 }
  494.                 return arr;
  495.             }
  496.  
  497.             function toKeyCode() {
  498.                 var getCharCode = function (str) {
  499.                     return str.charCodeAt(str.length - 1);
  500.                 };
  501.                 var cc = getCharCode(this.value);
  502.                 document.getElementById("datamessage").removeEventListener("keyup", toKeyCode);
  503.                 this.value = "";
  504.                 var keysArray = convertCharCode(cc);
  505.                 if (datachannel && document.getElementById('keypresssend').checked && keysArray.length) {
  506.                    var keycodes = {
  507.                        keycodes: keysArray
  508.                    };
  509.                     datachannel.send(JSON.stringify(keycodes));
  510.                 }
  511.             }
  512.             ;
  513.  
  514.             function keydown(e) {
  515.                 if (e.keyCode == 0 || e.keyCode == 229) { // on mobile
  516.                     return;
  517.                 }
  518.                 e.preventDefault();
  519.                 e.stopPropagation();
  520.                 e.stopImmediatePropagation();
  521.                 keys[e.keyCode] = e.keyCode;
  522.                 for (var i = keys.length; i >= 0; i--) {
  523.                     if (keys[i] !== 16 && keys[i] !== 17 && keys[i] !== 18 && keys[i] !== 225 && keys[i] !== e.keyCode)
  524.                        keys[i] = false;
  525.                 }
  526.                 var keysArray = convertKeycodes(getKeycodesArray(keys));
  527.                 if (datachannel && document.getElementById('keypresssend').checked && keysArray.length) {
  528.                    var keycodes = {
  529.                        keycodes: keysArray
  530.                    };
  531.                     datachannel.send(JSON.stringify(keycodes));
  532.                 }
  533.             }
  534.             ;
  535.  
  536.             function keyup(e) {
  537.                 if (e.keyCode == 0 || e.keyCode == 229) { // on mobile
  538.                     document.getElementById("datamessage").addEventListener("keyup", toKeyCode);
  539.                     return;
  540.                 }
  541.                 e.preventDefault();
  542.                 e.stopPropagation();
  543.                 e.stopImmediatePropagation();
  544.                 keys[e.keyCode] = false;
  545.             }
  546.             ;
  547.  
  548.             function keypresssend_selection() {
  549.                 if (document.getElementById('keypresssend').checked) {
  550.                     window.addEventListener('keydown', keydown, true);
  551.                     window.addEventListener('keyup', keyup, true);
  552.                 } else {
  553.                     keys = [];
  554.                     window.removeEventListener('keydown', keydown, true);
  555.                     window.removeEventListener('keyup', keyup, true);
  556.                 }
  557.             }
  558.  
  559.             function trickleice_selection() {
  560.                 if (document.getElementById('trickleice').value === "false") {
  561.                     trickle_ice = false;
  562.                 } else if (document.getElementById('trickleice').value === "true") {
  563.                     trickle_ice = true;
  564.                 } else {
  565.                     trickle_ice = null;
  566.                 }
  567.                 return trickle_ice;
  568.             }
  569.  
  570.             window.onload = function () {
  571.                 if (window.MediaRecorder === undefined) {
  572.                     document.getElementById('record').disabled = true;
  573.                 }
  574.                 if (false) {
  575.                     start();
  576.                 }
  577.             };
  578.  
  579.             window.onbeforeunload = function () {
  580.                 if (ws) {
  581.                     ws.onclose = function () {}; // disable onclose handler first
  582.                     stop();
  583.                 }
  584.             };
  585.  
  586.         </script>
  587.         <style>
  588.             #container {
  589.                 display: flex;
  590.                 flex-flow: row nowrap;
  591.                 align-items: flex-end;
  592.             }
  593.             video {
  594.                 background: #eee none repeat scroll 0 0;
  595.                 border: 1px solid #aaa;
  596.             }
  597.             .overlayWrapper {
  598.                 position: relative;
  599.             }
  600.             .overlayWrapper .overlay {
  601.                 position: absolute;
  602.                 top: 0;
  603.                 left: 5px;
  604.             }
  605.             p {
  606.                 margin: 0.125em;
  607.             }
  608.             small {
  609.                 font-size: smaller;
  610.             }
  611.         </style>
  612.     </head>
  613.     <body>
  614.         <h1>
  615.             <span>WebRTC two-way Audio/Video/Data Intercom & Recorder</span>
  616.        </h1>
  617.        <h3 style="color:red" >
  618.            <span>WARNING! Some browsers do not allow to access local media on insecure origins.</span>
  619.            <span>Consider switching the UV4L Streaming Server to secure HTTPS instead.</span>
  620.        </h3>
  621.        <div id="container">
  622.            <div class="overlayWrapper">
  623.                <video id="remote-video" autoplay="" width="640" height="480">
  624.                    Your browser does not support the video tag.
  625.                </video>
  626.                <p class="overlay">remote</p>
  627.            </div>
  628.            <div class="overlayWrapper">
  629.                <video id="local-video" autoplay="" width="320" height="240">
  630.                    Your browser does not support the video tag.
  631.                </video>
  632.                <p class="overlay">local</p>
  633.            </div>
  634.        </div>
  635.        <div id="controls">
  636.            <button type=button id="pause" onclick="pause();" title="pause or resume local player">Pause/Resume</button>
  637.             <button type=button id="mute" onclick="mute();" title="mute or unmute remote audio source">Mute/Unmute</button>
  638.             <button type=button id="fullscreen" onclick="fullscreen();">Fullscreen</button>
  639.             <button type=button id="record" onclick="start_stop_record();" title="start or stop recording audio/video">Start Recording</button>
  640.         </div>
  641.         <fieldset>
  642.             <legend><b>Remote peer options</b></legend>
  643.             <div>
  644.                 <span>Video:</span>
  645.                 <label><input type="checkbox" onclick="remote_hw_vcodec_selection();"  id="remote_hw_vcodec" name="remote_hw_vcodec" value="remote_hw_vcodec" title="try to force the use of the hardware codec for both encoding and decoding if enabled and supported">force use of hardware codec for</label>
  646.                 <select id="remote_vformat" name="remote_vformat" onclick="remote_hw_vcodec_format_selection();" title="available resolutions and frame rates at the min., max. and start configured bitrates for adaptive streaming which will be scaled from the base 720p 30fps">
  647.                     <option value="5">320x240 15 fps</option>
  648.                     <option value="10">320x240 30 fps</option>
  649.                     <option value="20">352x288 30 fps</option>
  650.                     <option value="25">640x480 15 fps</option>
  651.                     <option value="30">640x480 30 fps</option>
  652.                     <option value="35">800x480 30 fps</option>
  653.                     <option value="40">960x720 30 fps</option>
  654.                     <option value="50">1024x768 30 fps</option>
  655.                     <option value="55">1280x720 15 fps</option>
  656.                     <option value="60" selected="selected">1280x720 30 fps, kbps min.800 max.4000 start1200</option>
  657.                     <option value="63">1280x720 60 fps</option>
  658.                     <option value="65">1280x768 15 fps</option>
  659.                     <option value="70">1280x768 30 fps</option>
  660.                     <option value="75">1536x768 30 fps</option>
  661.                     <option value="80">1280x960 30 fps</option>
  662.                     <option value="90">1600x768 30 fps</option>
  663.                     <option value="95">1640x1232 15 fps</option>
  664.                     <option value="97">1640x1232 30 fps</option>
  665.                     <option value="98">1792x896 15 fps</option>
  666.                     <option value="99">1792x896 30 fps</option>
  667.                     <option value="100">1920x1080 15 fps</option>
  668.                     <option value="105">1920x1080 30 fps</option>
  669.                 </select>
  670.                 <p id="note1_"><small>NOTE: if your browser does not support the hardware codec yet, try Firefox with the codec plugin enabled or a recent version of Chrome.</small></p>
  671.             </div>
  672.         </fieldset>
  673.         <div>
  674.             <details id="record-detail">
  675.                 <summary><b>Recorded Audio/Video stream</b></summary>
  676.                 <div>
  677.                     <div class="overlayWrapper">
  678.                         <video id="recorded-video" controls>
  679.                             Your browser does not support the video tag.
  680.                         </video>
  681.                         <p class="overlay">recorded</p>
  682.                     </div>
  683.                 </div>
  684.                 <div>
  685.                     <p><small>NOTE: some old Chrome version may generate corrupted video if the audio track is not present as well (use Firefox in this case)</small></p>
  686.                     <button type=button id="discard" onclick="discard_recording();" title="discard recorded audio/video">Discard</button>
  687.                     <button type=button id="download" onclick="download();" title="save recorded audio/video">Save as</button>
  688.                 </div>
  689.             </details>
  690.         </div><br>
  691.         <fieldset>
  692.             <legend><b>Cast local Audio/Video sources to remote peer</b></legend>
  693.             <div>
  694.                 <span>Audio:</span>
  695.                 <label><input type="checkbox" onclick="singleselection('audio_cast', 'cast_mic');" id="cast_mic" name="audio_cast" value="microphone">microphone/other input</label>
  696.                 <label><input type="checkbox" id="echo_cancellation" name="audio_processing" title="disable any audio processing when casting music" checked>echo cancellation</label>
  697.                 <!--label><input type="checkbox" onclick="singleselection('audio_cast', 'cast_tab');" id="cast_tab" name="audio_cast" value="system">tab</label-->
  698.             </div>
  699.             <div>
  700.                 <span>Video:</span>
  701.                 <label><input type="checkbox" onclick="singleselection('video_cast', 'cast_camera');" id="cast_camera" name="video_cast" value="camera">camera</label>
  702.                 <label><input type="checkbox" onclick="singleselection('video_cast', 'cast_screen');" id="cast_screen" name="video_cast" value="screen">screen</label>
  703.                 <label><input type="checkbox" onclick="singleselection('video_cast', 'cast_window');" id="cast_window" name="video_cast" value="screen">window</label>
  704.                 <label><input type="checkbox" onclick="singleselection('video_cast', 'cast_application');" id="cast_application" name="video_cast" value="application">application</label>
  705.             </div>
  706.             <div>
  707.                 <p id="note1"><small>NOTE: camera and screen can be casted over HTTPS only in Chrome. For the screen the --enable-usermedia-screen-capturing flag must be set. window or application casting is only supported in Firefox 44 on.</small></p>
  708.                 <p id="note2"><small>NOTE: except for camera, to enable screen, window or application casting open <i>about:config</i> URL
  709.                         and set <i>media.getusermedia.screensharing.enabled</i> to <i>true</i>
  710.                         and permanently add the current domain to the list in <i>media.getusermedia.screensharing.allowed_domains.</i></small>
  711.                 </p>
  712.                 <p id="note3"><small>NOTE: if you want to cast music, for better audio quality disable <i>echo-cancellation.</i></small></p>
  713.                 <p id="note4"><small>NOTE: if you want to cast music, for better audio quality disable <i>echo-cancellation</i>,
  714.                         and <i>aec</i>, <i>noise-suppression</i>, <i>agc</i> in the browser configuration <i>(about:config).</i></small>
  715.                 </p>
  716.             </div>
  717.         </fieldset>
  718.         <div>
  719.             <details>
  720.                 <summary><b>Data Channels</b></summary>
  721.                 <fieldset id="datachannels" disabled>
  722.                     <span>message: </span><input type="text" id="datamessage" value="" title="message to send to the remote peer"/>
  723.                     <button id="datasend" onclick="send_message();">Send</button>
  724.                     <span>received: </span><input type="text" readonly="readonly" id="datareceived" size="40" title="data received from the remote peer"/><br>
  725.                     <label><input type="checkbox" onclick="orientationsend_selection();" id="orientationsend" name="orientationsend" title="send device orientation angles when they change">send device orientation angles alpha, beta, gamma</label>
  726.                     <label><input type="checkbox" onclick="keypresssend_selection();" id="keypresssend" name="keypresssend" title="send keyboard events. Assume US layout. For users with virtual keyboard: put the focus on the 'message' input text item.">send key codes (US layout)</label>
  727.                     <label><input type="checkbox" onclick="alert('not implemented yet');" id="mousesend" name="mousesend" title="send mouse events">send mouse events</label>
  728.                 </fieldset>
  729.                 <!--fieldset id="localdatachannels">
  730.                    <button id="datacreate" onclick="create_localdatachannel();">Create</button>
  731.                    <button id="dataclose" onclick="close_localdatachannel();">Close</button>
  732.                </fieldset-->
  733.             </details>
  734.         </div><br>
  735.         <div id="commands">
  736.             <details open>
  737.                 <summary><b>Advanced options</b></summary>
  738.                 <fieldset>
  739.                     <span>Remote Peer/Signalling Server Address: </span><input required type="text" id="signalling_server" value="192.168.100.6:8080" title="<host>:<port>, default address is autodetected"/><br>
  740.                     <span>Optional ICE Servers (STUN/TURN): </span><input type="text" id="ice_servers" value="" title="array of RTCIceServer objects as valid JSON string"/><br>
  741.                     <span>Trickle ICE: </span>
  742.                     <select onclick="trickleice_selection();" id="trickleice" name="trickleice" title="enable trickle ice">
  743.                         <option value="auto">auto</option>
  744.                         <option value="true" selected="selected">true</option>
  745.                         <option value="false">false</option>
  746.                     </select>
  747.                 </fieldset>
  748.             </details>
  749.             <button id="start" style="background-color: green; color: white" onclick="start();">Call!</button>
  750.             <button disabled id="stop" style="background-color: red; color: white" onclick="stop();">Hang up</button>
  751.         </div><br>
  752.         <a target="_top" href="/">home</a>&nbsp;<a href="/panel" target="_blank" title="change the image settings on-the-fly">control panel</a>
  753.     </body>
  754. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement