websocket+node实现直播(弱鸡版)

这篇具有很好参考价值的文章主要介绍了websocket+node实现直播(弱鸡版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

心血历程

这部分主要是写在写这些的时候遇到的问题以及换思路的过程,可以之间看正文
在之前我也写过直播功能,并且与websocket相结合实现了直播弹幕。只不过直播是使用的腾讯云的,而不是手写的直播推流拉流,这次又有一个新的项目,和直播息息相关(直播自习平台),所以就想着使用原生的写直播推流、拉流,搞了两天,实现了一个基础版本的直播。
这两天搞直播也挺难受的,原本我和后端想的和之前写项目一样,一个拉流地址,一个推流地址,不过后端写好之后也用软件测试了一下可行,兴高采烈的给我说写好了,既然后端接口写好了,剩下的就是前端去交互了,经过一段时间的交互,拉流报错,推流也报错,经过一番百度原来是浏览器不支持rtmp协议,只能另寻它法,最后想到使用websocket去连接,我把采集到的音视频流数据传输给后端,后端在传输给我,我再统一处理,写好之后发现了一个小问题就是每次推流与拉流之间都会闪一下,原本想着使用mediaSource视频流去搞一下,不过最后发现视频格式对于不同浏览器的要求是不一样的,而且浏览器对于视频格式要求也比较严,最后就不搞了。经过与后端的商量,最终决定项目中写两版直播,一版是原生写的,一版是使用腾讯云直播写的。下面就进入正文吧。

直播常见协议
  1. RTMP
    RTMP(Real-Time Messaging Protocol)是一种用于音频、视频和数据传输的协议。它最初由Adobe开发,用于在Flash播放器和媒体服务器之间进行实时通信。RTMP通过建立持久的连接来传输流媒体数据,支持实时的流媒体传输和即时通信。
  2. HTTP-FLV
    HTTP-FLV(HTTP-Flash Video)是一种基于HTTP协议的流媒体传输协议。它是由阿里巴巴开发的,用于在Web浏览器中播放Flash视频。HTTP-FLV通过HTTP协议传输FLV(Flash Video)格式的视频,可以实现低延迟的视频直播和点播。
  3. HLS
    HLS(HTTP Live Streaming)是一种由苹果公司开发的流媒体传输协议。它通过将视频和音频切片成小的TS(Transport Stream)文件,并使用HTTP协议传输这些文件,实现了在不同网络环境下的自适应流媒体传输。HLS支持多种编码格式和分辨率的视频,可以在iOS设备和Web浏览器上播放。
    总的来说RTMP是一种实时的流媒体传输协议,适用于实时通信和互动性较高的应用;HTTP-FLV是一种基于HTTP协议的低延迟流媒体传输协议,适用于Web浏览器中的Flash视频播放;HLS是一种适用于不同网络环境下的自适应流媒体传输协议,适用于iOS设备和Web浏览器的播放。
    直播基本流程
    websocket+node实现直播(弱鸡版),websocket,网络协议,网络,前端,直播

看上图可知直播分为以下三个步骤:

  1. 视频/音频采集(推流)
  2. 流媒体服务器(用于推流/拉流的中转服务器)
  3. 播放(拉流)
    对于前端来说推流以及拉流都是我们所要操心的事,而后端要做的是中转服务器作用
直播代码

经过以上的说明,大家对直播有了一个简单的了解,那么我们之间上代码
node端(需要下载ws第三方库)

const WebSocket = require("ws");

const wss = new WebSocket.Server({
  port: 3000,
});

wss.on("connection", (ws) => {
  ws.on("message", (msg) => {
    wss.clients.forEach((ws) => {
      ws.send(msg);
    });
  });
});

node端我们做的很简洁,就是把前端发给我们的数据再发给前端
那么就显得数据很重要了,既然是直播那么我们的数据就是我们直播的数据(及视频,音频),另外需要补充两点就是我们传输的数据一般比较大,websocket的传输虽然理论上是无限,但是为了不明显的卡顿,我们前端传输数据采用分段上传。另外就是为了保证数据的准确,我们传输的是二进制数据,这样就能保证了观看与直播的相对无误差。
在写前端代码之前,我来解释一下为什么这个直播是弱鸡版,我们实现的是推流是前端录视频一段时间之后发给后端,后端再转接给前端,循环往复,由此就实现了直播功能,这也是推流拉流时屏幕闪的原因。不过更多的是让大家了解一下大致的流程,及一个可行的方法。
前端推流代码

<!--用以预览-->
    <video></video>

    <button onclick="onStartRecord()">开始共享</button>
    <button onclick="onDownload()">手动推流</button>
    <button onclick="close()">关闭</button>
    <script>
        var socket = new WebSocket("ws://127.0.0.1:3000");
        socket.onopen = () => {
            console.log("WebSocket 连接成功");
        };
        socket.onclose = (event) => {
            console.log("WebSocket 连接关闭", event);
        };
        socket.onerror = (error) => {
            console.error("发生错误", error);
        };
        socket.onmessage = (event) => {
            console.log("收到信息", event.data);
        };
        // 想要获取一个最接近 1280x720 的相机分辨率
        var recordedChunks = [];
        var stream

        var onStartRecord = function () {
            navigator.mediaDevices
                .getDisplayMedia({
                    video: {
                        mediaSource: "screen",
                    },
                    audio: true
                })
                .then(async function (mediaStream) {
                    const audioTrack = await navigator.mediaDevices.getUserMedia({ audio: true });
                    // 添加声音轨道
                    await mediaStream.addTrack(audioTrack.getAudioTracks()[0]);
                    var video = document.querySelector('video');
                  //本地预览视频
                    video.srcObject = mediaStream;
                    stream = mediaStream
                    video.onloadedmetadata = function (e) {
                        video.play();
                    };
                  //采集视频
                    startRecord(mediaStream);
                })
                .catch(function (err) {
                    console.log(err.name + ': ' + err.message);
                }); // 总是在最后检查错误
        };

        var timer = null

        function startRecord(stream) {
            recordedChunks = []
            var options = { mimeType: 'video/webm; codecs=vp9' };
            mediaRecorder = new MediaRecorder(stream, options);

            mediaRecorder.ondataavailable = handleDataAvailable;
            mediaRecorder.start();
            clearInterval(timer)
          //每隔5秒自动推流
            timer = setInterval(async () => {
                await onDownload()
                await startRecord(stream)
            }, 5000)
        }

        //onDownloadClick,调用stop会停止并会触发ondataavailable,相应下载逻辑在回调中完成
        var onDownload = function () {
            mediaRecorder.stop();
        };


        function handleDataAvailable(event) {
            if (event.data.size > 0) {
                recordedChunks.push(event.data);
                download();
            } else {
                // ...
            }
        }

        const CHUNK_SIZE = 1024 * 5; // 每个数据块的大小为 16KB
      //分片上传
        function sliceBlob(blob) {
            const chunks = [];
            let offset = 0;
            while (offset < blob.size) {
                const chunk = blob.slice(offset, offset + CHUNK_SIZE);
                chunks.push(chunk);
                offset += CHUNK_SIZE;
            }
            return chunks;
        }

        async function download() {
            var blob = new Blob(recordedChunks, {
                type: 'video/webm',
            });
            console.log(blob);
            const binaryChunks = sliceBlob(blob);
            for (const chunk of binaryChunks) {
                console.log(chunk);
                await socket.send(chunk);
            }
        }
      //关闭直播
        function close() {
            stream.getTracks().map((track) => track.stop());
        }

    </script>

前端拉流代码

 <video src="" id="mv" controls></video>
    <script>
        const mv = document.getElementById('mv')
        var socket = new WebSocket("ws://127.0.0.1:3000");
        socket.onopen = () => {
            console.log("WebSocket 连接成功");
        };

        socket.onclose = (event) => {
            console.log("WebSocket 连接关闭", event);
        };

        socket.onerror = (error) => {
            console.error("WebSocket Error:", error);
        };
        let videoData = []
        socket.onmessage = async (event) => {
            if (event.data.size < 1024 * 5) {
              //合并数据进行渲染
                const blob = new Blob(videoData, { type: 'video/webm' })
                mv.src = URL.createObjectURL(blob);
                videoData = []
                mv.play()
            } else {
                // 接收数据
                videoData.push(event.data)
            }
        }

    </script>

注意事项:
我们使用blob时要指定格式,以此方便我们播放的时候浏览器解码

总结

之后遇到项目的问题再继续分享吧。之后也正式开始写项目了。我们一同进步。文章来源地址https://www.toymoban.com/news/detail-630907.html

到了这里,关于websocket+node实现直播(弱鸡版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 持久双向通信网络协议-WebSocket-入门案例实现demo

    1 介绍 WebSocket 是基于 TCP 的一种新的 网络协议 。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建 持久性 的连接, 并进行 双向 数据传输。 HTTP协议和WebSocket协议对比: HTTP是 短连接 (一次响应完即消除) WebSocket是 长连接

    2024年01月16日
    浏览(45)
  • 用 Node.js 手写 WebSocket 协议

    目录 引言 从 http 到 websocekt 的切换 Sec-WebSocket-Key 与 Sec-WebSocket-Accept 全新的二进制协议 自己实现一个 websocket 服务器 按照协议格式解析收到的Buffer 取出opcode 取出MASK与payload长度 根据mask key读取数据 根据类型处理数据 frame 帧 数据的发送 完整代码 总结         我们知道,

    2024年02月16日
    浏览(40)
  • [前端基础]websocket协议

    (1)websocket websocket(简写为ws),是一种轻量化的协议,经过最开始的握手阶段以后,前后端之间允许自由地发送信息不受限制(建议发送json字符串).虽然理论上这个东西是属于协议内容,但是已经被疯狂封装得像框架一样了. websocket协议具有天然的优势处理前端多线程并发,并且只需要一

    2024年02月08日
    浏览(41)
  • WebSocket 网络协议(实时更新 )

    WebSocket 是一种在客户端和服务器之间建立双向通信信道的网络协议。它在客户端和服务器之间建立一个持久的、全双工的连接,允许数据在两个方向上实时传输,而不需要像HTTP一样进行多次请求和响应。  WebSocket 的主要优势是减少了服务器和客户端之间的通信延迟,因为数

    2024年01月17日
    浏览(47)
  • 【spring(六)】WebSocket网络传输协议

    🌈键盘敲烂,年薪30万🌈 目录 核心概要: 概念介绍: 对比HTTP协议:⭐ WebSocket入门案例:⭐ websocket对比http         WebSocket是Web服务器的一个组件,WebSocket是一种基于TCP的新的 网络传输协议 ,它实现了浏览器与服务器全双工通信——浏览器只需要完成 一次握手 ,两者之

    2024年02月05日
    浏览(42)
  • 使用node实现websocket

    websocket 代表了 Web 应用程序通信方式的根本转变。不同于传统的 HTTP 请求响应周期,即客户端从服务器请求数据并等待响应, websocket 在客户端和服务器之间建立一个持久的全双工连接。这意味着一旦建立了 websocket ,数据可以在任何时候双向流动,而不需要重复请求。 Web

    2024年02月08日
    浏览(33)
  • Node.js实现WebSocket

    1、Http协议发布REST API 的不足: 每次请求响应完成之后,服务器与客户端之间的连接就断开了,如果客户端想要继续获取服务器的消息,必须再次向服务器发起请 求。这显然无法适应对实时通信有高要求的场景。 2、改善http的不足:Web通信领域出现了一些其他的解决方案,如

    2024年02月02日
    浏览(39)
  • 【websocket】Node+Vue2+WebSocket实现前后端通讯

    WebSocket是一个长连接,客户端可以给服务端发送消息,服务端也可以给客户端发送消息,是 全双工通信。 平时的前后端分离项目,是前端请求结果获取后端服务器数据,从而渲染到页面,服务端无法主动向客户端发起消息,某些需求场景下,一旦客户端 需要知道服务端的频

    2024年02月02日
    浏览(42)
  • WebSocket | 基于TCP的全双工通信网络协议

    ​🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎Python人工智能开发和前端开发。 🦅主页:@逐梦苍穹 📕所属专栏:Java EE ✈ 您的一键三连,是我创作的最大动力🌹 WebSocket 是基于 TCP 的一

    2024年02月19日
    浏览(74)
  • 网络通信协议-HTTP、WebSocket、MQTT的比较与应用

    在今天的数字化世界中,各种通信协议起着关键的作用,以确保信息的传递和交换。HTTP、WebSocket 和 MQTT 是三种常用的网络通信协议,它们各自适用于不同的应用场景。本文将比较这三种协议,并探讨它们的主要应用领域。 HTTP (超文本传输协议) HTTP  是最常见的协议之一

    2024年02月05日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包