srs+webrtc实现浏览器直播(仿b站页面,纯前端)

历届足球世界杯 2025-05-10 23:47:56

关于srs请看我之前的博客,SRS实现网页和手机端简单直播。

与之不同的是,浏览器推流需要使用werbrtc,因此只需要按srs官网配置即可,WebRTC | SRS (ossrs.net)。回到正题...

一.页面搭建

b站web直播页面是通过video标签元素实现,但是video并不能同时将摄像头、麦克风、屏幕共享等同时呈现出来,所以猜测是用的canvas,将不同素材通过画布呈现,同时把canvas的流放到video上。

1.我们要实现这个画布,首先需要使用webrtc(没有接触过的去看官网WebRTC API),在webrtc中,MediaDevices接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据。

enumerateDevices() 请求一个可用的媒体输入和输出设备的列表。

getDisplayMedia() 方法提供授权捕获展示的内容或部分内容(如一个窗口)。

getUserMedia() 会提示用户使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道、一个音频轨道,也可能是其他轨道类型。

2.使用canvas标签,npm下载Fabric.js,Fabric.js 简化了很多 Canvas 里的概念,Fabric.js 语法更加简单易用,而且还提供了很多交互类的 api,更重要的是fabric.js操作canvas自带拖拽拉伸旋转效果。

首先通过fabric.canvas生成一个画布,但由于屏幕共享和摄像头都是视频类,所以可以通过document.createElement('video')创建video元素,并将获取到的MediaStream赋给video.srcObject,之后通过fabric.Image(video),将video中每一帧画面生成,同时还可以设置生成好的画面的宽高以及在哪个位置出现。(其他属性请到Fabric.js官网查看)之后通过fabric.canvas.add即可添加到画布中观看。

var canvasDom = new fabric.Image(videoEl, {

top: 0,

left: 0,

width,

height,

objectCaching: false

});

以此类推,实现以下素材的添加,同时在画布中显示(示例图片中包含摄像头、窗口、图片)

3.生成好画面后,需要将这添加的素材保存起来,并且可以删改。关于这个问题,可以新建数据类型tracks:[],存放素材数据。如下(要根据实际情况更改):

const mediaVideoTrack = {

id: id,

audio: 1,//是否开启音频流

video: 1,//是否开启视频流

mediaName: that.mediaName,//素材名称

type: 'Media',//素材类型(有media、text等)

track: undefined,//轨道

trackid: undefined,//轨道id

stream: undefined,//媒体流

streamid: undefined,//媒体流id

canvasDom:canvasDom,//fabric.Image元素

videoEl:videoEl,//video元素

volume:80,//音量

hidden: false,//是否隐藏

muted: false,//是否静音播放

scaleInfo: {},//缩放比例

};

实现如下,可以隐藏或呈现某个素材,修改仅限修改名称,不可修改内容,删除需要把fabric.canvas中与tracks中相同的删除。

二.推流和拉流功能

推拉流功能是使用WebRTC+SRS实现的,webrtc和srs具体原理不在这里赘述,详情请查百度。

由于SRS中自带简单的信令服务器,所以在使用WebRTC中的RTCPeerConnection时只需交换sdp,设置setLocalDescription和setRemoteDescription,之后按照srs提供的api进行sdp交换来实现媒体流的推送。

代码示例(该代码借鉴csdn某大佬(忘记是哪个了🤦‍),其中包括推流和拉流):

推流/拉流示例代码

在本系统中,需要将上述代码中的摄像头stream换成画布的流canvas.captureStream()即可实现。

三.效果展示

四.需要改进的地方

1.添加帧率、分辨率、码率的调整

2.该项目为纯前端,后期加入后端实现多个直播间

3.音量调控不合理,需优化

4.实现送礼物功能

五.项目源码

总结:若有问题或者有其他想法,期待一起交流,后期会更新聊天室功能

由于原项目使用vue2,所以二开用vue2