2016-04-08 5 views
2

Я работаю со следующим кодом от Rob Manson. Начало работы с WebRTC. Он реализован с использованием Node.js. Код запускает видеозвонок в режиме реального времени, и я запустил его как ожидалось между двумя вкладками в веб-браузере. Я просто пытаюсь изменить это, чтобы он использовал Express вместо пакета http.Сервер сигнализации WebRTC с использованием пакетов Express & 'websocket

Проблема, с которой я сталкиваюсь, заключается в том, что в моей версии видео не отображается. «Caller» работает так, как ожидалось, но затем «Callee» останавливается в сообщении «One moment please ... connect your call ...». В консоли браузера или моем терминале ошибок не обнаружено, и, проведя день, пытаясь решить проблему, у меня все еще мало информации о том, где я ошибаюсь.

Вот исходный файл-сервер сигнализации:

// useful libs 
var http = require("http"); 
var fs = require("fs"); 
var websocket = require("websocket").server; 

// general variables 
var port = 8000; 
var webrtc_clients = []; 
var webrtc_discussions = {}; 

// web server functions 
var http_server = http.createServer(function(request, response) { 
     var matches = undefined; 
     if (matches = request.url.match("^/images/(.*)")) { 
      var path = process.cwd()+"/images/"+matches[1]; 

      fs.readFile(path, function(error, data) { 
       if (error) { 
         log_error(error); 
       } else { 
         response.end(data); 
       } 
      }); 
     } else { 
      response.end(page); 
     } 
}); 

http_server.listen(port, function() { 
     log_comment("server listening (port "+port+")"); 
}); 

var page = undefined; 
fs.readFile("basic_video_call.html", function(error, data) { 
     if (error) { 
      log_error(error); 
     } else { 
      page = data; 
     } 
}); 

// web socket functions 
var websocket_server = new websocket({ 
    httpServer: http_server 
}); 
websocket_server.on("request", function(request) { 

    log_comment("new request ("+request.origin+")"); 

    var connection = request.accept(null, request.origin); 
    log_comment("new connection ("+connection.remoteAddress+")"); 

    webrtc_clients.push(connection); 
    connection.id = webrtc_clients.length-1; 

    connection.on("message", function(message) { 
    if (message.type === "utf8") { 
     log_comment("got message "+message.utf8Data); 

      var signal = undefined; 
      try { signal = JSON.parse(message.utf8Data); } catch(e) { }; 

      if (signal) { 
      if (signal.type === "join" && signal.token !== undefined) { 
        try { 
         if (webrtc_discussions[signal.token] === undefined) { 
           webrtc_discussions[signal.token] = {}; 
         } 
        } catch(e) { }; 
        try { 
         webrtc_discussions[signal.token][connection.id] = true; 
        } catch(e) { }; 
      } else if (signal.token !== undefined) { 
        try { 
         Object.keys(webrtc_discussions[signal.token]).forEach(function(id) { 
           if (id != connection.id) { 
             webrtc_clients[id].send(message.utf8Data, log_error); 
           } 
         }); 
        } catch(e) { }; 
      } else { 
       log_comment("invalid signal: "+message.utf8Data); 
      } 
      } else { 
        log_comment("invalid signal: "+message.utf8Data); 
      } 
    } 
    }); 

    connection.on("close", function(connection) { 
     log_comment("connection closed ("+connection.remoteAddress+")"); 

     Object.keys(webrtc_discussions).forEach(function(token) { 
       Object.keys(webrtc_discussions[token]).forEach(function(id) { 
       if (id === connection.id) { 
        delete webrtc_discussions[token][id]; 
       } 
       }); 
     }); 
    }); 
}); 

// utility functions 
function log_error(error) { 
    if (error !== "Connection closed" && error !== undefined) { 
    log_comment("ERROR: "+error); 
    } 
} 
function log_comment(comment) { 
    console.log((new Date())+" "+comment); 
} 

А вот мой измененный файл. Только первый бит был изменен:

// useful libs 
var http = require("http"); 
var fs = require("fs"); 
var websocket = require("websocket").server; 
var express = require('express'); 
var morgan = require('morgan'); 
var bodyParser = require('body-parser'); 

// general variables 
var hostname = 'localhost'; 
var port = 8000; 
var webrtc_clients = []; 
var webrtc_discussions = {}; 

var expressApp = express(); 

expressApp.use(morgan('dev')); 

var myRouter = express.Router(); 

myRouter.use(bodyParser.json()); 

// web server functions 
myRouter.route('/').all(function(request,response,next) { 
    var matches = undefined; 
    if (matches = request.url.match("^/images/(.*)")) { 
    var path = process.cwd() +"/images/"+matches[1]; 

    debugger; 
    console.log("PATH: " + path); 

    fs.readFile(path, function(error, data) { 
     if (error) { 
     log_error(error); 
     } else { 
     response.end(data); 
     } 
    }); 
    } else { 
    response.end(page); 
    } 
}); 
////////////////////// 


expressApp.use('/',myRouter); 

expressApp.listen(port, hostname, function(){ 
    console.log(`Server running at http://${hostname}:${port}/`); 
}); 

/////////////////////// **I CHANGED NOTHING BELOW HERE** //////////// 

var page = undefined; 
fs.readFile("basic_video_call.html", function(error, data) { 
    if (error) { 
    log_error(error); 
    } else { 
    page = data; 
    } 
}); 



// web socket functions 
var websocket_server = new websocket({ 
    httpServer: expressApp 
}); 

websocket_server.on("request", function(request) { 


    log_comment("new request ("+request.origin+")"); 

    var connection = request.accept(null, request.origin); 
    log_comment("new connection ("+connection.remoteAddress+")"); 

    webrtc_clients.push(connection); 
    connection.id = webrtc_clients.length-1; 

    connection.on("message", function(message) { 
    if (message.type === "utf8") { 
     log_comment("got message "+message.utf8Data); 

     var signal = undefined; 
     try { signal = JSON.parse(message.utf8Data); } catch(e) { }; 
     if (signal) { 
     if (signal.type === "join" && signal.token !== undefined) { 
      try { 
      if (webrtc_discussions[signal.token] === undefined) { 
       webrtc_discussions[signal.token] = {}; 
      } 
      } catch(e) { }; 
      try { 
      webrtc_discussions[signal.token][connection.id] = true; 
      } catch(e) { }; 
     } else if (signal.token !== undefined) { 
      try { 
      Object.keys(webrtc_discussions[signal.token]).forEach(function(id) { 
       if (id != connection.id) { 
       webrtc_clients[id].send(message.utf8Data, log_error); 
       } 
      }); 
      } catch(e) { }; 
     } else { 
      log_comment("invalid signal: "+message.utf8Data); 
     } 
     } else { 
     log_comment("invalid signal: "+message.utf8Data); 
     } 
    } 
    }); 

    connection.on("close", function(connection) { 
    log_comment("connection closed ("+connection.remoteAddress+")");  
    Object.keys(webrtc_discussions).forEach(function(token) { 
     Object.keys(webrtc_discussions[token]).forEach(function(id) { 
     if (id === connection.id) { 
      delete webrtc_discussions[token][id]; 
     } 
     }); 
    }); 
    }); 
}); 

// utility functions 
function log_error(error) { 
    if (error !== "Connection closed" && error !== undefined) { 
    log_comment("ERROR: "+error); 
    } 
} 
function log_comment(comment) { 
    console.log((new Date())+" "+comment); 
} 

Кроме того, вот код, который обрабатывает WebRTC вызов, который я не изменился:

<!DOCTYPE html> 
<html> 
<head> 
<script> 
/* 

    webrtc_polyfill.js by Rob Manson 
    NOTE: Based on adapter.js by Adam Barth 

    The MIT License 

    Copyright (c) 2010-2013 Rob Manson, http://buildAR.com. All rights reserved. 

    Permission is hereby granted, free of charge, to any person obtaining a copy 
    of this software and associated documentation files (the "Software"), to deal 
    in the Software without restriction, including without limitation the rights 
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
    copies of the Software, and to permit persons to whom the Software is 
    furnished to do so, subject to the following conditions: 

    The above copyright notice and this permission notice shall be included in 
    all copies or substantial portions of the Software. 

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
    THE SOFTWARE. 

*/ 

var webrtc_capable = true; 
var rtc_peer_connection = null; 
var rtc_session_description = null; 
var get_user_media = null; 
var connect_stream_to_src = null; 
var stun_server = "stun.l.google.com:19302"; 

if (navigator.getUserMedia) { // WebRTC 1.0 standard compliant browser 
    rtc_peer_connection = RTCPeerConnection; 
    rtc_session_description = RTCSessionDescription; 
    get_user_media = navigator.getUserMedia.bind(navigator); 
    connect_stream_to_src = function(media_stream, media_element) { 
    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21606 
    media_element.srcObject = media_stream; 
    media_element.play(); 
    }; 
} else if (navigator.mediaDevices.getUserMedia) { // early firefox webrtc implementation 
    rtc_peer_connection = mozRTCPeerConnection; 
    rtc_session_description = mozRTCSessionDescription; 
    get_user_media = navigator.mozGetUserMedia.bind(navigator); 
    connect_stream_to_src = function(media_stream, media_element) { 
    media_element.mozSrcObject = media_stream; 
    media_element.play(); 
    }; 
    stun_server = "74.125.31.127:19302"; 
} else if (navigator.webkitGetUserMedia) { // early webkit webrtc implementation 
    rtc_peer_connection = webkitRTCPeerConnection; 
    rtc_session_description = RTCSessionDescription; 
    get_user_media = navigator.webkitGetUserMedia.bind(navigator); 
    connect_stream_to_src = function(media_stream, media_element) { 
    media_element.src = webkitURL.createObjectURL(media_stream); 
    }; 
} else { 
    alert("This browser does not support WebRTC - visit WebRTC.org for more info"); 
    webrtc_capable = false; 
} 
</script> 
<script> 
/* 

    basic_video_call.js by Rob Manson 

    The MIT License 

    Copyright (c) 2010-2013 Rob Manson, http://buildAR.com. All rights reserved. 

    Permission is hereby granted, free of charge, to any person obtaining a copy 
    of this software and associated documentation files (the "Software"), to deal 
    in the Software without restriction, including without limitation the rights 
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
    copies of the Software, and to permit persons to whom the Software is 
    furnished to do so, subject to the following conditions: 

    The above copyright notice and this permission notice shall be included in 
    all copies or substantial portions of the Software. 

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
    THE SOFTWARE. 

*/ 

var call_token; // unique token for this call 
var signaling_server; // signaling server for this call 
var peer_connection; // peer connection object 

function start() { 
    // create the WebRTC peer connection object 
    peer_connection = new rtc_peer_connection({ // RTCPeerConnection configuration 
    "iceServers": [ // information about ice servers 
     { "url": "stun:"+stun_server }, // stun server info 
    ] 
    }); 

    // generic handler that sends any ice candidates to the other peer 
    peer_connection.onicecandidate = function (ice_event) { 
    if (ice_event.candidate) { 
     signaling_server.send(
     JSON.stringify({ 
      token:call_token, 
      type: "new_ice_candidate", 
      candidate: ice_event.candidate , 
     }) 
    ); 
    } 
    }; 

    // display remote video streams when they arrive using local <video> MediaElement 
    peer_connection.onaddstream = function (event) { 
    connect_stream_to_src(event.stream, document.getElementById("remote_video")); 
    // hide placeholder and show remote video 
    document.getElementById("loading_state").style.display = "none"; 
    document.getElementById("open_call_state").style.display = "block"; 
    }; 

    // setup stream from the local camera 
    setup_video(); 

    // setup generic connection to the signaling server using the WebSocket API 
    signaling_server = new WebSocket("ws://localhost:8000"); 

    if (document.location.hash === "" || document.location.hash === undefined) { // you are the Caller 

    // create the unique token for this call 
    var token = Math.round(Math.random()*100); 
    call_token = "#"+token; 

    // set location.hash to the unique token for this call 
    document.location.hash = token; 

    signaling_server.onopen = function() { 
     // setup caller signal handler 
     signaling_server.onmessage = caller_signal_handler; 

     // tell the signaling server you have joined the call 
     signaling_server.send(
     JSON.stringify({ 
      token:call_token, 
      type:"join", 
     }) 
    ); 
    } 

    document.title = "You are the Caller"; 
    document.getElementById("loading_state").innerHTML = "Ready for a call...ask your friend to visit:<br/><br/>"+document.location; 

    } else { // you have a hash fragment so you must be the Callee 

    // get the unique token for this call from location.hash 
    call_token = document.location.hash; 

    signaling_server.onopen = function() { 
     // setup caller signal handler 
     signaling_server.onmessage = callee_signal_handler; 

     // tell the signaling server you have joined the call 
     signaling_server.send(
     JSON.stringify({ 
      token:call_token, 
      type:"join", 
     }) 
    ); 

     // let the caller know you have arrived so they can start the call 
     signaling_server.send(
     JSON.stringify({ 
      token:call_token, 
      type:"callee_arrived", 
     }) 
    ); 
    } 

    document.title = "You are the Callee"; 
    document.getElementById("loading_state").innerHTML = "One moment please...connecting your call..."; 
    } 

} 

/* functions used above are defined below */ 

// handler to process new descriptions 
function new_description_created(description) { 
    peer_connection.setLocalDescription(
    description, 
    function() { 
     signaling_server.send(
     JSON.stringify({ 
      token:call_token, 
      type:"new_description", 
      sdp:description 
     }) 
    ); 
    }, 
    log_error 
); 
} 

// handle signals as a caller 
function caller_signal_handler(event) { 
    var signal = JSON.parse(event.data); 
    if (signal.type === "callee_arrived") { 
    peer_connection.createOffer(
     new_description_created, 
     log_error 
    ); 
    } else if (signal.type === "new_ice_candidate") { 
    peer_connection.addIceCandidate(
     new RTCIceCandidate(signal.candidate) 
    ); 
    } else if (signal.type === "new_description") { 
    peer_connection.setRemoteDescription(
     new rtc_session_description(signal.sdp), 
     function() { 
     if (peer_connection.remoteDescription.type == "answer") { 
      // extend with your own custom answer handling here 
     } 
     }, 
     log_error 
    ); 
    } else { 
    // extend with your own signal types here 
    } 
} 

// handle signals as a callee 
function callee_signal_handler(event) { 
    var signal = JSON.parse(event.data); 
    if (signal.type === "new_ice_candidate") { 
    peer_connection.addIceCandidate(
     new RTCIceCandidate(signal.candidate) 
    ); 
    } else if (signal.type === "new_description") { 
    peer_connection.setRemoteDescription(
     new rtc_session_description(signal.sdp), 
     function() { 
     if (peer_connection.remoteDescription.type == "offer") { 
      peer_connection.createAnswer(new_description_created, log_error); 
     } 
     }, 
     log_error 
    ); 
    } else { 
    // extend with your own signal types here 
    } 
} 

// setup stream from the local camera 
function setup_video() { 
    get_user_media(
    { 
     "audio": true, // request access to local microphone 
     "video": true // request access to local camera 
     //"video": {mandatory: {minHeight:8, maxHeight:8, minWidth:8, maxWidth:8}} 
    }, 
    function (local_stream) { // success callback 
     // display preview from the local camera & microphone using local <video> MediaElement 
     connect_stream_to_src(local_stream, document.getElementById("local_video")); 
     // add local camera stream to peer_connection ready to be sent to the remote peer 
     peer_connection.addStream(local_stream); 
    }, 
    log_error 
); 
} 

// generic error handler 
function log_error(error) { 
    console.log(error); 
} 

</script> 
<style> 
html, body { 
    padding: 0px; 
    margin: 0px; 
    font-family: "Arial","Helvetica",sans-serif; 
} 
#loading_state { 
    position: absolute; 
    top: 45%; 
    left: 0px; 
    width: 100%; 
    font-size: 20px; 
    text-align: center; 
} 
#open_call_state { 
    display: none; 
} 
#local_video { 
    position: absolute; 
    top: 10px; 
    left: 10px; 
    width: 160px; 
    height: 120px; 
    background: #333333; 
} 
#remote_video { 
    position: absolute; 
    top: 0px; 
    left: 0px; 
    width: 1024px; 
    height: 768px; 
    background: #999999; 
} 
</style> 
</head> 
<body onload="start()"> 
    <div id="loading_state"> 
     loading... 
    </div> 

    <div id="open_call_state"> 
     <video id="remote_video"></video> 
     <video id="local_video"></video> 
    </div> 
</body> 
</html> 

Я также открыты для решений, которые дон» t используйте Express, но все еще поддерживают аутентификацию в WebRTC. Большое спасибо за вашу помощь.

ответ

1

Ну, я нашел решение. Он просто занимается заменой этой линии:

expressApp.listen (порт, имя хоста, функция() {console.log (Server running at http://${hostname}:${port}/);

С помощью этого один:

вар WebServer = http.createServer (expressApp) .listen (8000);

Причина, по которой это сработало, объясняется в this thread , Извинился за то, что тратил время на чью-то мелочь.

Смежные вопросы