二十、WebRTC視頻傳輸

本DEMO中,發(fā)送端和接收端都在本地,暫時省略了信令服務器
和真正的遠端視頻傳輸實現(xiàn)邏輯是一樣的,只是缺少信令服務器,后續(xù)會加上,實現(xiàn)真正的端到端視頻傳輸

let localVideo = document.querySelector('video#localvideo')
let remoteVideo = document.querySelector('video#remotevideo')
let btnStart = document.querySelector('button#start')
let btnCall = document.querySelector('button#call')
let btnHangup = document.querySelector('button#hangup')

let localStream
let pc1
let pc2

btnStart.onclick = () => {
    if(!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        console.log('the getUserMedia is not supported!')
        return
    }else {
        let constraints = {
            video: true,
            audio: true
        }
        navigator.mediaDevices.getUserMedia(constraints)
        .then((stream) => {
            localVideo.srcObject = stream
            localStream = stream
        })
        .catch((err) => {
            console.log(`Failed to get Media Stream! - ${err}`)
        })
    }
}

btnCall.onclick = () => {
    // 創(chuàng)建兩個連接 pc1 是調用者 pc2 是被調用者
    pc2 = new RTCPeerConnection()
    pc1 = new RTCPeerConnection()

    // 收到候選者時觸發(fā)的事件, 收到事件后交給對方,讓對方插入自己的 candidate列表中
    pc1.onicecandidate = (e) => {
        pc2.addIceCandidate(e.candidate) 
    }
    pc2.onicecandidate = (e) => {
        pc1.addIceCandidate(e.candidate) 
    }

    // 因為pc2是被調用者,當有數(shù)據(jù)時,它可以觸發(fā)ontrack事件
    pc2.ontrack = (e) => {
        // 從streams中取第一個值,賦值給remoteVide,這樣就可以顯示遠端的視頻
        remoteVideo.srcObject = e.streams[0]
    }

    // 將本地采集的流添加到pc1中
    localStream.getTracks().forEach(track => {
        pc1.addTrack(track, localStream)
    });

    let offerOptions = {
        offerToRecieveAudio: 1,
        offerToRecieveVideo: 1
    }
    // 媒體協(xié)商
    pc1.createOffer(offerOptions)
    .then((desc) => {
        // desc.sdp  打印出來是offer的sdp信息

        // 將desc放到自己遠端的描述信息的槽
        pc1.setLocalDescription(desc)
        // send desc to signal 信令服務器
        // receive desc from signal 
        pc2.setRemoteDescription(desc)

        pc2.createAnswer()
        .then((desc) => {
            // desc.sdp  打印出來是answer的sdp信息
            pc2.setLocalDescription(desc)
            // send desc to signal
            // receive desc from signal 
            pc1.setRemoteDescription(desc)
        })
        .catch((err) => {
            console.log(`Failed to create answer! - ${err}`)
        })
    })
    .catch((err) => {
        console.log(`Failed to create offer! - ${err}`)
    })
}

btnHangup.onclick = () => {
    pc1.close()
    pc2.close()
    pc1 = null
    pc2 = null
}
<html>
    <head>
        <title>PeerConnection</title>
    </head>
    <body>
        <video id="localvideo" autoplay playsinline></video>
        <video id="remotevideo" autoplay playsinline></video>
        <div>
                <button id="start">Start</button>
                <button id="call">Call</button>
                <button id="hangup">HangUp</button>
        </div>
        <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> -->
        <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
        <script src="./js/client.js"></script>
    </body>
</html>

實現(xiàn)效果

點擊start,打開本地視頻(左側視頻)
點擊call,呼叫對端(右側視頻)
點擊hangup,掛斷對端(右側視頻)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容