(เกือบ) การสตรีมเว็บแคมที่ไร้ประโยชน์จากเบราว์เซอร์ ส่วนที่ 2 WebRTC

เข้ามาบ้าง. หนึ่ง จากบทความเก่าและที่ถูกละทิ้งไปแล้ว ฉันเขียนเกี่ยวกับวิธีการออกอากาศวิดีโอจาก Canvas ผ่านเว็บซ็อกเก็ตได้อย่างง่ายดายและเป็นธรรมชาติ ในบทความนั้น ผมได้พูดคุยสั้นๆ เกี่ยวกับวิธีการถ่ายวิดีโอจากกล้องและเสียงจากไมโครโฟนโดยใช้ มีเดียสตรีม APIวิธีเข้ารหัสสตรีมที่ได้รับและส่งผ่านเว็บซ็อกเก็ตไปยังเซิร์ฟเวอร์ อย่างไรก็ตาม ในความเป็นจริงพวกเขาไม่ได้ทำเช่นนี้ สำหรับการออกอากาศพวกเขาใช้ซอฟต์แวร์พิเศษที่จำเป็นต้องติดตั้งและกำหนดค่า: ทันที สิ่งนี้สามารถทำได้ เปิดซอฟต์แวร์ Broadcastหรือใช้ WebRTC ซึ่งใช้งานได้ทันทีนั่นคือไม่จำเป็นต้องติดตั้งปลั๊กอิน a la flash player ใด ๆ ซึ่งจะถูกตัดออกจากเบราว์เซอร์ Chromium ในเดือนธันวาคม

วันนี้เราจะมาพูดถึง WebRTC

การสื่อสารแบบเรียลไทม์ผ่านเว็บ (WebRTC) ไม่ใช่โปรโตคอลเดียว แต่เป็นการรวบรวมมาตรฐาน โปรโตคอล และ JavaScript API ทั้งหมดที่ให้การสื่อสารผ่านวิดีโอและเสียงแบบเรียลไทม์แบบเพียร์ทูเพียร์ และยังสามารถใช้เพื่อถ่ายโอนข้อมูลใดๆ ก็ได้ ข้อมูลไบนารี โดยปกติแล้วเบราว์เซอร์จะทำหน้าที่เป็นเพียร์ แต่ก็สามารถเป็นแอปพลิเคชันมือถือได้เช่นกัน เพื่อจัดระเบียบการสื่อสาร p2p ระหว่างไคลเอนต์ จำเป็นต้องมีการรองรับเบราว์เซอร์สำหรับการเข้ารหัสวิดีโอและเสียงประเภทต่าง ๆ รองรับโปรโตคอลเครือข่ายที่หลากหลาย รับรองการทำงานร่วมกันของฮาร์ดแวร์กับเบราว์เซอร์ (ผ่านเลเยอร์ OS): เว็บแคม การ์ดเสียง การผสมผสานเทคโนโลยีทั้งหมดนี้ซ่อนอยู่หลังนามธรรม JavaScript API เพื่อความสะดวกของนักพัฒนา

ทั้งหมดนั้นแบ่งออกเป็นสาม API:

  • มีเดียสตรีม API - เราแยกมันออกจากกันเมื่อครั้งที่แล้ว วันนี้ฉันจะเขียนเพิ่มเติมเกี่ยวกับเรื่องนี้อีกเล็กน้อย ทำหน้าที่รับสตรีมวิดีโอ / เสียงจากฮาร์ดแวร์

  • RTCPeerConnection — ให้การสื่อสารระหว่างลูกค้าสองราย (p2p)

  • RTCDataChannel - ทำหน้าที่ถ่ายโอนข้อมูลโดยพลการระหว่างไคลเอนต์สองราย

การเตรียมสตรีมเสียงและวิดีโอสำหรับการส่งสัญญาณ

ทุกอย่างเริ่มต้นด้วยการ "จับภาพ" สตรีมสื่อของเว็บแคมและไมโครโฟน แน่นอนว่าสตรีมแบบดิบไม่เหมาะสำหรับการจัดการประชุมทางไกล แต่ละสตรีมจะต้องได้รับการประมวลผล: ปรับปรุงคุณภาพ ซิงโครไนซ์เสียงกับวิดีโอ วางเครื่องหมายการซิงโครไนซ์ในสตรีมวิดีโอ และตรวจสอบให้แน่ใจว่าบิตเรตสอดคล้องกับแบนด์วิดท์ที่เปลี่ยนแปลงตลอดเวลาของช่องสัญญาณ . เบราว์เซอร์จะดูแลทั้งหมดนี้ นักพัฒนาไม่จำเป็นต้องกังวลเกี่ยวกับการเข้ารหัสสำหรับสตรีมสื่อด้วยซ้ำ ภายในเบราว์เซอร์สมัยใหม่ มีเลเยอร์ซอฟต์แวร์สำหรับจับภาพ ปรับปรุงคุณภาพ (ลบเสียงสะท้อนและเสียงออกจากเสียง ปรับปรุงภาพ) การเข้ารหัสวิดีโอและเสียง โครงร่างเลเยอร์จะแสดงในรูป 1:

(เกือบ) การสตรีมเว็บแคมที่ไร้ประโยชน์จากเบราว์เซอร์ ส่วนที่ 2 WebRTCข้าว. 1. เลเยอร์ของการประมวลผลเสียงและวิดีโอในเบราว์เซอร์

การประมวลผลทั้งหมดเกิดขึ้นโดยตรงในเบราว์เซอร์เอง ไม่มีการเพิ่มเติม ไม่ต้องใช้ปลั๊กอิน อย่างไรก็ตาม สิ่งต่างๆ ยังคงไม่สดใสนักในปี 2020 มีเบราว์เซอร์ที่ยังไม่รองรับอย่างสมบูรณ์ มีเดียสตรีม APIคุณสามารถไปตามลิงก์และดูตารางความเข้ากันได้ที่ด้านล่างสุด โดยเฉพาะ IE น่าผิดหวังอีกครั้ง

คุณสามารถทำสิ่งที่น่าสนใจมากกับสตรีมที่ได้รับ: คุณสามารถโคลน เปลี่ยนความละเอียดของวิดีโอ จัดการคุณภาพเสียง คุณสามารถนำและ "แนบ" สตรีม Media Stream ไปที่ แท็กและดูตัวเองในหน้า html หรือคุณสามารถวาดสตรีมบนผืนผ้าใบ และตั้งค่า WebGL หรือ CSS3 และใช้ตัวกรองต่างๆ กับวิดีโอ จับภาพวิดีโอที่ประมวลผลจาก Canvas แล้วส่งผ่านเครือข่ายไปยังเซิร์ฟเวอร์ แปลงรหัสและเผยแพร่ให้กับทุกคน (สวัสดี bigo live, twitch และคนอื่น ๆ). ที่นี่ฉันจะไม่วิเคราะห์ว่าสิ่งต่าง ๆ เสร็จสิ้นอย่างไร ฉันจะยกตัวอย่างสองสามตัวอย่างที่พบในเว็บ:

https://jeeliz.com/ - พวกเขากำลังทำ CV แบบเรียลไทม์ใน Javascript พวกเขามีทั้ง คลังแสง ไลบรารี js ต่างๆ สำหรับการทำงานกับสตรีมวิดีโอบนผืนผ้าใบ: การตรวจจับใบหน้า วัตถุ การใช้ตัวกรอง (มาสก์ เช่น ใน Instagram) ฯลฯ ตัวอย่างที่ยอดเยี่ยมของวิธีที่คุณสามารถประมวลผลวิดีโอแบบเรียลไทม์ได้โดยตรงในเบราว์เซอร์โดยไม่ต้องใช้ปลั๊กอินเพิ่มเติม

Canvas captureStream API - เอกสารประกอบ API สำหรับการจับภาพวิดีโอสตรีมจากแคนวาส รองรับ Chrome, Opera และ Firefox แล้ว

RTCPeerConnection

ดังนั้นเราจึงมาถึงประเด็น แต่จะถ่ายโอนวิดีโอไปยังผู้ใช้รายอื่นได้อย่างไร มาถึงเบื้องหน้าแล้ว RTCPeerConnection. กล่าวโดยสรุป ในขั้นตอนนี้คุณจะต้องสร้างออบเจ็กต์ RTCPeerConnection:

const peerConnection = new RTCPeerConnection({
  iceServers: [{
    urls: 'stun:stun.l.google.com:19302'
  }]
});

เราระบุ iceServers เป็นหนึ่งในตัวเลือก - นี่คือเซิร์ฟเวอร์ที่ช่วยในการเชื่อมต่อระหว่างเบราว์เซอร์สองตัวที่อยู่เบื้องหลัง NAT'om นั่นคือปัญหาได้รับการแก้ไขที่นี่: จะทราบ ip ของคู่สนทนาได้อย่างไรว่าเขาอยู่เบื้องหลัง NAT ของผู้ให้บริการของเขาหรือไม่? โปรโตคอล ICE มาช่วยแล้ว อันที่จริง ICE ใช้ไม่ได้กับ WebRTC เลย แต่จะเพิ่มเติมในภายหลัง

ก่อนหน้านี้ เรามีสตรีม Usermedia:

navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
  // Usermedia-потоки, обычно это видео и аудио 
  const tracks = stream.getTracks();

   for (const track of tracks) {
     // каждый трек присоединяем к peerConnection
     peerConnection.addTrack(track);
   }
}).catch(console.error);

ถัดไป เหตุการณ์ที่จำเป็นต้องมีการเจรจาจะเริ่มทำงานบน peerConnection ในตัวจัดการที่เราต้องสร้างข้อเสนอ (ในแง่ของ SDP - Session Description Protocol) และกำหนดให้กับ peerConnection ผ่านเมธอด setLocalDescription เกี่ยวกับ SDP - คืออะไร และเกี่ยวกับรูปแบบข้อเสนอและคำตอบ - เราจะพูดคุยเพิ่มเติม

หลังจากกำหนด LocalDescription peerConnection แล้ว เบราว์เซอร์จะ "รวบรวม" ตัวเลือกน้ำแข็ง กล่าวคือ ค้นหาวิธีต่างๆ ในการสื่อสารผ่าน NAT เหตุการณ์ onicegatheringstatechange เริ่มทำงาน ในตัวจัดการ onicegatheringstatechange เราอนุญาตให้เชื่อมต่อกับสตรีม webrtc-signaling-server เพื่อแลกเปลี่ยนคำอธิบายเซสชันระหว่างเพียร์:

peerConnection.oniceconnectionstatechange = (event) => {
      console.log('Connection state: ', peerConnection.iceConnectionState);

      if (peerConnection.iceConnectionState === 'connected') {
        // Можем активировать кнопку Start broadcast
        setBroadcasting(true);
        setBroadcastingBtnActive(true);
      }
    };

// Событие срабатывает сразу, как только добавился медаиапоток в peerConnection
peerConnection.onnegotiationneeded = (event) => {
      // Создаем и назначаем SDP offer
      peerConnection.createOffer().
        then((offer) => peerConnection.setLocalDescription(offer)).
        catch(console.error);
    };

// Событие срабатывает каждый раз, как появляется ICE кандидат
peerConnection.onicegatheringstatechange = (ev) => {
      let connection = ev.target;

      // Now we can activate broadcast button
      if (connection.iceGatheringState === 'complete') {
        let delay = 50;
        let tries = 0;
        let maxTries = 3;

        let timerId = setTimeout(function allowStreaming() {
          if (isOnline) {
            setBroadcastingBtnActive(true);
            return;
          }

          if (tries < maxTries) {
            tries += 1;
            delay *= 2;
            timerId = setTimeout(allowStreaming, delay);
          } else {
            // TODO: show user notification
            console.error("Can't connect to server");

            alert("Can't connect to server");
          }
        }, delay);
      }
    };

webrtc-signaling-server คือเซิร์ฟเวอร์ที่จำเป็นสำหรับการแลกเปลี่ยนคำอธิบายเซสชันระหว่างสองเพียร์ ซึ่งอาจเป็น websocket หรือ xhr-server ที่ง่ายที่สุดบน PL ใดก็ได้ หน้าที่ของมันง่ายมาก: ยอมรับคำอธิบายเซสชั่นจากเพียร์หนึ่งแล้วโอนไปยังอีกเพียร์หนึ่ง

หลังจากการแลกเปลี่ยนคำอธิบายเซสชัน ทั้งสองฝ่ายก็พร้อมที่จะออกอากาศและรับสตรีมวิดีโอ ที่ด้านที่ได้รับสตรีมวิดีโอ เหตุการณ์ ontrack จะถูกทริกเกอร์บนการเชื่อมต่อแบบเพียร์ ในตัวจัดการ ซึ่งแทร็กที่ได้รับสามารถกำหนดให้กับ และดูคู่สนทนาที่คุณชื่นชอบ ทฤษฎีและรายละเอียดเพิ่มเติม

ลิงค์และวรรณกรรม:

https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection - เอกสาร RTCPeerConnection

https://github.com/pion/webrtc - การใช้งานโปรโตคอล WebRTC ขณะเดินทาง

https://webrtcforthecurious.com/ - หนังสือจากผู้สร้างไพออน

https://hpbn.co/ - จองเครือข่ายเบราว์เซอร์ประสิทธิภาพสูง มีการกล่าวถึงประเด็นต่างๆ ของการรับรองประสิทธิภาพสูงของเว็บแอปพลิเคชันอย่างละเอียด ในตอนท้ายจะมีการอธิบาย WebRTC หนังสือเล่มนี้เก่าอย่างแน่นอน (2013) แต่ก็ไม่ได้สูญเสียความเกี่ยวข้อง

ในส่วนถัดไป ฉันต้องการให้เพิ่มอีกเล็กน้อยของทฤษฎีและในทางปฏิบัติเพื่อวิเคราะห์การรับและการประมวลผลสตรีมวิดีโอบนเซิร์ฟเวอร์โดยใช้ pion การแปลงรหัสเป็น HLS ผ่าน ffmpeg สำหรับการออกอากาศครั้งต่อไปไปยังผู้ชมในเบราว์เซอร์

สำหรับผู้ที่ใจร้อน: ต้นแบบการแพร่ภาพวิดีโอที่หยาบมากของฉันจากเว็บแคมเพื่อโต้ตอบผ่านเซิร์ฟเวอร์ที่ใช้ไพออนในการกระตุก (นี่เป็นเพียงการทดลอง)

ที่มา: will.com

ซื้อโฮสติ้งที่เชื่อถือได้สำหรับไซต์ที่มีการป้องกัน DDoS เซิร์ฟเวอร์ VPS VDS 🔥 ซื้อบริการเว็บโฮสติ้งที่เชื่อถือได้ พร้อมระบบป้องกัน DDoS และเซิร์ฟเวอร์ VPS/VDS | ProHoster