首页 文章 精选 留言 我的

精选列表

搜索[JavaScript],共9118篇文章
优秀的个人博客,低调大师

如何使用Javascript构建WebRTC视频直播?

WebRTC是一个免费的开源项目,它通过简单的API为浏览器和移动应用程序提供实时通信功能。本文将向你展示WebRTC的基本概念和功能,并指导你使用Node.js构建自己的WebRTC视频直播。 先决条件: 具有Java经验 掌握Socket.io基本知识 WebRTC基础 WebRTC支持在网络世界中进行实时通信,主要用于在网络上传输视频和音频数据。 在开始编写代码之前,我们首先来看一下WebRTC的最重要概念。 信令: WebRTC用于浏览器中的通信流,但还需要一种机制来协调通信并发送控制消息,该过程称为信令。 信令用于以下任务: 初始化和关闭通讯 与外界共享网络配置(IP地址,端口) 报告连接错误 信令方法不是WebRTC指定的,开发人员可以自行选择(本教程将使用Socket.io)。 STUN和TURN服务器: 如果主要的WebRTC对等连接遇到问题,则将STUN和TURN服务器用作备用方法。 STUN服务器用于获取计算机的IP地址,而TURN服务器用作对等连接失败的中继。 既然我们已经了解了WebRTC的基本概念,就可以继续开发上面讨论的项目。 使用Socket.io发出信号 在使用WebRTC通过对等连接发送视频广播之前,我们首先需要使用信令方法(在本例中为Socket.IO)实例化该连接。 为此,我们创建项目并使用npm安装所需的依赖项: mkdir WebSocketsVideoBroadcast && cd WebSocketsVideoBroadcast npm install express socket.io --save 之后,我们创建以下文件夹结构: 我们从一个简单的Socket.io服务器框架开始: const express = require("express"); const app = express(); const port = 4000; const http = require("http"); const server = http.createServer(app); const io = require("socket.io")(server); app.use(express.static(__dirname + "/public")); io.sockets.on("error", e => console.log(e)); server.listen(port, () => console.log(`Server is running on port ${port}`)); 然后,我们需要实现客户端和直播者与服务器的连接。 直播者的Socket ID保存到一个变量中,以便我们以后知道客户端需要连接到的位置。 let broadcaster io.sockets.on("connection", socket => { socket.on("broadcaster", () => { broadcaster = socket.id; socket.broadcast.emit("broadcaster"); }); socket.on("watcher", () => { socket.to(broadcaster).emit("watcher", socket.id); }); socket.on("disconnect", () => { socket.to(broadcaster).emit("disconnectPeer", socket.id); }); }); 之后,我们将实现socket.io事件以初始化WebRTC连接。 双方将使用这些事件来实例化对等连接。 socket.on("offer", (id, message) => { socket.to(id).emit("offer", socket.id, message); }); socket.on("answer", (id, message) => { socket.to(id).emit("answer", socket.id, message); }); socket.on("candidate", (id, message) => { socket.to(id).emit("candidate", socket.id, message); }); 这就是我们Socket.io的服务器实现的全部内容,现在我们可以继续进行布局以及双方通信的实现。 Layouts 我们的布局由两个基本HTML文件组成,其中包含一个视频视图(稍后将显示我们正在发送的视频流)和一个CSS文件(用于某些基本样式)。 index.html文件包含一个视频视图,该视图将显示来自广播公司的视频流。 它还会导入socket.io依赖项和我们的watch.js文件。 <!DOCTYPE html> <html> <head> <title>Viewer</title> <meta charset="UTF-8" /> <link href="/styles.css" rel="stylesheet"> </head> <body> <video playsinline autoplay></video> <script src="/socket.io/socket.io.js"></script> <script src="/watch.js"></script> </body> </html> broadcast.html文件与主布局非常相似,但会导入broadcast.js文件而不是watch.js。 <!DOCTYPE html> <html> <head> <title>Broadcaster</title> <meta charset="UTF-8" /> <link href="/styles.css" rel="stylesheet"> </head> <body> <video playsinline autoplay muted></video> <script src="/socket.io/socket.io.js"></script> <script src="/broadcast.js"></script> </body> </html> 我还为视频视图提供了一些简单的CSS样式。 html { overflow: hidden; height: 100%; } video { width: 100%; height: 100%; position: absolute; display: block; top: 0; left: 0; object-fit: cover; } body { background-color: black; margin: 0; height: 100%; width: 100%; position: fixed; top: 0; left: 0; bottom: 0; right: 0; } RTCPeerConnection RTCPeerConnections帮助我们将位于本地网络中的两台计算机相互连接。 在谈论这些类型的连接时,会涉及到很多术语: ICE-互联网连接建立 STUN-通过网络地址转换器[NAT]进行的用户数据报协议[UDP]的会话遍历 由于当今大多数设备都在NAT路由器后面,因此无法直接连接。 这就是为什么必须由STUN服务器初始化对等连接的原因,STUN服务器将返回我们可以连接的ICE候选对象。 在本指南中,我们有两个不同的连接部分。 一个是视频直播方,可以与客户端建立多个对等连接,并使用流发送视频。 第二个是客户端,它与当前视频直播方只有一个连接。 直播方 首先,我们为对等连接和摄像机创建配置对象。 const peerConnections = {}; const config = { iceServers: [ { urls: ["stun:stun.l.google.com:19302"] } ] }; const socket = io.connect(window.location.origin); const video = document.querySelector("video"); // Media contrains const constraints = { video: { facingMode: "user" } // Uncomment to enable audio // audio: true, }; 我们使用正式的google STUN服务器进行点对点连接,并使用媒体限制条件配置摄像机。 你也可以通过取消注释音频线路来启用音频。 在创建对等连接之前,我们首先需要从摄像机获取视频,以便将其添加到我们的连接中。 navigator.mediaDevices .getUserMedia(constraints) .then(stream => { video.srcObject = stream; socket.emit("broadcaster"); }) .catch(error => console.error(error)); 接下来,我们将使用以下代码创建一个RTCPeerConnection: socket.on("watcher", id => { const peerConnection = new RTCPeerConnection(config); peerConnections[id] = peerConnection; let stream = video.srcObject; stream.getTracks().forEach(track => peerConnection.addTrack(track, stream)); peerConnection.onicecandidate = event => { if (event.candidate) { socket.emit("candidate", id, event.candidate); } }; peerConnection .createOffer() .then(sdp => peerConnection.setLocalDescription(sdp)) .then(() => { socket.emit("offer", id, peerConnection.localDescription); }); }); socket.on("answer", (id, description) => { peerConnections[id].setRemoteDescription(description); }); socket.on("candidate", (id, candidate) => { peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate)); }); 每次有新客户端加入时,我们都会创建一个新的RTCPeerConnection并将其保存在我们的peerConnections对象中。 然后,我们使用addTrack()方法将本地流添加到连接中,并传递流和跟踪数据。 当我们收到一个ICE候选者时,将调用peerConnection.onicecandidate事件,并将其发送到我们的服务器。 之后,我们通过调用peerConnection.createOffer()将连接提议发送给客户端,然后调用peerConnection.setLocalDescription()来配置连接。 当客户端断开连接时,关闭连接是应用程序的另一个重要部分,我们可以使用以下代码来实现: socket.on("disconnectPeer", id => { peerConnections[id].close(); delete peerConnections[id]; }); 最后,如果用户关闭窗口,我们将关闭socket连接。 window.onunload = window.onbeforeunload = () => { socket.close(); }; 客户端 客户端(观看视频的一方))具有几乎相同的功能。 唯一的区别是,他仅打开了与当前视频直播方的一个对等连接,并且他获取了视频,而不是流式传输视频。 我们还需要为RTCPeerConnection创建一个配置。 let peerConnection; const config = { iceServers: [ { urls: ["stun:stun.l.google.com:19302"] } ] }; const socket = io.connect(window.location.origin); const video = document.querySelector("video"); 然后,我们可以创建我们的RTCPeerConnection并从视频直播方获取视频流。 socket.on("offer", (id, description) => { peerConnection = new RTCPeerConnection(config); peerConnection .setRemoteDescription(description) .then(() => peerConnection.createAnswer()) .then(sdp => peerConnection.setLocalDescription(sdp)) .then(() => { socket.emit("answer", id, peerConnection.localDescription); }); peerConnection.ontrack = event => { video.srcObject = event.streams[0]; }; peerConnection.onicecandidate = event => { if (event.candidate) { socket.emit("candidate", id, event.candidate); } }; }); 在这里,我们像上面一样使用配置对象创建了一个新的RTCPeerConnection。 唯一的区别是,我们调用createAnswer()函数将连接应答发送回视频直播方的请求。 建立连接后,我们可以继续使用peerConnection对象的ontrack事件侦听器获取视频流。 我们还需要为点对点连接实现其他生命周期功能,这将有助于我们打开和关闭新连接。 socket.on("candidate", (id, candidate) => { peerConnection .addIceCandidate(new RTCIceCandidate(candidate)) .catch(e => console.error(e)); }); socket.on("connect", () => { socket.emit("watcher"); }); socket.on("broadcaster", () => { socket.emit("watcher"); }); window.onunload = window.onbeforeunload = () => { socket.close(); peerConnection.close(); }; 至此,该应用程序已完成,可以继续在浏览器中对其进行测试。 测试应用程序 现在我们已经完成了该应用程序,是时候对其进行测试,看看它是否可以工作了。 我们可以使用以下命令启动该应用程序: node server.js 该应用程序现在应该在你的localhost:4000上运行,并且可以通过连接到localhost:4000 / broadcast来添加新的视频直播品程序进行测试。 之后,只需要访问localhost:4000即可作为客户端连接到服务器,并且你应该获得从视频直播方的流式传输的视频。 结论 我希望本文能帮助您了解WebRTC的基础知识以及如何使用它来流式传输视频直播。 EasyRTC视频会议云服务 基于WebRTC技术而开发的EasyRTC,是TSINGSEE青犀视频团队在音视频领域多年的技术积累而研发的, 它是覆盖全球的实时音频开发平台,支持一对一、一对多等视频通话。 EasyRTC拥有MCU和SFU两种架构,无需安装客户端与插件,纯H5在线视频会议系统,支持微信小程序、H5页面、APP、PC客户端等接入方式,极大满足语音视频社交、在线教育和培训、视频会议和远程医疗等场景需求。 随着移动互联网的高速发展,AI、5G等等新兴技术的到来,结合WebRTC技术,也将衍生出更多的应用场景,改变人类的衣、食、住、行等生活方式。

优秀的个人博客,低调大师

用JavaScript开发Stellar区块链应用

Stellar JS SDK封装了Stellar交易的提交,以及与Stellar Horizon API服务器的交互过程,可以运行在Node.js环境或Web浏览器中。js-stellar-sdk主要有两个作用:1、通过HorizonAPI服务器查询Stellar区块链数据 2、构建Stellar交易、签名并提交到Stellar网络中。 相关推荐:汇智网 区块链开发系列教程 1、构造Horizon访问请求 js-stellar-sdk使用Builder模式来创建要发送给Horizon API服务器的请求。从一个server对象开始,你可以通过链式调用来生成最终的查询请求。例如: var StellarSdk = require('stellar-sdk'); var server = new StellarSdk.Server('https://horizon-testnet.stellar.org'); // get a list of transactions that occurred in ledger 1400 server.transactions() .forLedger(1400) .call().then(function(r){ console.log(r); }); // get a list of transactions submitted by a particular account server.transactions() .forAccount('GASOCNHNNLYFNMDJYQ3XFMI7BYHIOCFW3GJEOWRPEGK2TDPGTG2E5EDW') .call().then(function(r){ console.log(r); }); 一旦请求构造好了,就可以调用.call()或.stream()来提交请求。.call()将返回一个promise对象,其解析结果为Horizon服务器的响应。 2、发送流式请求 许多请求可以使用.stream()来调用。与.call()返回promise对象不同,.stream()将返回一个EventSource对象。Horizon API服务器会自动推送相关的数据给请求的客户端。 例如,下面的代码显示输出指定的Stellar账户的交易: var StellarSdk = require('stellar-sdk') var server = new StellarSdk.Server('https://horizon-testnet.stellar.org'); var lastCursor=0; // or load where you left off var txHandler = function (txResponse) { console.log(txResponse); }; var es = server.transactions() .forAccount(accountAddress) .cursor(lastCursor) .stream({ onmessage: txHandler }) 3、处理Stellar Horizon API服务器的响应 3.1 Stellar XDR格式解码 Horizon API服务器的交易访问端结点会以原始XDR格式返回某些字段。你可以使用.fromXDR()将XDR转换为JSON格式。 例如,下面的代码重写了上面示例中的txHandler来将XDR字段显示为JSON格式: var txHandler = function (txResponse) { console.log( JSON.stringify(StellarSdk.xdr.TransactionEnvelope.fromXDR(txResponse.envelope_xdr, 'base64')) ); console.log( JSON.stringify(StellarSdk.xdr.TransactionResult.fromXDR(txResponse.result_xdr, 'base64')) ); console.log( JSON.stringify(StellarSdk.xdr.TransactionMeta.fromXDR(txResponse.result_meta_xdr, 'base64')) ); }; 3.2 Horizon响应结果中的链接跟随 在Horizon响应中包含的链接已经被转换为对应的方法调用,这让你可以简单地通过.next()方法来逐页查看结果,同时也让获取额外信息更加轻松。例如: server.payments() .limit(1) .call() .then(function(response){ // will follow the transactions link returned by Horizon response.records[0].transaction().then(function(txs){ console.log(txs); }); }); 4、Stellar交易构建与广播 4.1 Stellar交易构建 Stellar的交易构建过程稍微复杂一点,我们将在另一篇文章中介绍,你可以先查看英文原文 4.2 Stellar交易提交 一旦创建好了交易,就可以使用Server.submitTransaction()方法将其提交到Stellar网络中。 const StellarSdk = require('stellar-sdk') StellarSdk.Network.useTestNetwork(); const server = new StellarSdk.Server('https://horizon-testnet.stellar.org'); (async function main() { const account = await server.loadAccount(publicKey); /* Right now, we have one function that fetches the base fee. In the future, we'll have functions that are smarter about suggesting fees, e.g.: `fetchCheapFee`, `fetchAverageFee`, `fetchPriorityFee`, etc. */ const fee = await server.fetchBaseFee(); const transaction = new StellarSdk.TransactionBuilder(account, { fee }) .addOperation( // this operation funds the new account with XLM StellarSdk.Operation.payment({ destination: "GASOCNHNNLYFNMDJYQ3XFMI7BYHIOCFW3GJEOWRPEGK2TDPGTG2E5EDW", asset: StellarSdk.Asset.native(), amount: "20000000" }) ) .setTimeout(30) .build(); // sign the transaction transaction.sign(StellarSdk.Keypair.fromSecret(secretString)); try { const transactionResult = await server.submitTransaction(transaction); console.log(transactionResult); } catch (err) { console.error(err); } })() 原文链接:Stellar JS SDK简明教程 - 汇智网

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册