????????自己在做一个视频分析项目的时候,需要将后台读取的视频实时抛转到前台web页面显示,本来是用的是MQTT协议,已经可以满足需求。但是在实时上线测试的时候,发现当图片比较大的时候,会存在页面不能实时显示图片的bug,经过各种分析和研究发现,造成这个问题的主要原因是因为图片数据比较大,上传会存在一定的延迟,而MQTT对响应时间有一定的要求,因此无法实时显示,查阅资料建议使用更具有即时性的协议WebRTC。
????????WebRTC(Web实时通信)是一种用于在Web浏览器之间实现实时通信的开放标准和协议。它允许浏览器之间直接建立点对点的音频、视频和数据通信,无需任何插件或第三方软件。
WebRTC协议的核心技术包括:
1.媒体捕获和传输:WebRTC支持从摄像头和麦克风捕获音视频数据,并使用实时传输协议(RTP)将数据传输给对方浏览器。
2.网络传输:WebRTC使用用户数据协议(UDP)和传输控制协议(TCP)来传输音视频数据。它还使用ICE(Interactive Connectivity Establishment)协议来处理网络连接和穿越NAT(网络地址转换)的问题。
3.信令传输:WebRTC需要一个信令服务器来协调浏览器之间的连接。信令服务器负责交换连接信息,如网络地址和传输协议。WebRTC并没有规定具体的信令协议,开发者可以使用自己喜欢的协议,如WebSocket、HTTP或者XMPP。
4.媒体处理和编解码:WebRTC支持多种音视频编解码器,如VP8、VP9、H.264和Opus。它还提供了一些媒体处理功能,如媒体格式转换、流量控制和噪声抑制。
????????WebRTC的应用场景广泛,包括实时语音和视频通话、视频会议、屏幕共享、远程教育和在线游戏等。它为Web开发者提供了一种简单和便捷的方式来实现实时通信功能,而不需要依赖于第三方插件或软件。
WebRTC具有以下几个优点:
1.简单易用:WebRTC是一个开放标准和协议,可以直接在现代Web浏览器中使用,无需安装任何插件或第三方软件。开发者可以使用简单的JavaScript API来实现实时通信功能。
2.实时性:WebRTC支持实时音视频传输,可以实现高质量、低延迟的实时通信。这对于实时语音和视频通话、视频会议等应用非常重要。
3.点对点通信:WebRTC支持点对点的通信方式,可以直接在浏览器之间建立连接,无需经过中间服务器。这样可以减少延迟和带宽消耗,并提高隐私性。
4.跨平台支持:WebRTC可以在不同的操作系统和设备上使用,包括Windows、macOS、Linux、Android和iOS等。这使得开发者可以轻松地实现跨平台的实时通信应用。
5.开放标准:WebRTC是一个开放的标准和协议,由W3C和IETF等组织制定和维护。这意味着各种浏览器和设备都可以基于WebRTC实现兼容的实时通信功能。
6.安全性:WebRTC提供了端到端的加密和身份验证机制,可以保护用户的通信数据和隐私。它使用SRTP(Secure Real-time Transport Protocol)来加密音视频数据,并使用DTLS(Datagram Transport Layer Security)来加密信令数据。
总的来说,WebRTC具有简单易用、实时性、点对点通信、跨平台支持、开放标准和安全性等优点,使得它成为实现Web实时通信的理想选择。
import asyncio
import cv2
import numpy as np
import aiortc
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription
from aiortc.contrib.media import MediaBlackhole, MediaStreamError
from aiortc.contrib.media import MediaRecorder
from aiortc.contrib.media import MediaPlayer
from aiortc.contrib.signaling import object_from_string, object_to_string
# 创建一个视频轨道类
class VideoTrack(MediaStreamTrack):
def __init__(self):
super().__init__() # 调用父类构造函数
self.video_capture = cv2.VideoCapture(0) # 打开摄像头
async def recv(self):
try:
# 读取摄像头捕获的帧
ret, frame = self.video_capture.read()
if ret:
# 转换帧为JPEG格式
ret, jpeg = cv2.imencode('.jpg', frame)
if ret:
# 将JPEG数据作为媒体流传递给客户端
return aiortc.VideoFrame(jpeg.tobytes(), format='jpeg')
except MediaStreamError as e:
print(e)
# 创建一个信令服务器类
class Signaling:
def __init__(self):
self.pc = None
self.offer = None
async def connect(self):
pass
async def receive(self):
pass
async def send(self, message):
pass
async def on_offer(self, offer):
self.pc = RTCPeerConnection()
# 添加视频轨道到peer连接
self.pc.addTrack(VideoTrack())
# 设置远程描述
await self.pc.setRemoteDescription(offer)
# 创建应答
answer = await self.pc.createAnswer()
# 设置本地描述
await self.pc.setLocalDescription(answer)
# 发送应答给客户端
return self.pc.localDescription
async def on_answer(self, answer):
# 设置远程描述
await self.pc.setRemoteDescription(answer)
async def on_icecandidate(self, candidate):
# 添加ICE候选到peer连接
await self.pc.addIceCandidate(candidate)
# 创建一个信令服务器实例
signaling = Signaling()
# 启动信令服务器
async def run_signaling():
# 连接到信令服务器
await signaling.connect()
while True:
# 等待收到offer
offer = await signaling.receive()
# 处理offer
answer = await signaling.on_offer(offer)
# 发送应答到信令服务器
await signaling.send(answer)
# 等待收到answer
answer = await signaling.receive()
# 处理answer
await signaling.on_answer(answer)
# 等待收到ICE候选
candidate = await signaling.receive()
# 处理ICE候选
await signaling.on_icecandidate(candidate)
# 关闭peer连接
await signaling.pc.close()
# 运行信令服务器
asyncio.ensure_future(run_signaling())
asyncio.get_event_loop().run_forever()