当前位置:首页 » 《我的小黑屋》 » 正文

WebRTC播放组件之 srs.sdk.js 使用与详述

27 人参与  2024年10月18日 09:20  分类 : 《我的小黑屋》  评论

点击全文阅读


1、简介

webrtc流媒体的播放,本质上也是基于建立端到端的RTC连接、接收推送过来的视频流数据的过程。webrtc流地址本质上就具有很强的规则性,其中包含信令服务器地址、基本参数等。

SRS(Simple Real-Time Media Server)是一个强大的开源的流媒体服务器, webrtcs视频流的播放本身就是一个订阅(播放)的过程,因此 SRS 源码中自然包含播放的代码,即 srs.sdk.js

srs.sdk.js 是基于 SRS 实时视频服务器、对浏览器支持的 WebRTC 基础功能的封装。

github 地址

2、使用

2.1、引入

从官网下载好 srs.sdk.js 文件,将此文件放入项目中的静态文件夹;通过 CDN 方式引入,即 例: <script src="./static/webrtc/srs.sdk.js"></script>暴露出实现函数 SrsRtcPlayerAsync 

2.2、函数说明

通过构造函数 SrsRtcPlayerAsync 实例化出对象(本文用 sdk 定义),对象的属性:pc -- RTCPeerConnection() 实例化对象;stream -- 实例化MediaStream()对象对象的方法:play() -- 初始化播放的代码;close() -- 关闭播放的方法

2.3、基本实现代码

下面是基本的实现代码,在 vue 中的写法

    <video         width="100%"         height="100%"         autoplay         muted         class="screen-full-db"         :id="`webrtc-video-${uid}`"    ></video>
            // 获取实例化对象,参数传入失败回调函数            this.sdk = new SrsRtcPlayerAsync(this.sdkInitError);            // 监听 webrtc 建立状态            this.sdk.pc.addEventListener("iceconnectionstatechange", data => {                if (data.target.iceConnectionState == "disconnected") {                    this.$emit("disconnected");                }            });            // 将获取的视频流 给 video 的 srcObject            $(`#webrtc-video-${this.uid}`).prop("srcObject", this.sdk.stream);            // 初始化代码            try {                // play() 初始化播放代码,参数:webrtc流地址                this.sdk.play(this.src).then(                    res => {}                )            } catch (error) {                // 错误回调            }            // 关闭播放器            this.sdk.close();

再简化一下:

        let sdk = new SrsRtcPlayerAsync(sdkInitErrorCallback);        $(`#webrtc-video-id`).prop("srcObject", sdk.stream);        sdk.play(src)

基本实现就基本完成了,十分的简单简便。

3、源码简述

这一部分会源码进行基本的介绍,源码也是十分的通俗易懂。

 3.1、基本结构

        function SrsRtcPlayerAsync() {            var self = {};            // Close the player.            self.play = async function (url) { }            // The callback when got remote track.            // Note that the onaddstream is deprecated, @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onaddstream            self.ontrack = function (event) {}            // Internal APIs.            self.__internal = {}            self.pc = new RTCPeerConnection(null);            // Create a stream to add track to the stream, @see https://webrtc.org/getting-started/remote-streams            self.stream = new MediaStream();            // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/ontrack            self.pc.ontrack = function (event) {}            return self;        }

函数的基本结构没什么好讲的,主要注意一个小tip,通过实例化去 new 这个函数,函数有返回值且为引用类型,实例化对象就是返回的对象。

3.2、play 方法

主要看 play 方法具体如何实现:

            self.play = async function (url) {                var conf = self.__internal.prepareUrl(url);                self.pc.addTransceiver("audio", { direction: "recvonly" });                self.pc.addTransceiver("video", { direction: "recvonly" });                //self.pc.addTransceiver("video", {direction: "recvonly"});                //self.pc.addTransceiver("audio", {direction: "recvonly"});                var offer = await self.pc.createOffer();                await self.pc.setLocalDescription(offer);                var session = await new Promise(function (resolve, reject) {                    // @see https://github.com/rtcdn/rtcdn-draft                    var data = {                        api: conf.apiUrl, tid: conf.tid, streamurl: conf.streamUrl,                        clientip: null, sdp: offer.sdp                    };                    console.log("Generated offer: ", data);                    const xhr = new XMLHttpRequest();                    xhr.onload = function () {                        if (xhr.readyState !== xhr.DONE) return;                        if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);                        const data = JSON.parse(xhr.responseText);                        console.log("Got answer: ", data);                        return data.code ? reject(xhr) : resolve(data);                    }                    xhr.open('POST', conf.apiUrl, true);                    xhr.setRequestHeader('Content-type', 'application/json');                    xhr.send(JSON.stringify(data));                });                await self.pc.setRemoteDescription(                    new RTCSessionDescription({ type: 'answer', sdp: session.sdp })                );                session.simulator = conf.schema + '//' + conf.urlObject.server + ':' + conf.port + '/rtc/v1/nack/';                return session;            };
一开始调用 __internal 对象中 prepareUrl 方法,通过 webrtc 流地址解析得到信令服务器URL地址,从而完成媒体协商。前面说过webrtc的流地址是规则性很强的,在SRS的源码里面体现了。这里如果信令服务器不是通过webrtc地址获取的,可以自行在代码中修改。获取本地SDP,开始媒体协商请求,拿到远程SDP,并设置。返回SDP信息。

3.3、ontrack

            self.pc.ontrack = function (event) {                if (self.ontrack) {                    self.ontrack(event);                }            };            self.ontrack = function (event) {                // https://webrtc.org/getting-started/remote-streams                self.stream.addTrack(event.track);            };

pc.ontrack 回调事件监听媒体流数据,并添加track到stream。

webrtc 播放还可以使用 jswebrtc.js 库,可看:WebRTC播放组件之 jswebrtc 使用与详述


点击全文阅读


本文链接:http://zhangshiyu.com/post/173443.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1