SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播

这篇具有很好参考价值的文章主要介绍了SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

CentOS版本号:7.9
SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端
SRS版本号:4.0.215
SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端
服务器IP:192.168.5.104
SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端
注意需要开启端口号:1935、1985、8000(UDP端口)、8080。
SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端
注意需要开启服务:http
SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端

webRTC介绍

WebRTC是一个由Google发起的实时通讯解决方案,其中包含视频音频采集,编解码,数据传输,音视频展示等功能,我们可以通过技术快速地构建出一个音视频通讯应用。 虽然其名为WebRTC,但是实际上它不光支持Web之间的音视频通讯,还支持Android以及IOS端,此外由于该项目是开源的,我们也可以通过编译C++代码,从而达到全平台的互通。

getUserMedia

为一个 RTC 连接获取设备的摄像头与 (或) 麦克风权限,并为此 RTC 连接接入设备的摄像头与 (或) 麦克风的信号。

RTCPeerConnection

用于配置音频或视频聊天。

RTCDataChannel

用于设置两个浏览器之间的端到端 (en-US) 数据连接。

SRS流媒体服务器

SRS(Simple Realtime Server)是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT/GB28181。
SRS服务自带一个简单的信令服务器,用于webRTC交换SDP,提供了2个接口分别用于发布端(推流)和播放端(拉流)进行SDP交换

推流API:POST /rtc/v1/publish/

使用WebRTC推流到SRS时,需要先调用API交换SDP。例如:

POST /rtc/v1/publish/

Body in JSON:

{
  "api": "https://d.ossrs.net/rtc/v1/publish/"
  "streamurl": "webrtc://d.ossrs.net/live/3abd9f34",
  "sdp": "v=0\r\n......\r\na=ssrc:2064016335 label:c8243ce9-ace5-4d17-9184-41a2543101b5\r\n"
}

服务器响应对应的SDP如下:

{
  "code": 0
  "sdp": "v=0\r\n......\r\na=candidate:1 1 udp 2130706431 172.18.0.4 8000 typ host generation 0\r\n"
  "sessionid": "186tj710:hMub"
}

假如部署SRS服务的服务器IP地址为:192.168.5.104,SRS的http_api监听端口为1985,则推流端交换SDP的API请求地址为:http://192.168.5.104:1985/rtc/v1/publish/,发送post请求

POST /rtc/v1/publish/

Body in JSON:

{
  "api": "http://192.168.5.104:1985/rtc/v1/publish/"
  "streamurl": "webrtc://192.168.5.104:8000/live/stream",
  "sdp": "v=0\r\n......\r\na=ssrc:2064016335 label:c8243ce9-ace5-4d17-9184-41a2543101b5\r\n"
}

拉流API:POST /rtc/v1/play/

拉流或播放时,需要调用另外的API,请求格式和publish一样。例如:

POST /rtc/v1/play/

Body in JSON:

{
  "api": "https://d.ossrs.net/rtc/v1/play/"
  "streamurl": "webrtc://d.ossrs.net/live/3abd9f34",
  "sdp": "v=0\r\n......\r\na=ssrc:2064016335 label:c8243ce9-ace5-4d17-9184-41a2543101b5\r\n"
}

服务器响应对应的SDP如下:

{
  "code": 0
  "sdp": "v=0\r\n......\r\na=candidate:1 1 udp 2130706431 172.18.0.4 8000 typ host generation 0\r\n"
  "sessionid": "186tj710:hMub"
}

SRS服务配置开启RTC服务

SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端

创建web应用

编写代码,vue3项目

<template>
    <div id="box">
        <!-- 设置自动播放,否则不会显示视频流画面 -->
        <video id="video" autoplay></video>
        <div id="btn">
            <button ref="button_one" @click="publish">开始直播</button>
            <button ref="button_two" @click="close" >停止直播</button>
            <button ref="button_three" @click="stopAudio" >关闭声音</button>
            <button ref="button_four" @click="startAudio" >开启声音</button>
            <button ref="button_five" @click="play" >播放直播</button>
        </div>
        
        <video id="video2" autoplay></video>
    </div>
</template>

<script setup>
import { onMounted,ref } from 'vue';
// 定义全局属性
let videoStream = null;
let videoElement = null;
// 全局的RTCPeerConnection
let pc = null;
// 全局音频轨道,用于RTCRtpSender发送和停止对应轨道
let audioTrack = null;
// 全局的RTCRtpSender
let audioSender = null;
// 获取按钮元素
let button_one = ref(null);
let button_two = ref(null);
let button_three = ref(null);
let button_four = ref(null);
let button_five = ref(null);

const publish = async()=>{
        if(pc!==null&& pc!==undefined){
            console.log("已开始推流");
            return ;
        }
            

        var httpURL = "http://192.168.5.104:1985/rtc/v1/publish/";
        var webRTCURL = "webRTC://192.168.5.104/live/1";
        var constraints = {
                audio: {
                    echoCancellation : true,    // 回声消除
                    noiseSuppression : true,    // 降噪
                    autoGainControl  : true     // 自动增益
                },
                video: {
                    frameRate   : { min : 30 },                // 最小帧率
                    width       : { min : 640, ideal : 1080}, // 宽度   
                    height      : { min : 360, ideal : 720},  // 高度  
                    aspectRadio : 16/9                        // 宽高比
                }
}
        // 通过摄像头、麦克风获取音视频流
        videoStream = await navigator.mediaDevices.getUserMedia(constraints);
        // 获取video元素
        videoElement = document.querySelector("#video")
        //video播放流数据
        videoElement.srcObject = videoStream;
        // 静音
        videoElement.volume=0;
        // 创建RTC连接对象
         pc = new RTCPeerConnection();
        
        // RTCPeerConnection方法addTransceiver()创建一个新的RTCRtpTransceiver,并将其添加到与RTCPeerConnection关联的收发器集中。
        // 每个收发器代表一个双向流,RTCRtpSender和RTCRtpReceiver都与之相关联。
        // 注意添加顺序为audio、video,后续RTCPeerConnection创建offer时SDP的m线顺序遵循此顺序创建,SRS自带的信令服务器响应的SDP中m线总是先audio后video。
        // 若本端SDP和远端SDP中的m线顺序不一直,则设置远端描述时会异常,显示offer中的m线与answer中的m线顺序不匹配
        pc.addTransceiver("audio", {direction: "recvonly"});
        pc.addTransceiver("video", {direction: "recvonly"});
        // 遍历getUserMedia()获取到的流数据,拿到其中的音频轨道和视频轨道,加入到RTCPeerConnection连接的音频轨道和视频轨道中
        videoStream.getTracks().forEach((track)=>{
            pc.addTrack(track);
        });
        // 创建本端offer
        var offer = await pc.createOffer();
        // 设置本端
        await pc.setLocalDescription(offer);
        var data = {
            "api": httpURL,
            "streamurl":webRTCURL,
            "sdp":offer.sdp
        }
        // SDP交换,请求SRS自带的信令服务器
        httpApi(httpURL,data).then(async(data)=>{
            console.log("answer",data);
            // 设置远端描述,开始连接
            await pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: data.sdp}));
                button_one.value.disabled=true;
                button_two.value.disabled=false;
                button_three.value.disabled=false;
                button_five.value.disabled=false;

        }).catch((data)=>{
            if(data.code===400){
                console.log("SDP交换失败");
            }
        });
        
    
}

const play = async()=>{
    var httpURL = "http://192.168.5.104:1985/rtc/v1/play/";
    var webRTCURL = "webRTC://192.168.5.104/live/1";
    // 创建RTCPeerConnection连接对象
    var pc = new RTCPeerConnection();
    // 创建媒体流对象
    var stream = new MediaStream();
    // 获取播放流的容器video
    var videoElement2 = document.querySelector("#video2");
    // 监听流
    pc.ontrack = (event)=>{
        // 监听到的流加入MediaStream对象中让video播放
        stream.addTrack(event.track);
        videoElement2.srcObject = stream;
    }
    // RTCPeerConnection方法addTransceiver()创建一个新的RTCRtpTransceiver,并将其添加到与RTCPeerConnection关联的收发器集中。
    // 每个收发器代表一个双向流,RTCRtpSender和RTCRtpReceiver都与之相关联。
    // 注意添加顺序为audio、video,后续RTCPeerConnection创建offer时SDP的m线顺序遵循此顺序创建,SRS自带的信令服务器响应的SDP中m线总是先audio后video。
    // 若本端SDP和远端SDP中的m线顺序不一直,则设置远端描述时会异常,显示offer中的m线与answer中的m线顺序不匹配
    pc.addTransceiver("audio", {direction: "recvonly"});
    pc.addTransceiver("video", {direction: "recvonly"});

    var offer =await pc.createOffer();
    await pc.setLocalDescription(offer)
    var data = {
            "api": httpURL,
            "streamurl":webRTCURL,
            "sdp":offer.sdp
    }
    // SDP交换,请求SRS自带的信令服务器
    httpApi(httpURL,data).then(async(data)=>{
            console.log("answer",data);
            // 设置远端描述,开始连接
            await pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: data.sdp}));
            button_five.value.disabled=true;

    }).catch((data)=>{
            if(data.code===400){
                console.log("SDP交换失败");
            }
    });
}

// 关闭连接
const close = ()=>{
    if(pc!==null&&pc!==undefined){
        pc.close();
        pc = null;
        button_one.value.disabled=false;
        button_two.value.disabled=true;
        button_three.value.disabled=true;
        button_four.value.disabled=true;
        button_five.value.disabled=true;
    }
}
// 关闭音频
const stopAudio = ()=>{
    if(pc!==null&&pc!==undefined){
        // RTCPeerConnection方法getSenders()返回RTCRtpSender对象的数组,
        // 每个对象代表负责传输一个轨道的数据的RTP发送器。
        // sender对象提供了检查和控制音轨数据的编码和传输的方法和属性。
        pc.getSenders().forEach((sender)=>{
            if(sender.track!==null&&sender.track.kind==="audio"){
                // 拿到音频轨道
                audioTrack = sender.track;
                // 拿到音频轨道发送者对象RTCRtpSender
                audioSender = sender;
                // RTCRtpSender的replaceTrack()可以在无需重新媒体协商的情况下用另一个媒体轨道更换当前正在发送轨道
                // 参数为空则将当前正在发送的轨道停止,比如关闭音频,再次开启时将音频轨道作为参数传入
                audioSender.replaceTrack(null);
                button_three.value.disabled=true;
                button_four.value.disabled=false;
            }
        });
    }
}
// 开启音频
const startAudio = ()=>{
    console.log(audioSender);
    if(pc!==null&&pc!==undefined){
       if(audioSender.track===null){
        audioSender.replaceTrack(audioTrack);
        button_three.value.disabled=false;
        button_four.value.disabled=true;
       }
    }
}

const httpApi = (httpURL,data)=>{
    var promise = new Promise((resolve,reject)=>{
        var xhr = new XMLHttpRequest();
        xhr.open('POST', httpURL, true);
        xhr.setRequestHeader('Content-type', 'application/json');
        xhr.send(JSON.stringify(data));
        xhr.onload = ()=>{
                if (xhr.readyState !== xhr.DONE) reject(xhr);
                if (xhr.status !== 200 && xhr.status !== 201) reject(xhr) ;
                var data = JSON.parse(xhr.responseText);
                if(data.code===0){
                    resolve(data);
                }else{
                    reject(data)
                }
            }
    });
    return promise;
}

onMounted(()=>{
    button_one.value.disabled=false;
    button_two.value.disabled=true;
    button_three.value.disabled=true;
    button_four.value.disabled=true;
    button_five.value.disabled=true;
});

</script>

<style lang="scss">
*{
    margin: 0;
    padding: 0;
    border: 0;
    box-sizing: border-box;
}
#box{
    width: 100%;
    text-align: center;
}
video{
    background-color: black;
    width: 500px;
    height: 400px;
    object-fit: cover;
}
#btn{
    width: 80%;
    height: 100px;
    display: flex;
    margin:10px 10%;
}
button{
    flex: 1;
    height: 100px;
    background-color: aqua;
    border-radius: 20px;
    margin-left: 10px;
}
button:nth-child(1){
    margin-left: 0;
}
</style>

运行代码

SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播,SRS流媒体,前端,vue,webrtc,音视频,前端
2个客户端双向推拉流即可实现实时视频通话文章来源地址https://www.toymoban.com/news/detail-654993.html

到了这里,关于SRS流媒体服务(四)WebRTC实现实时视频通话和低延时互动直播的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Qt推流程序自动生成网页远程查看实时视频流(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)

    推流程序将视频流推送到流媒体服务器后,此时就等待验证拉流播放,一般可以选择ffplay命令行播放或者vlc等播放器打开播放,也可以选择网页直接打开拉流地址播放,一般主流的浏览器都支持网页直接播放hls/m3u8/webrtc类型的视频流,而且推流的主要目的可能就是为了能够在

    2024年02月05日
    浏览(80)
  • 搭建SRS流媒体服务器

    一、获取 SRS git clone https://github.com/ossrs/srs cd srs/trunk 二、编译SRS ./configure make 三、编写SRS配置文件(我的这个文件是原始的,未修改) vim conf/srs.conf 四、启动SRS ./objs/srs -c conf/srs.conf 五、启动ip摄像头进行推流 手机下载一个ip摄像头软件,然后设置中修改RTMP推流地址 rtmp://你的阿里

    2024年02月16日
    浏览(48)
  • SRS流媒体服务器——Forward集群搭建和源码分析

    Forward集群原理 RTMP流转发(Forward)部署实例 Forward集群源码分析 Forward 表示向前、前头的、发送等意思。 在SRS中可以理解为把Master节点获得直播流⼴播(转发)给所有的Slave节点,master节点由多少路直播流,那么在每个slave节点也会多少路直播流。 注:在SRS中还有另外⼀种集

    2023年04月11日
    浏览(100)
  • 【音视频流媒体】2、WebRTC 直播超详细介绍

    一对一直播框架: WebRTC终端: 音视频采集, 编解码, NAT穿越, 音视频数据传输 Signal服务器: 信令处理(如加入房间, 离开房间, 传递媒体协商消息) STUN/TURN服务器: 获取WebRTC终端在公网的IP地址, NAT穿越失败后的数据中转. js中 var promise = navigator.mediaDevices.getUserMedia(constraints); 可访问摄

    2023年04月18日
    浏览(50)
  • 流媒体服务器SRS的搭建及QT下RTMP推流客户端的编写

        目前市面上有很多开源的流媒体服务器解决方案,常见的有SRS、EasyDarwin、ZLMediaKit和Monibuca。这几种的对比如下: (本图来源:https://www.ngui.cc/zz/1781086.html?action=onClick)     SRS(Simple Real-time Server)是一个开源的流媒体服务器,它支持RTMP、HLS、HTTP-FLV等多种流媒体协议

    2024年02月11日
    浏览(48)
  • linux+nginx-http-flv-module+ffmpeg实现搭建简易流媒体服务器将rtsp流转flv格式在web端和微信小程序实时播放监控视频

    一.介绍背景 公司项目开发需求:将海康摄像头的rtsp流在web端及微信小程序端进行播放。之前我写过一篇关于web端使用webtrc+videojs播放rtsp流的文章,确实能够解决web端播放rtsp流的需求,但是这次多加了一个微信小程序....所以要考虑小程序的播放问题。本着探索实践的精神在

    2024年02月08日
    浏览(73)
  • H.265视频无插件流媒体播放器EasyPlayer.js播放webrtc断流重连的异常修复

    H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放,可支持H.264与H.265编码格式,性能稳定、播放流畅,能支持WebSocket-FLV、HTTP-FLV,HLS(m3u8)、WebRTC等格式的视频流,并且已实现网页端实时录像、在iOS上实现低延时直

    2024年02月10日
    浏览(62)
  • 使用EasyDarwin + ffmpeg 搭建流媒体服务器,实现多台智能电视同步播放宣传视频

    近期单位用户提出需求,需要在单位内部的9台安卓智能电视(小米电视)上同步播放用户提供的宣传视频,希望能够做到所有电视音视频同步播放(电视均位于食堂内部,使用内置扬声器,各电视间音频延迟不同会导致混响) 。 由于电视在安装时只预留了电源线,使用HDM

    2024年02月10日
    浏览(79)
  • 【FAQ】H.265视频无插件流媒体播放器EasyPlayer.js播放webrtc断流重连的异常修复

    H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放,可支持H.264与H.265编码格式,性能稳定、播放流畅,能支持WebSocket-FLV、HTTP-FLV,HLS(m3u8)、WebRTC等格式的视频流,并且已实现网页端实时录像、在iOS上实现低延时直

    2024年02月11日
    浏览(63)
  • Qt推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远程观看

    推流直播就是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号从手机端,电脑端,摄影机端打包传到服务器的过程。“推流”对网络要求比较高,如果网络不稳定,直播效果就会很差,观众观看直播时就会发生卡顿等现象,观看体验比较糟糕。主流

    2024年02月04日
    浏览(73)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包