红包
◆ [2024-12-23 星期一 10:32] ◆
您来自:3.144.25.130,欢迎您访问風雲工作室。
◆
收藏本站
◆ | ◆
设为首页
◆
联系站长(腾讯QQ)
5029111 [風雲]
〓
站长当前离线
〓
首 页
论坛交流
游戏频道
无忧脚本
旧版论坛
云服务器
聊 天 室
自助链接
来访记录
访客留言
搜索提供
位置:
風雲工作室
-
论坛交流
-
技术专栏
-
脚本中心
- 【原创】RTC 版 Hello World
返回
主题:【原创】RTC 版 Hello World
風雲
★☆☆☆☆☆☆☆☆☆
积分:58
发帖:62
登录:2024/3/26
注册:2006/9/17
(1楼)
【原创】RTC 版 Hello World
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>RTC Hello World</title> <style type="text/css"> body{ font: 4vw/6vw arial; margin: 0mm } video{ width: 40vw; float: left } input{ font: 4vw/6vw arial; height: 6vw; padding: 0mm 2vw } textarea{ width: 40vw; height: 20vw; font: 4vw/6vw arial; float: left } </style> </head> <body> <div class="box">Hello world 演示:</div><hr /> <table border="1"> <caption>视频通话测试</caption> <tr> <td><input type="button" value="1、我是主叫方" /></td> <td><input type="button" value="1、我是应答方" /></td> </tr> <tr> <td><textarea readonly="true" placeholder="2、点击按钮生成主叫码"></textarea></td> <td><textarea readonly="true" placeholder="4、点击连接生成应答码"></textarea></td> </tr> <tr> <td><textarea placeholder="3、等待输入应答码"></textarea></td> <td><textarea placeholder="2、等待输入主叫码"></textarea></td> </tr> <tr> <td><input type="button" value="4、连接" /></td> <td><input type="button" value="3、连接" /></td> </tr> <tr> <td>聊天区</td> <td>聊天区</td> </tr> <tr> <td><input placeholder="开始聊天" /></td> <td><input placeholder="开始聊天" /></td> </tr> <tr> <td><video></video></td> <td><video></video></td> </tr> </table> </body> <script type="text/javascript"> var step = new Array; step.push(["第一步:创建主叫端", function() { self.conn1 = new RTC(msg => alert("主叫端收到回答:" + msg.data)); }]); step.push(["第二步:生成主叫码", function() { conn1.createOffer(sdp => { console.log(sdp); self.sdp = JSON.stringify(sdp); }); }]); step.push(["第三步:创建应答端", function() { self.conn2 = new RTC(msg => alert("应答端接收消息:" + msg.data)); }]); step.push(["第四步:连接主叫码", function() { if(!self.sdp) return !!alert("正在定位……"); conn2.connect(self.sdp); self.sdp = null; }]); step.push(["第五步:生成应答码", function() { conn2.createAnswer(sdp => { console.log(sdp); self.sdp = JSON.stringify(sdp); }); }]); step.push(["第六步:连接应答码", function() { if(!self.sdp) return !!alert("正在定位……"); conn1.connect(self.sdp); self.sdp = null; }]); step.push(["第七步:发送:你好", function() { conn1.send("你好"); }]); step.push(["第八步:回答:我好", function() { conn2.send("我好"); }]); doStep(); // RTC 类 function RTC(onMsg) { var conn = new RTCPeerConnection({ iceServers: [ { urls: ["stun:stun.l.google.com:19302"] } ] }), me = this; conn.onicecandidate = evt => { if(evt.candidate) return; if(!conn.localDescription) return; me.onready && me.onready(conn.localDescription); }; // 主叫端 this.createOffer = function(func) { me.onready = func; // 呼叫端主动创建信道 me.channel = "createDataChannel" in conn ? conn.createDataChannel("channel-1") : 0; me.channel.onopen = evt => me.onopen(evt); me.channel.onmessage = res => me.onmessage && me.onmessage(res); conn.createOffer({}).then(sdp => conn.setLocalDescription(sdp)); }; // 应答端 this.createAnswer = function(func) { // 应答端被动获得信道 conn.ondatachannel = e => { me.channel = e.channel; me.channel.onopen = evt => me.onopen(evt); me.channel.onmessage = res => me.onmessage && me.onmessage(res); }; conn.createAnswer({}).then(sdp => { conn.setLocalDescription(sdp); }); me.onready = func; }; // 连接对方 this.connect = function(sdp) { conn.setRemoteDescription(new RTCSessionDescription(JSON.parse(sdp))).catch(err => alert(err.message)); }; this.onopen = (evt) => console.log(evt, conn.remoteDescription.type + ":连接成功"); // 消息处理 this.onmessage = onMsg; this.send = function(msg) { if(!me.channel) return me.onmessage && me.onmessage({ data: "暂时不支持聊天" }); me.channel.send(msg); }; this.conn = conn; } // Hello World Demo function doStep() { var item = step.shift(); if(!item) return; var remain = step.length; var div = document.createElement("div"); div.innerHTML = "<input type='button' />"; var btn = div.lastChild; btn.value = item[0]; btn.onclick = function() { if(remain != step.length) return; if(item[1]() !== false) doStep(); }; document.querySelector(".box").appendChild(div); } // 聊天测试 var tbl = document.querySelector("table"); tbl.rows[0].onclick = function(e) { var btn = e.srcElement; if(btn.tagName != "INPUT") return; var idx = btn.parentNode.cellIndex; var conn = new RTC(msg => { var div = document.createElement("div"); div.innerHTML = "你:" + msg.data; tbl.rows[4].cells[idx].append(div); }); // 接收流事件 conn.conn.ontrack = track => { console.log(["offer", "answer"][idx], track); var tv = tbl.rows[6].cells[idx].lastChild; tv.srcObject =track.streams[0]; tv.play(); }; conn.onopen = evt => conn.onmessage({ data: "连接成功" }); var box = tbl.rows[1].cells[0].lastChild; self["rtc" + idx] = conn; alert("连接创建成功"); if(idx) return; getVideoStream(stream => { // createOffer前必须先附加视频流,否则不会传输视频 if(stream) stream.getTracks().forEach(x => conn.conn.addTrack(x, stream)); conn.createOffer(sdp => { box.value = JSON.stringify(sdp); tbl.rows[2].cells[1].lastChild.value = box.value; var ips = sdp.sdp.match(/IN IP4 [\d\.]+/g); if(!ips) return console.log("未找到本机IP"); ips = ips.map(x=> x.slice(7)); ips.unshift("IP 列表:"); alert(ips.join("\r\n")); }); box.placeholder = "正在生成主叫码"; }); }; tbl.rows[3].onclick = function(e) { var btn = e.srcElement; if(btn.tagName != "INPUT") return; var idx = btn.parentNode.cellIndex; var conn = self["rtc" + idx]; if(!conn) return alert("尚未创建连接"); conn.connect(tbl.rows[2].cells[idx].lastChild.value); var box = tbl.rows[1].cells[1].lastChild; if(!idx) return; box.placeholder = "正在生成应答码"; getVideoStream(stream => { if(stream) stream.getTracks().forEach(x => conn.conn.addTrack(x, stream)); conn.createAnswer(sdp => { box.value = JSON.stringify(sdp); tbl.rows[2].cells[0].lastChild.value = box.value; var ips = sdp.sdp.match(/IN IP4 [\d\.]+/g); if(!ips) return console.log("未找到本机IP"); ips = ips.map(x=> x.slice(7)); ips.unshift("IP 列表:"); alert(ips.join("\r\n")); }); }); }; tbl.rows[5].onkeypress = function(e) { if(e.keyCode != 13) return; var ipt = e.srcElement; if(ipt.tagName != "INPUT") return; var idx = ipt.parentNode.cellIndex; self["rtc" + idx].send(ipt.value); var div = document.createElement("div"); div.innerHTML = "我:" + ipt.value; tbl.rows[4].cells[idx].append(div); ipt.value = ""; } function getVideoStream(func) { if("getDisplayMedia" in navigator) return navigator.getDisplayMedia().then( stream => func(stream) ).catch(err => func(null, err)); navigator.mediaDevices.getUserMedia({ video: { mandatory: { chromeMediaSource: "desktop" }, mediaSource: "screen" } }).then(stream => func(stream)).catch(err => func(null, err)); } </script> </html>
[您可以先修改代码再运行]
1、实际应用可能需要配合 websocket 来传递 主叫码和应答码。
2、视频通话因安全原因,需要使用 https 协议 或者 localhost 域名。
时间:
2020年4月28日 23:46:25
IP:
已记录
引用
回复
© Copyright 2006-2024,
風雲工作室
All rights reserved.
【
湘ICP备05009306号
】
QQ登录
操作 1 个库,连接 2 次,执行 7 次,耗时 47 毫秒。