需要先与服务端建立一个连接

发布时间:2025-06-24 19:43:31  作者:北方职教升学中心  阅读量:263


HttpPost(),发送:offer.sdp 到推流端,服务端收到offer.sdp,再返回回来。监听 sendChannel.onopen 连接是否建立成功。

二、

this.pc.setRemoteDescription(newRTCSessionDescription({type:'answer',sdp:window.atob(answerSdp)}));

7、

h5播放WebRTC,WebRTC(Web Real-Time Communication)是一种基于网页浏览器的开源项目,提供了实时音视频传输、数据共享等功能,现在各大浏览器已经逐渐加大对WebRTC技术的支持,实现WebRTC的视频推流,播放WebRTC流。创建PeerConnection对象等

this.pc =newRTCPeerConnection(null);this.pc.ontrack=(event)=>{this._mediaElement['srcObject']=event.streams[0];};this.pc.addTransceiver('audio',{direction:'recvonly'});this.pc.addTransceiver('video',{direction:'recvonly'});this.sendChannel =this.pc.createDataChannel('keepalive');this.sendChannel.onclose =this.onChannelClose.bind(this);this.sendChannel.onopen =this.onChannelOpen.bind(this);this.sendChannel.onmessage =this.onChannelMessage.bind(this);this.pc.createOffer({offerToReceiveVideo:!0,offerToReceiveAudio:!0}).then((offer)=>{returnthis.pc.setLocalDescription(offer).then(()=>{returnoffer;});}).then((offer)=>{returnnewPromise((resolve,reject)=>{this.HttpPost(url,window.btoa(offer.sdp)).then((res)=>{resolve(res);},function(rej){reject(rej);});});}).then((answerSdp)=>{returnthis.pc.setRemoteDescription(newRTCSessionDescription({type:'answer',sdp:window.atob(answerSdp)}));}).then(()=>{this._isLoad =true;}).catch((reason)=>{throwreason;});

2、服务器推流,前端开始播放。需要先与服务端建立一个连接。ontrack回调中将媒体播放地址,绑定到video上。设置ICE服务器配置、
4、初始化WebRTC连接。
9、完整代码

importPlayerEvents from'../FlvPlayer/flv.js/player/player-events';importEventEmitter from'events';import*ascommon from'../common/common';exportdefaultclassWebRtcPlayer{constructor(url,options){this.TAG='WebRtcPlayer';this._type ='WebRtcPlayer';this._emitter =newEventEmitter();// this.options = options || {};this.pc =null;this._mediaElement =null;this.url =url;this.autoplay =!!options.autoplay ||false;this.typeCallback =options.typeCallback;this.statusCallback =options.statusCallback;if(!url.match(/^webrtc?:\/\/||^webrtcs?:\/\//)){throw('JSWebrtc just work with webrtc');}this.timer =null;this.sendChannel =null;this._mediaInfo =null;this._statisticsInfo =null;this.isPlaying =false;this._isLoad =false;this._isDestroy =false;this.e ={onvLoadedMetadata:this._onvLoadedMetadata.bind(this),onvSeeking:this._onvSeeking.bind(this),onvCanPlay:this._onvCanPlay.bind(this),onvPlay:this._onvPlay.bind(this),onvStalled:this._onvStalled.bind(this),onvProgress:this._onvProgress.bind(this),onvWaiting:this._onvWaiting.bind(this),onvPlaying:this._onvPlaying.bind(this)};this.attachMediaElement(options.mediaElement,url);}on(event,listener){if(event ===PlayerEvents.MEDIA_INFO){if(this._mediaInfo !=null){Promise.resolve().then(()=>{this._emitter.emit(PlayerEvents.MEDIA_INFO,this.mediaInfo);});}}elseif(event ===PlayerEvents.STATISTICS_INFO){if(this._statisticsInfo !=null){Promise.resolve().then(()=>{this._emitter.emit(PlayerEvents.STATISTICS_INFO,this.statisticsInfo);});}}this._emitter.addListener(event,listener);}off(event,listener){this._emitter.removeListener(event,listener);}attachMediaElement(mediaElement,url){this._mediaElement =mediaElement;this._mediaElement =mediaElement;mediaElement.addEventListener('loadedmetadata',this.e.onvLoadedMetadata);mediaElement.addEventListener('seeking',this.e.onvSeeking);mediaElement.addEventListener('canplay',this.e.onvCanPlay);mediaElement.addEventListener('play',this.e.onvPlay);mediaElement.addEventListener('stalled',this.e.onvStalled);mediaElement.addEventListener('progress',this.e.onvProgress);mediaElement.addEventListener('waiting',this.e.onvWaiting);mediaElement.addEventListener('playing',this.e.onvPlaying);this.typeCallback(!false);this.load(url);}load(url){this.statusCallback(0);if(this.pc){this.pc.close();}this.pc =newRTCPeerConnection(null);this.pc.ontrack=(event)=>{this._mediaElement['srcObject']=event.streams[0];};this.pc.addTransceiver('audio',{direction:'recvonly'});this.pc.addTransceiver('video',{direction:'recvonly'});this.sendChannel =this.pc.createDataChannel('keepalive');this.sendChannel.onclose =this.onChannelClose.bind(this);this.sendChannel.onopen =this.onChannelOpen.bind(this);this.sendChannel.onmessage =this.onChannelMessage.bind(this);this.pc.createOffer({offerToReceiveVideo:!0,offerToReceiveAudio:!0}).then((offer)=>{returnthis.pc.setLocalDescription(offer).then(()=>{returnoffer;});}).then((offer)=>{returnnewPromise((resolve,reject)=>{this.HttpPost(url,window.btoa(offer.sdp)).then((res)=>{resolve(res);},function(rej){reject(rej);});});}).then((answerSdp)=>{returnthis.pc.setRemoteDescription(newRTCSessionDescription({type:'answer',sdp:window.atob(answerSdp)}));}).then(()=>{this._isLoad =true;}).catch((reason)=>{throwreason;});}onChannelClose(){clearInterval(this.timer);if(!this._isDestroy){common.sleep(3000).then(()=>{this.load(this.url);});}}onChannelOpen(){this.timer =setInterval((()=>{if(this.sendChannel){this.sendChannel.send('ping');}}),3000);}onChannelMessage(){// console.log('onmessage');}HttpPost(url,data){returnnewPromise((resolve,reject)=>{varxhr =newXMLHttpRequest();xhr.onreadystatechange=()=>{if(xhr.readyState ===4&&(xhr.status >=200&&xhr.status <300)){varrespone =xhr.responseText;xhr.onreadystatechange =newFunction;xhr =null;resolve(respone);}};xhr.open('POST',url.replace('webrtc','http'),true);xhr.send(data);});}_onvLoadedMetadata(){}_onvSeeking(){}_onvCanPlay(){if(this.autoplay){this._mediaElement.play();}}_onvPlay(){this.isPlaying =true;this.statusCallback(100);}_onvStalled(){}_onvProgress(){}_onvWaiting(){}_onvPlaying(){}unload(){}play(){if(!this.isPlaying){this._mediaElement.play();this.isPlaying =true;}}pause(){if(this.isPlaying){this._mediaElement.pause();this.isPlaying =false;}}resume(){}openAudio(){}closeAudio(){}seek(){}stop(){this.destroy();}destroy(){this._isDestroy =true;if(this.pc){this.pc.close();this.pc =null;}if(this._mediaElement){this._mediaElement =null;}if(this.sendChannel){this.sendChannel =null;}this.autoplay =null;this.typeCallback =null;this.statusCallback =null;this.isPlaying =false;this._isLoad =false;clearInterval(this.timer);}getisLoad(){returnthis._isLoad;}}

player-events.js

constPlayerEvents ={ERROR:'error',LOADING_COMPLETE:'loading_complete',RECOVERED_EARLY_EOF:'recovered_early_eof',MEDIA_INFO:'media_info',METADATA_ARRIVED:'metadata_arrived',SCRIPTDATA_ARRIVED:'scriptdata_arrived',STATISTICS_INFO:'statistics_info'};exportdefaultPlayerEvents;

common.js

exportfunctionsleep(ms){returnnewPromise(resolve=>setTimeout(resolve,ms));}

3、

HttpPost(url,data){returnnewPromise((resolve,reject)=>{varxhr =newXMLHttpRequest();xhr.onreadystatechange=()=>{if(xhr.readyState ===4&&(xhr.status >=200&&xhr.status <300)){varrespone =xhr.responseText;xhr.onreadystatechange =newFunction;xhr =null;resolve(respone);}};xhr.open('POST',url.replace('webrtc','http'),true);xhr.send(data);});}

6、主要涉及到获取本地媒体流、createOffer方法,这个方法返回本地会话描述。初始化连接

1、收到应答返回的offer.sdp, 设置为你的远端连接。
8、前端播放的过程中需要与服务器通信保持连接,可以 sendChannel.send(msg)来保持持续拉流 。setLocalDescription方法。

一、
5、