我有一个正在运行的node.js,用户将连接到它。报价和答案将通过 Node.js 生成并发送。
我正在尝试建立对等连接并通过相机流发送。我尝试了我的代码,但没有使用 ICE 候选者作为同一子网中的计算机。后来我尝试实现ICE。我不确定我是否做得对,或者如果计算机位于同一子网上是否需要它。
var localStream;
//Connect to signaling server
var signalingChannel = io.connect('http://85.134.54.193:8001');
console.log("Connect to signaling server");
var servers = null;
var video1;
var video2;
var audio1;
var audio2;
var cfg = {"iceServers":[{"url":"stun:stun.l.google.com:19302"}]};//{ "iceServers": [{ "url": "stun:stun.l.google.com:19302" }] };
var con = { 'optional': [{'DtlsSrtpKeyAgreement': true}, {'RtpDataChannels': true }] };
var peerConnection;
//Runs after the page has been loaded
window.onload=function(){
//Gets ID for the video element which will display the local stream
video1 = document.getElementById("audio1");
//Gets ID for the video element which will display the remote stream
video2 = document.getElementById("audio2");
audio1 = document.getElementById("audio1");
audio2 = document.getElementById("audio2");
}
//Start button function
function caller(){
peerConnection = new webkitRTCPeerConnection(cfg);
navigator.webkitGetUserMedia({'audio':true, video:true}, function (stream) {
console.log("Got local audio", stream);
video1.src = window.webkitURL.createObjectURL(stream)
peerConnection.addStream(stream);
},
function ( err ) {
console.log( 'error: ', err );
});
console.log("Calling");
//Create Offer
peerConnection.createOffer(function (offerDesc) {
console.log("Created local offer", offerDesc.sdp);
peerConnection.setLocalDescription(offerDesc);
}, function () { console.warn("Couldn't create offer"); });
//ICE Candidates Generator
peerConnection.onicecandidate = function(evt) {
//When The Ice Gathering is complete
if (evt.target.iceGatheringState == "complete") {
//Create a new offer with ICE candidates
peerConnection.createOffer(function(offer) {
console.log("Offer with ICE candidates: " + offer.sdp);
signalingChannel.emit('offer', JSON.stringify(offer));
console.log("offer sent");
signalingChannel.on('answer', function(data){
console.log("Receive answer");
//The answer is set as the remote description for the offerer
peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(data)));
console.log("Set remote desc");
peerConnection.onaddstream = gotRemoteStream;
console.log("Add remote stream to peer connection");
});
});
}
}
}
function answerer(){
peerConnection = new webkitRTCPeerConnection(cfg);
navigator.webkitGetUserMedia({'audio':true, video:true}, function (stream) {
console.log("Got local audio", stream);
video1.src = window.webkitURL.createObjectURL(stream)
peerConnection.addStream(stream);
},
function ( err ) {
console.log( 'error: ', err );
});
console.log("Answering");
//Listen for offer
signalingChannel.on('offer', function(data){
console.log("Offer Received");
//Set the remote description from caller's local description
peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(data)));
//Generate answer after getting the remote description
peerConnection.createAnswer(function(sessionDescription) {
//Set local description
peerConnection.setLocalDescription(sessionDescription);
//The local desc will be the answer sent back to offerer
signalingChannel.emit('answer', JSON.stringify(sessionDescription));
console.log("Answer sent");
});
});
}
function gotRemoteStream(event){
video2.src = window.webkitURL.createObjectURL(event.stream);
}
以下是我今天(2014 年 2 月)在 Chrome 中处理的一系列事件。这是一个简化的情况,即对等点 1 将视频流式传输到对等点 2。
- 设置某种方式供对等点交换消息。 (遗憾的是,人们实现这一目标的方式存在差异,这使得不同的 WebRTC 代码示例变得不可通约。但在精神上和代码组织中,请尝试将此逻辑与其余逻辑分开。)
- 在每一侧,为重要的信令消息设置消息处理程序。您可以设置它们并保留它们。有 3 个核心消息需要处理和发送:
- 对方发送来的ice候选者==>用它调用
addIceCandidate
- 一条报价消息 ==>
SetRemoteDescription
,然后做出答复并发送
- 回复消息 ===>
SetRemoteDescription
及其
- 在每一侧,创建一个新的对等连接对象,并为重要事件附加事件处理程序:onicecandidate、onremovestream、onaddstream 等。
- ice候选===>发送给对方
- 已添加流===>将其附加到视频元素以便您可以看到它
- 当两个对等点都存在并且所有处理程序都就位时,对等点 1 会收到某种触发消息以开始视频捕获(使用
getUserMedia
调用)
- 一旦
getUserMedia
成功,我们就有了一个流。在对等点 1 的对等连接对象上调用 addStream
。
- 然后——并且只有在那时——同行 1 提出报价
- 由于我们在第 2 步中设置的处理程序,对等点 2 会获取此信息并发送答案
- 与此同时(有点模糊),对等连接对象开始生成ice候选对象。它们在两个对等点之间来回发送并进行处理(上面的步骤 2 和 3)
- 由于以下两个条件,流式传输会自行不透明地启动:
当我想要更改流时,我返回步骤 3 并设置一个新的对等连接对象,并再次执行整个提供/应答。
我是一名优秀的程序员,十分优秀!