鍓嶇闊宠棰慦ebRTC瀹炴椂閫氳鐨勬牳蹇?/a>

Posted 绔ユ宸?,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鍓嶇闊宠棰慦ebRTC瀹炴椂閫氳鐨勬牳蹇?/a>相关的知识,希望对你有一定的参考价值。

瑙傛劅搴︼細馃専馃専馃専馃専馃専

鍙e懗锛氭柊鐤嗙倰绫崇矇

鐑归オ鏃堕棿锛?0min

鏈枃宸叉敹褰曞湪鍓嶇椋熷爞鍚屽悕浠撳簱Github github.com/Geekhyt锛屾杩庡厜涓撮鍫傦紝濡傛灉瑙夊緱閰掕彍杩樼畻鍙彛锛岃祻涓?Star 瀵归鍫傝€佹澘鏉ヨ鏄帿澶х殑榧撳姳銆?/blockquote>

閫氳繃涓婁袱涓郴鍒椾笓鏍忕殑瀛︿範锛屾垜浠鍓嶇闊宠棰戝強 WebRTC 鏈変簡鍒濇鐨勪簡瑙o紝鏄椂鍊欐暡浠g爜瀹炵幇涓€涓?Demo 鏉ョ湡瀹炴劅鍙椾笅 WebRTC 瀹炴椂閫氳鐨勯瓍鍔涗簡銆傝繕娌℃湁鐪嬭繃鐨勫悓瀛﹁绉绘锛?/p>

  • 鍓嶇闊宠棰戠殑閭d簺鍚嶈瘝
  • 鍓嶇闊宠棰戜箣WebRTC鍒濇帰

RTCPeerConnection

RTCPeerConnection 绫绘槸鍦ㄦ祻瑙堝櫒涓嬩娇鐢?WebRTC 瀹炵幇瀹炴椂浜掑姩闊宠棰戠郴缁熶腑鏈€鏍稿績鐨勭被锛屽畠浠h〃涓€涓敱鏈湴璁$畻鏈哄埌杩滅鐨?WebRTC 杩炴帴銆傝鎺ュ彛鎻愪緵浜嗗垱寤恒€佷繚鎸併€佺洃鎺у強鍏抽棴杩炴帴鐨勬柟娉曠殑瀹炵幇銆?/p>

鎯宠瀵硅繖涓被浜嗚В鏇村鍙互绉绘杩欎釜閾炬帴锛?https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection

鍏跺疄锛屽鏋滀綘鏈夊仛杩?socket 寮€鍙戠殑璇濓紝浣犱細鏇村鏄撶悊瑙?RTCPeerConnection锛屽畠鍏跺疄灏辨槸涓€涓姞寮虹増鏈殑 socket銆?/p>

鍦ㄤ笂涓郴鍒椾笓鏍?鍓嶇闊宠棰戜箣WebRTC鍒濇帰 涓紝鎴戜滑浜嗚В浜?WebRTC 鐨勯€氫俊鍘熺悊锛屽湪鐪熷疄鍦烘櫙涓嬮渶瑕佽繘琛屽獟浣撳崗鍟嗐€佺綉缁滃崗鍟嗐€佹灦璁句俊浠ゆ湇鍔″櫒绛夋搷浣滐紝鎴戠敾浜嗕竴寮犲浘锛屽皢 WebRTC 鐨勯€氫俊杩囩▼鎬荤粨濡備笅锛?/p>

涓嶈繃浠婂ぉ鎴戜滑涓轰簡鍗曠函鐨勬悶娓呮 RTCPeerConnection锛屽厛涓嶈€冭檻寮€鍙戞灦璁句俊浠ゆ湇鍔″櫒鐨勯棶棰橈紝绠€鍗曠偣锛屾垜浠繖娆″皾璇曞湪鍚屼竴涓〉闈腑妯℃嫙涓ょ杩涜闊宠棰戠殑浜掗€氥€?/p>

鍦ㄦ涔嬪墠锛屾垜浠厛浜嗚В涓€浜涘皢瑕佺敤鍒扮殑 API 浠ュ強 WebRTC 寤虹珛杩炴帴鐨勬楠ゃ€?/p>

鐩稿叧 API

  • RTCPeerConnection 鎺ュ彛浠h〃涓€涓敱鏈湴璁$畻鏈哄埌杩滅鐨?WebRTC 杩炴帴銆傝鎺ュ彛鎻愪緵浜嗗垱寤恒€佷繚鎸併€佺洃鎺с€佸叧闂繛鎺ョ殑鏂规硶鐨勫疄鐜般€?/li>
  • PC.createOffer 鍒涘缓鎻愯 Offer 鏂规硶锛屾鏂规硶浼氳繑鍥?SDP Offer 淇℃伅銆?/li>
  • PC.setLocalDescription 璁剧疆鏈湴 SDP 鎻忚堪淇℃伅銆?/li>
  • PC.setRemoteDescription 璁剧疆杩滅 SDP 鎻忚堪淇℃伅锛屽嵆瀵规柟鍙戣繃鏉ョ殑 SDP 鏁版嵁銆?/li>
  • PC.createAnswer 鍒涘缓搴旂瓟 Answer 鏂规硶锛屾鏂规硶浼氳繑鍥?SDP Answer 淇℃伅銆?/li>
  • RTCIceCandidate WebRTC 缃戠粶淇℃伅(IP銆佺鍙g瓑)
  • PC.addIceCandidate PC 杩炴帴娣诲姞瀵规柟鐨?IceCandidate 淇℃伅锛屽嵆娣诲姞瀵规柟鐨勭綉缁滀俊鎭€?/li>

WebRTC 寤虹珛杩炴帴姝ラ

  • 1.涓鸿繛鎺ョ殑涓ょ鍒涘缓涓€涓?RTCPeerConnection 瀵硅薄锛屽苟涓旂粰 RTCPeerConnection 瀵硅薄娣诲姞鏈湴娴併€?/li>
  • 2.鑾峰彇鏈湴濯掍綋鎻忚堪淇℃伅(SDP)锛屽苟涓庡绔繘琛屼氦鎹€?/li>
  • 3.鑾峰彇缃戠粶淇℃伅(Candidate锛孖P 鍦板潃鍜岀鍙?锛屽苟涓庤繙绔繘琛屼氦鎹€?/li>

Demo 瀹炴垬

棣栧厛锛屾垜浠坊鍔犺棰戝厓绱犲強鎺у埗鎸夐挳锛屽紩鍏?adpater.js 鏉ラ€傞厤鍚勬祻瑙堝櫒銆?/p>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Demo</title>
    <style>
        video {
            width: 320px;
        }
    </style>
</head>
<body>
    <video id="localVideo" autoplay playsinline></video>
    <video id="remoteVideo" autoplay playsinline></video>

    <div>
        <button id="startBtn">鎵撳紑鏈湴瑙嗛</button>
        <button id="callBtn">寤虹珛杩炴帴</button>
        <button id="hangupBtn">鏂紑杩炴帴</button>
    </div>
    <!-- 閫傞厤鍚勬祻瑙堝櫒 API 涓嶇粺涓€鐨勮剼鏈?-->
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="./webrtc.js"></script>
</body>
</html>

鐒跺悗锛屽畾涔夋垜浠皢瑕佷娇鐢ㄥ埌鐨勫璞°€?/p>

// 鏈湴娴佸拰杩滅娴?let localStream;
let remoteStream;

// 鏈湴鍜岃繙绔繛鎺ュ璞?let localPeerConnection;
let remotePeerConnection;

// 鏈湴瑙嗛鍜岃繙绔棰?const localVideo = document.getElementById(\'localVideo\');
const remoteVideo = document.getElementById(\'remoteVideo\');

// 璁剧疆绾︽潫
const mediaStreamConstraints = {
    video: true
}

// 璁剧疆浠呬氦鎹㈣棰?const offerOptions = {
    offerToReceiveVideo: 1
}

鎺ヤ笅鏉ワ紝缁欐寜閽敞鍐屼簨浠跺苟瀹炵幇鐩稿叧涓氬姟閫昏緫銆?/p>

function startHandle() {
    startBtn.disabled = true;
    // 1.鑾峰彇鏈湴闊宠棰戞祦
    // 璋冪敤 getUserMedia API 鑾峰彇闊宠棰戞祦
    navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
        .then(gotLocalMediaStream)
        .catch((err) => {
            console.log(\'getUserMedia 閿欒\', err);
        });
}

function callHandle() {
    callBtn.disabled = true;
    hangupBtn.disabled = false;

    // 瑙嗛杞ㄩ亾
    const videoTracks = localStream.getVideoTracks();
    // 闊抽杞ㄩ亾
    const audioTracks = localStream.getAudioTracks();
    // 鍒ゆ柇瑙嗛杞ㄩ亾鏄惁鏈夊€?    if (videoTracks.length > 0) {
        console.log(`浣跨敤鐨勮澶囦负: ${videoTracks[0].label}.`);
    }
    // 鍒ゆ柇闊抽杞ㄩ亾鏄惁鏈夊€?    if (audioTracks.length > 0) {
        console.log(`浣跨敤鐨勮澶囦负: ${audioTracks[0].label}.`);
    }
    const servers = null;

    // 鍒涘缓 RTCPeerConnection 瀵硅薄
    localPeerConnection = new RTCPeerConnection(servers);
    // 鐩戝惉杩斿洖鐨?Candidate
    localPeerConnection.addEventListener(\'icecandidate\', handleConnection);
    // 鐩戝惉 ICE 鐘舵€佸彉鍖?    localPeerConnection.addEventListener(\'iceconnectionstatechange\', handleConnectionChange)

    remotePeerConnection = new RTCPeerConnection(servers);
    remotePeerConnection.addEventListener(\'icecandidate\', handleConnection);
    remotePeerConnection.addEventListener(\'iceconnectionstatechange\', handleConnectionChange);
    remotePeerConnection.addEventListener(\'track\', gotRemoteMediaStream);

    // 灏嗛煶瑙嗛娴佹坊鍔犲埌 RTCPeerConnection 瀵硅薄涓?    // 娉ㄦ剰锛氭柊鐨勫崗璁腑宸茬粡涓嶅啀鎺ㄨ崘浣跨敤 addStream 鏂规硶鏉ユ坊鍔犲獟浣撴祦锛屽簲浣跨敤 addTrack 鏂规硶
    // localPeerConnection.addStream(localStream);
    // 閬嶅巻鏈湴娴佺殑鎵€鏈夎建閬?    localStream.getTracks().forEach((track) => {
        localPeerConnection.addTrack(track, localStream)
    })

    // 2.浜ゆ崲濯掍綋鎻忚堪淇℃伅
    localPeerConnection.createOffer(offerOptions)
    .then(createdOffer).catch((err) => {
        console.log(\'createdOffer 閿欒\', err);
    });
}

function hangupHandle() {
    // 鍏抽棴杩炴帴骞惰缃负绌?    localPeerConnection.close();
    remotePeerConnection.close();
    localPeerConnection = null;
    remotePeerConnection = null;
    hangupBtn.disabled = true;
    callBtn.disabled = false;
}

// getUserMedia 鑾峰緱娴佸悗锛屽皢闊宠棰戞祦灞曠ず骞朵繚瀛樺埌 localStream
function gotLocalMediaStream(mediaStream) {
    localVideo.srcObject = mediaStream; 
    localStream = mediaStream; 
    callBtn.disabled = false;
}

function createdOffer(description) {
    console.log(`鏈湴鍒涘缓offer杩斿洖鐨剆dp:\\n${description.sdp}`)
    // 鏈湴璁剧疆鎻忚堪骞跺皢瀹冨彂閫佺粰杩滅
    // 灏?offer 淇濆瓨鍒版湰鍦?    localPeerConnection.setLocalDescription(description) 
        .then(() => {
            console.log(\'local 璁剧疆鏈湴鎻忚堪淇℃伅鎴愬姛\');
        }).catch((err) => {
            console.log(\'local 璁剧疆鏈湴鎻忚堪淇℃伅閿欒\', err)
        });
    // 杩滅灏嗘湰鍦扮粰瀹冪殑鎻忚堪璁剧疆涓鸿繙绔弿杩?    // 杩滅灏?offer 淇濆瓨
    remotePeerConnection.setRemoteDescription(description) 
        .then(() => { 
            console.log(\'remote 璁剧疆杩滅鎻忚堪淇℃伅鎴愬姛\');
        }).catch((err) => {
            console.log(\'remote 璁剧疆杩滅鎻忚堪淇℃伅閿欒\', err);
        });
    // 杩滅鍒涘缓搴旂瓟 answer
    remotePeerConnection.createAnswer() 
        .then(createdAnswer)
        .catch((err) => {
            console.log(\'杩滅鍒涘缓搴旂瓟 answer 閿欒\', err);
        });
}

function createdAnswer(description) {
    console.log(`杩滅搴旂瓟Answer鐨剆dp:\\n${description.sdp}`)
    // 杩滅璁剧疆鏈湴鎻忚堪骞跺皢瀹冨彂缁欐湰鍦?    // 杩滅淇濆瓨 answer
    remotePeerConnection.setLocalDescription(description)
        .then(() => { 
            console.log(\'remote 璁剧疆鏈湴鎻忚堪淇℃伅鎴愬姛\');
        }).catch((err) => {
            console.log(\'remote 璁剧疆鏈湴鎻忚堪淇℃伅閿欒\', err);
        });
    // 鏈湴灏嗚繙绔殑搴旂瓟鎻忚堪璁剧疆涓鸿繙绔弿杩?    // 鏈湴淇濆瓨 answer
    localPeerConnection.setRemoteDescription(description) 
        .then(() => { 
            console.log(\'local 璁剧疆杩滅鎻忚堪淇℃伅鎴愬姛\');
        }).catch((err) => {
            console.log(\'local 璁剧疆杩滅鎻忚堪淇℃伅閿欒\', err);
        });
}

// 3.绔笌绔缓绔嬭繛鎺?function handleConnection(event) {
    // 鑾峰彇鍒拌Е鍙?icecandidate 浜嬩欢鐨?RTCPeerConnection 瀵硅薄 
    // 鑾峰彇鍒板叿浣撶殑Candidate
    const peerConnection = event.target;
    const iceCandidate = event.candidate;

    if (iceCandidate) {
        // 鍒涘缓 RTCIceCandidate 瀵硅薄
        const newIceCandidate = new RTCIceCandidate(iceCandidate);
        // 寰楀埌瀵圭鐨?RTCPeerConnection
        const otherPeer = getOtherPeer(peerConnection);

        // 灏嗘湰鍦拌幏寰楃殑 Candidate 娣诲姞鍒拌繙绔殑 RTCPeerConnection 瀵硅薄涓?        // 涓轰簡绠€鍗曪紝杩欓噷骞舵病鏈夐€氳繃淇′护鏈嶅姟鍣ㄦ潵鍙戦€?Candidate锛岀洿鎺ラ€氳繃 addIceCandidate 鏉ヨ揪鍒颁簰鎹?Candidate 淇℃伅鐨勭洰鐨?        otherPeer.addIceCandidate(newIceCandidate)
            .then(() => {
                handleConnectionSuccess(peerConnection);
            }).catch((error) => {
                handleConnectionFailure(peerConnection, error);
            });
    }
}

// 4.鏄剧ず杩滅濯掍綋娴?function gotRemoteMediaStream(event) {
    if (remoteVideo.srcObject !== event.streams[0]) {
        remoteVideo.srcObject = event.streams[0];
        remoteStream = event.streams[0];
        console.log(\'remote 寮€濮嬫帴鍙楄繙绔祦\')
    }
}

鏈€鍚庯紝杩橀渶瑕佹敞鍐屼竴浜?Log 鍑芥暟鍙婂伐鍏峰嚱鏁般€?/p>

function handleConnectionChange(event) {
    const peerConnection = event.target;
    console.log(\'ICE state change event: \', event);
    console.log(`${getPeerName(peerConnection)} ICE state: ` + `${peerConnection.iceConnectionState}.`);
}

function handleConnectionSuccess(peerConnection) {
    console.log(`${getPeerName(peerConnection)} addIceCandidate 鎴愬姛`);
}

function handleConnectionFailure(peerConnection, error) {
    console.log(`${getPeerName(peerConnection)} addIceCandidate 閿欒:\\n`+ `${error.toString()}.`);
}

function getPeerName(peerConnection) {
    return (peerConnection === localPeerConnection) ? \'localPeerConnection\' : \'remotePeerConnection\';
}

function getOtherPeer(peerConnection) {
    return (peerConnection === localPeerConnection) ? remotePeerConnection : localPeerConnection;
}

鍏跺疄褰撲綘鐔熸倝鏁翠釜娴佺▼鍚庡彲浠ュ皢鎵€鏈夌殑 Log 鍑芥暟缁熶竴鎶藉彇骞跺皝瑁呰捣鏉ワ紝涓婃枃涓轰簡渚夸簬浣犲湪璇讳唬鐮佺殑杩囩▼涓洿瀹规槗鐨勭悊瑙f暣涓?WebRTC 寤虹珛杩炴帴鐨勮繃绋嬶紝骞舵病鏈夎繘琛屾娊鍙栥€?/p>

濂戒簡锛屽埌杩欓噷涓€鍒囬『鍒╃殑璇濓紝浣犲氨鎴愬姛鐨勫缓绔嬩簡 WebRTC 杩炴帴锛屾晥鏋滃涓嬶細

(闅忔墜鎶撹捣妗岃竟鐨勯紶骞翠紒楣呭叕浠?

鍙傝€?/h2>
  • 銆婁粠 0 鎵撻€犻煶瑙嗛鐩存挱绯荤粺銆?鏉庤秴
  • 銆奧ebRTC 闊宠棰戝紑鍙?React+Flutter+Go 瀹炴垬銆?浜㈠皯鍐?/li>
  • https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection

鉂わ笍鐖卞績涓夎繛鍑?/h2>

1.濡傛灉浣犺寰楅鍫傞厭鑿滆繕鍚堣儍鍙o紝灏辩偣涓禐鏀寔涓嬪惂锛屼綘鐨?strong>璧?/strong>鏄垜鏈€澶х殑鍔ㄥ姏銆?/p>

2.鍏虫敞鍏紬鍙峰墠绔鍫傦紝鍚冨ソ姣忎竴椤块キ锛?/strong>

3.鐐硅禐銆佽瘎璁恒€佽浆鍙?=== 鍌洿锛?/p>

以上是关于鍓嶇闊宠棰慦ebRTC瀹炴椂閫氳鐨勬牳蹇?/a>的主要内容,如果未能解决你的问题,请参考以下文章

閫氳繃杩?2寮犳墜缁樺浘锛屾悶鎳備粈涔堟槸寰湇鍔℃灦鏋?/h1>

Linux绯荤粺sersync鏁版嵁瀹炴椂鍚屾

鍊熷姪瀹炴椂鏁版嵁鎺ㄩ€佸揩閫熷埗浣滃湪绾垮鎴樹簲瀛愭灏忔父鎴忎辅瀹炴垬

铻嶄簯鍗虫椂閫氳SDK闆嗘垚 -- FCM鎺ㄩ€侀泦鎴愭寚鍗?Android骞冲彴)

[WebSocket]浣跨敤WebSocket瀹炵幇瀹炴椂澶氫汉绛旈瀵规垬娓告垙

铻嶄簯鍗虫椂閫氳SDK闆嗘垚 -- 鍥藉唴鍘傚晢鎺ㄩ€侀泦鎴愯俯鍧戠瘒(Android骞冲彴)