前端音视频开发

一.视频推流与拉流

推流,指的是把采集阶段封包好的内容传输到服务器的过程。
在这里插入图片描述

拉流,指的是服务器已有直播内容,用指定地址进行拉取的过程
在这里插入图片描述

二. 主流的推送协议和优缺点

1.RTMP协议
(1)是流媒体协议。
(2)RTMP协议是 Adobe 的私有协议,未完全公开。
(3)RTMP协议一般传输的是 flv,f4v 格式流。
(4)RTMP一般在 TCP 1个通道上传输命令和数据。
(5) 优势在于低延迟,稳定性高,支持所有摄像头格式,浏览器加载 flash插件就可以直接播放。
(6) 不支持浏览器,且Adobe已不再更新。因此直播服务要支持浏览器的话,需要另外的推送协议支持。

2.RTSP协议
(1)是流媒体协议。
(2)RTSP协议是共有协议,并有专门机构做维护。.
(3)RTSP协议一般传输的是 ts、mp4 格式的流。
(4)RTSP传输一般需要 2-3 个通道,命令和数据通道分离。
(5) RTSP实时效果非常好,适合视频聊天,视频监控等方向。
(6) RTSP虽然实时性最好,但是实现复杂,适合视频聊天和视频监控;RTMP强在浏览器支持好,加载flash插件后就能直接播放,所以非常火,相反在浏览器里播放rtsp就很困难了。

3.HLS协议
Http Live Streaming是由Apple公司定义的基于HTTP的流媒体实时传输协议。它的原理是将整个流分为多个小的文件来下载,每次只下载若干个。服务器端会将最新的直播数据生成新的小文件,客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播。基本上,HLS是以点播的技术实现了直播的体验。因为每个小文件的时长很短,客户端可以很快地切换码率,以适应不同带宽条件下的播放。
分段推送的技术特点,决定了HLS的延迟一般会高于普通的流媒体直播协议。
传输内容包括两部分:一是M3U8描述文件,二是TS媒体文件。TS媒体文件中的视频必须是H264编码,音频必须是AAC或MP3编码。
由于数据通过HTTP协议传输,所以完全不用考虑防火墙或者代理的问题,而且分段文件的时长很短。

4.HTTP协议
(1)不是是流媒体协议,通常用来做点播
(2)HTTP协议是共有协议,并有专门机构做维护。
(3)HTTP协议没有特定的传输流。
(4)HTTP传输一般需要 2-3 个通道,命令和数据通道分离。

5.WebRTC
WebRTC(Web Real-Time Communication),即“源自网页即时通信”。WebRTC是一个支持浏览器进行实时语音、视频对话的开源协议。WebRTC的支持者甚多,Google、Mozilla、Opera推动其成为W3C推荐标准。WebRTC支持目前的主流浏览器,并且基于SRTP和UDP,即便在网络信号一般的情况下也具备较好的稳定性。此外,WebRTC可以实现点对点通信,通信双方延时低,此外,WebRTC可以实现点对点通信,通信双方延时低,是实现“连麦”功能比较好的选择。

RTMP、RTSP的区别
前提知识:从网络上接收视频时首先要解协议(RTSP/RTMP/HTTP),然后是解格式(MKV,RMVB),之后才是将视频(H264)和音频(AAC)格式数据分别解码为图像(RGB/YUV)和声音(PCM),再根据时间戳同步播放。
总结:先解协议(RTSP/RTMP/HTTP),再解格式(MKV,RMVB),最后将视频(H264)和音频(AAC)格式数据解码为图像
  RTSP+RTP主要用于IPTV,原因是传输数据使用的是UDP,在网络环境比较稳定的情况下,传输效率是比较高的;
  RTMP主要用于互联网音视频传输,它使用的是TCP传输,因为互联网环境相对较差,采用RTMP保证了视频的传输质量,但是其传输延迟相对较高,传输效率相对较低。
  使用RTMP技术的流媒体系统有一个非常明显的特点:使用 Flash Player 作为播放器客户端,而Flash Player 现在已经安装在了全世界将近99%的PC上,因此一般情况下收看RTMP流媒体系统的视音频是不需要安装插件的。用户只需要打开网页,就可以直接收看流媒体,十分方便。直播服务普遍采用了RTMP作为流媒体协议,FLV作为封装格式,H.264作为视频编码格式,AAC作为音频编码格式。FLV是RTMP使用的封装格式,H.264是当今实际应用中编码效率最高的视频编码标准,AAC则是当今实际应用中编码效率最高的音频编码标准。

拓展资料
为什么现在的视频直播不使用RTSP协议而是使用RTMP?

三. websoket

看完让你彻底理解 WebSocket 原理,附完整的实战代码(包含前端和后端)
html5-websocket初探
websoket概念基础
WebSocket协议深入理解
基于WebSocket前端开发H.264流实现视频实时播放

webSoket概念总结:
WebSocket是为解决客户端与服务端实时通信而产生的技术。其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信
在这里插入图片描述

ArrayBuffer 和 Blob 对象
ArrayBuffer类型化数组
在这里插入图片描述

前端代码demo:

文件目录截图:
在这里插入图片描述

<!DOCTYPE html>
<html>
<script src="wfs/wfs.js"></script>

<body>
    <div>
        <p>ip:<input id="host" value="192.168.0.133" /></p>
        <p>端口:<input id="port" value="9999" />
            <button id="btn" onclick="play()">连接</button>
            <button id="btn" onclick="reload1()">刷新</button>
        </p>
        <video id="video" style="height: 500px; width: 500px"></video>
    </div>
    <script>
        function play() {
            // console.log(1)
            // let ws = new WebSocket('ws://192.168.0.133:2345')
            // ws.onopen = function() {
            //     ws.send('start')
            // }
            // 除了动态判断收到的数据类型,也可以使用binaryType属性,显式指定收到的二进制数据类型

            // 收到的是 ArrayBuffer 数据 ArrayBuffer 对象代表储存二进制数据的一段内存
            // ArrayBuffer是js操作二进制数据的一个接口,它是以数组的语法处理二进制数据,也称二进制数组
            // ws.binaryType = 'arraybuffer'

            // 收到的是 blob 数据 binary Large Object (二进制大型对象)
            // Blob 对象表示一个二进制文件的数据内容,通常用来读写文件,比如一个图片文件的内容就可以通过 Blob 对象读写
            // ws.binaryType = "blob";
            
            // ArrayBuffer和blob的区别
            // Blob 用于操作二进制文件
            // ArrayBuffer 用于操作内存

            // ws.onopen = function () {
            //     ws.send('start')
            // }

            // ws.onmessage = function (msg) {
            //     console.log(typeof msg , msg.data) // object
            //     console.log(msg.data) // ArrayBuffer(80) {}
            //     console.log(msg.data.toString()) // [object ArrayBuffer]
            // }
            // ws.onclose = function (msg) {
            //     console.log(msg + "Connection closed.");
            // }
            if (Wfs.isSupported()) {
                const ip = document.getElementById('host').value
                const port = document.getElementById('port').value
                const video1 = document.getElementById('video')
                const wfs = new Wfs()
                wfs.attachMedia(video1, ip, port)
            }
        }
        function reload1() {
            window.location.reload()
        }
    </script>
</body>

</html>

后端服务器(使用node生成)

文件目录结构:
在这里插入图片描述

const fs = require('fs')
const path = require('path')

const fileName = path.join(__dirname, 'b1.tlv')
const typeUseByte = 4 // 类型占用字节
const lengthUseByte = 4 // 长度占用字节
let readedByte = 0 // 已读已发送字节长度

const WebSocket = require('ws')
const wss = new WebSocket.Server({
//   host: 'localhost',
  host: '192.168.0.133',
  port: 9999,
  // perMessageDeflate: {
  //   serverMaxWindowBits: 20
  // }
})

let ws1

console.log('socket已打开')
wss.on('connection', function (ws) {
  console.log(ws)
  ws1 = ws
  ws.on('message', function(message) {
    console.log('server: 收到')
    fs.open(fileName, 'r', function(err, fd) {
      console.log('文件已打开')
      const array = []
      if (err) {
        throw err
      }
      fs.readFile(fileName, function(err, data) {
        console.log('文件已读取')

        if (err) {
          throw err
        }
        while (readedByte < data.length) {
          const typeBuffer = data.slice(readedByte, readedByte + typeUseByte)
          // typeBuffer = typeBuffer.reverse()
          const type = typeBuffer // hex2int(typeBuffer.toString('hex'))

          readedByte += typeUseByte
          let lengthBuffer = data.slice(readedByte, readedByte + lengthUseByte)
          // console.log(lengthBuffer)
          // console.log(lengthBuffer)
          const length = hex2int(lengthBuffer.reverse().toString('hex'))
          lengthBuffer = lengthBuffer.reverse()

          readedByte += lengthUseByte

          const val = data.subarray(readedByte - 8, readedByte + length)
          readedByte += length
          // console.log(val)
          // wss.clients.forEach(client => {
          //   if (client.readyState === WebSocket.OPEN) {
          //     client.send(val)
          //   }
          // })
          ws.send(val)
          array.push({
            type,
            length,
            val
          })
        }
        console.log('文件已发送')

        fs.close(fd, function() {
          readedByte = 0
          console.log('文件关闭')
        })
      })
    })
  })
  // ws.send('server: hello,client')
})

function hex2int(i) {
  let two = parseInt(i, 16).toString(2)
  const bitNum = i.length * 4
  if (two.length < bitNum) {
    while (two.length < bitNum) {
      two = '0' + two
    }
  }

  if (two.substring(0, 1) == '0') {
    two = parseInt(two, 2)
    return two
  } else {
    let two_unsign = ''
    two = parseInt(two, 2) - 1
    two = two.toString(2)

    two_unsign = two.substring(1, bitNum)
    two_unsign = two_unsign.replace(/0/g, 'z')

    two_unsign = two_unsign.replace(/1/g, '0')

    two_unsign = two_unsign.replace(/z/g, '1')
    console.log(parseInt(-two_unsign, 10))
    two = parseInt(-two_unsign, 2)

    return two
  }
}

服务端操作需要注意两点
1.如果使用的ws模块,那么需要安装node里的ws,npm install ws
详细请戳Websocket之ws模块(一)

在这里插入图片描述
2.如果使用nodejs-websocket,需要先安装nodejs-websocket,npm install nodejs-websocket
在这里插入图片描述
详细请戳nodejs-websocket 的简单用法和安装
2.在进行前端视频播放的时候,需要开启node服务指令, node index.js

注意事项

开启防火墙端口号,上述代码中我指定的webSoket通信端口号是9999。
记得在防火墙“出站规则”这里新建规则,选择端口号9999即可在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完成之后可以看下自己设置的端口信息
在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值