我搜索过很多网页,甚至还有“开始使用webrtc”这本书,其中的样本会出错。 但是我无法找到工作1to1视频聊天的任何工作示例。
更好的是使用nodeJS传输。
我认为我发现的样本不遵守这些规则:
我找到了许多个人API或个人aproaches,但找不到SIMPLEST方法来创建单个1to1视频聊天。
祝你好运
来自webrtc book的样本(确实有效)给出了错误:
Mon Apr 14 2014 23:19:26 GMT+0200 (Paris, Madrid invalid signal:
{"type":"new_ice_candidate","candidate":{"candidate":"candidate:1 2 UDP 16924671
98 90.7.245.247 63704 typ srflx raddr 192.168.1.15 rport 63704","sdpMid":"","sdp
MLineIndex":0}}
客户方:
<!DOCTYPE html>
<html>
<head>
<script>
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 = "stun01.sipphone.com";
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.mozGetUserMedia) { // 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>
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({
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://192.168.1.15:1234");
if (document.location.hash === "" || document.location.hash === undefined) { // you are the Caller
// create the unique token for this call
var token = Date.now()+"-"+Math.round(Math.random()*10000);
var token = Math.round(Math.random()*10000);
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
},
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>
服务器端(nodejs)
// useful libs
var http = require("http");
var fs = require("fs");
var websocket = require("websocket").server;
// general variables
var port = 1234;
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("signal.type="+signal.type+" *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);
}
答案 0 :(得分:1)
您可以参考codelab上的示例。尝试运行第7步:将所有内容放在一起:RTCPeerConnection + RTCDataChannel +信令。 Node.js是必需的。您还可以阅读文章How to Implement a Real-time Commnication Application with WebRTC,该文章基于codelab分享了一些学习经验。