WebRTC là gì? Phương thức hoạt động và Ứng dụng

WebRTC là gì? Tại sao WebRTC lại được ứng dụng nhiều trong giới lập trình hiện nay? Là viết tắt của Web Real-Time Communication, ta có thể hiểu được đây là một công cụ hỗ trợ người dùng tương tác, trò chuyện trực tiếp trên website. Để tiếp tục hiểu thêm về WebRTC, cùng TopDev đọc tiếp bài viết dưới đây bạn nhé!

WebRTC là gì?

WebRTC là gì? Phương thức hoạt động và Ứng dụng
WebRTC là gì? Phương thức hoạt động và Ứng dụng

WebRTC (Web Real-Time Communication) là một tập hợp các hàm lập trình (web API) được phát triển bởi World Wide Web Consortium (W3C). Khả năng hỗ trợ trình duyệt giao tiếp với nhau theo thời gian thực bằng video, âm thanh hay truyền tải dữ liệu “Peer-to-Peer” (P2P) mà không cần browser phải cài thêm plugins hay phần mềm hỗ trợ nào từ bên ngoài. WebRTC có thể giúp chúng ta gọi điện video ngay trong trình duyệt mà không cần đăng kí tài khoản, ngoài ra chúng còn được xài để phát triển game chơi trực tiếp trong trình duyệt và rất nhiều loại ứng dụng khác.

Cách webRTC hoạt động

Cách webRTC hoạt động
Cách webRTC hoạt động

Kết nối Peer-to-Peer

Hầu hết các ứng dụng WebRTC dựa trên kiến trúc P2P (peer-to-peer). Trong kết nối P2P, các thành viên truyền dữ liệu trực tiếp với nhau mà không cần trung gian. Ngay cả khi một thành viên rời khỏi cuộc gọi, các thành viên còn lại vẫn có thể tiếp tục chia sẻ dữ liệu. Điều này làm cho WebRTC vượt trội so với các công nghệ truyền thông truyền thống, nơi người dùng không thể tiếp tục nếu mất kết nối với máy chủ. Ngoài ra, các peer thường gần nhau về mặt địa lý, giảm khoảng cách dữ liệu phải truyền tải.

Máy chủ Signaling

Máy chủ signaling giúp thiết lập kết nối ban đầu giữa các peer. Nó theo dõi các sự kiện như người dùng tham gia hoặc rời khỏi cuộc gọi. Máy chủ signaling cần thiết trong giai đoạn khởi tạo cuộc gọi nhưng không cần thiết trong quá trình giao tiếp liên tục. Tuy nhiên, nó có thể được sử dụng để theo dõi các sự kiện như một peer bị ngắt kết nối. Có nhiều cách để triển khai máy chủ signaling, yêu cầu duy nhất là làm cầu nối giữa các peer.

SDP (Session Description Protocol)

SDP giúp các peer trao đổi thông tin và thiết lập kết nối mà không cần biết chi tiết về hệ thống của nhau. SDP cung cấp thông tin về phần mềm, phần cứng và loại phương tiện mà peer muốn trao đổi. Khi khởi tạo kết nối, một peer đưa ra đề nghị (offer) và nhận lại câu trả lời (answer).

  • Offer/Answer: Khi khởi tạo kết nối, một peer đưa ra đề nghị và nhận lại câu trả lời.
  • ICE (Interactive Connectivity Establishment) candidates: Tìm kiếm các phương tiện giao tiếp tốt nhất cho các peer.
  • NAT (Network Address Translation): WebRTC phải vượt qua các lớp NAT để kết nối trực tiếp giữa các peer. WebRTC sử dụng các máy chủ TURN để kết nối các thiết bị qua NAT với internet công cộng, giúp truyền tải dữ liệu media giữa các trình duyệt.

WebRTC được thiết kế để thiết lập kết nối trực tiếp giữa các bên, nhưng lớp NAT có thể làm phức tạp quá trình này. Các ứng dụng WebRTC sử dụng máy chủ TURN để kết nối các máy trên NAT với mạng internet công cộng, đảm bảo truyền tải dữ liệu media giữa các trình duyệt.

Ứng dụng của webRTC

WebRTC (Web Real-Time Communication) là một công nghệ tiên tiến cho phép truyền tải âm thanh, video và dữ liệu trực tiếp giữa các trình duyệt và thiết bị mà không cần các plugin hoặc phần mềm bên ngoài. Dưới đây là các loại ứng dụng mà bạn có thể phát triển bằng WebRTC:

  • Ứng dụng Video Chat: Tạo cuộc gọi video một đối một hoặc nhóm như Skype, Google Meet, Zoom.
  • Ứng dụng Audio Chat: Thực hiện các cuộc gọi âm thanh qua internet như VoIP, Google Voice.
  • Truyền Hình Trực Tiếp: Phát trực tiếp sự kiện, hội nghị trên YouTube, Facebook Live.
  • Chia Sẻ Màn Hình: Hỗ trợ kỹ thuật từ xa, thuyết trình.
  • Ứng Dụng Học Trực Tuyến: Lớp học ảo, dạy kèm trực tuyến với video và âm thanh thời gian thực, chia sẻ tài liệu.
  • Ứng Dụng Chơi Game Nhiều Người Chơi: Truyền tải dữ liệu game giữa các người chơi.
  • Hệ Thống Giám Sát và An Ninh: Camera an ninh, giám sát từ xa.

WebRTC mang lại nhiều cơ hội phát triển các ứng dụng thời gian thực với khả năng truyền tải dữ liệu hiệu quả và bảo mật.

Demo – Viết ứng dụng gọi video giữa 2 người bằng Webrtc và Firebase

Tham khảo nguồn tại đây.

1.Cài đặt Firebase

Firebase là gì: Đó là một dịch vụ cơ sở dữ liệu thời gian thực hoạt động trên nền tảng đám mây được cung cấp bởi Google nhằm giúp các lập trình phát triển nhanh các ứng dụng bằng cách đơn giản hóa các thao tác với cơ sở dữ liệu.

Vào trang Firebase để đăng ký một tài khoản và chọn “Create New Project”. Sau khi tạo được project xong thì chọn “Add Firebase to your web app”, tại đây bạn sẽ có một đoạn mã Javascript có chứa key ứng dung.

<script>
  // Initialize Firebase
  // TODO: Replace with your project's customized code snippet
  var config = {
    apiKey: "<API_KEY>",
    authDomain: "<PROJECT_ID>.firebaseapp.com",
    databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
    projectId: "<PROJECT_ID>",
    storageBucket: "<BUCKET>.appspot.com",
    messagingSenderId: "<SENDER_ID>",
  };
  firebase.initializeApp(config);
</script>

Trong phần Rules của database thay đổi giá trị .read và .write chuyển sang thành true

 

2.Đến phần Code

Code 1 giao diện html có thêm thẻ <video></video> để show camera:

<html>
     <head>
         <script src="https://www.gstatic.com/firebasejs/5.0.4/firebase.js"></script>
         <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
     </head>
     <body onload="showMyFace()">
         <video id="yourVideo" autoplay muted></video>
         <video id="friendsVideo" autoplay></video>
         <br />
         <button onclick="showFriendsFace()" type="button" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-facetime-video" aria-hidden="true"></span> Call</button>
     </body>
</html>

css:

video {
 background-color: #ddd;
 border-radius: 7px;
 margin: 10px 0px 0px 10px;
 width: 320px;
 height: 240px;
}
button {
 margin: 5px 0px 0px 10px !important;
 width: 654px;
}

Javascript

    1. Cấp quyền truy cập vào thư mục gốc của cơ sở dữ liệu Firebase
      var database = firebase.database().ref();
    2. Hàm sendMessage để thêm cơ sở dữ liệu vào Firebase: database.on('child_added', readMessage);
    3. Tạo yourId random: var yourId = Math.floor(Math.random()*1000000000);
    4. Khai báo máy chủ sử dụng: Hai máy chủ STUN sử dụng ở đây là của Google và Firefox, bạn cũng có thể thêm nhiều STUN khác tùy thích:
      var servers = {'iceServers': [
          {'urls': 'stun:stun.services.mozilla.com'},
          {'urls': 'stun:stun.l.google.com:19302'}
      ]};

      Note: STUN là gì? STUN (Session Traversal Utilities for NAT) là một giao thức mạng cho phép các máy khách tìm ra địa chỉ công khai của mình, loại NAT mà chúng đang đứng sau và cổng phía Internet được NAT gắn liền với cổng nội bộ nào đó. Thông tin này được sử dụng để thiết lập giao tiếp UDP giữa 2 host mà đều nằm sau NAT router. Giao thức STUN được định nghĩa trong RFC 5389.

    5. Tạo một object PeerConnection var pc = new RTCPeerConnection(servers);
    6. Chờ đợi đối tượng ICE Candidate được tạo trên máy tính của bạn:
      pc.onicecandidate = (event => event.candidate ? sendMessage(yourId, JSON.stringify({'ice': event.candidate})) : console.log('Sent All Ice') );

      Chức năng này sẽ được gọi nhiều lần, một lần cho mỗi ICE Candidate (khó dịch sang tiếng Việt nên để nguyên) được tạo ra. Khi một ICE Candidate được tạo ra thì hàm này sẽ biến object thành một chuỗi. Sau đó, nó gửi chuỗi này cho bạn bè của bạn thông qua Firebase. Máy tính bạn bè của bạn cũng sẽ thực hiện tương tự như trên.

      ICE (Interactive Communication Establishment) nôm na dễ hiểu là một giao thức được cùng để thiết lập phiên media dựa trên UDP đi qua NAT một cách nhanh nhất. ICE sẽ tìm đường tốt nhất để kết nối giữa các peer, nó thử tất cả khả năng có thể kết nối một cách song song và lựa chọn con đường hiệu quả nhất.

    7. Khi bạn và người nhận nhận được một ICE Candidate dưới dạng chuỗi được gửi từ Firebase, thì JSON.stringify sẽ chuyển đổi chuỗi trở lại thành đối tượng ICE Candidate.
    8. Chờ đợi cho các đối tượng Offer, Answer, ICE Candidates được gửi:pc.onaddstream = (event => friendsVideo.srcObject = event.stream);
    9. Event onaddstream được gọi và đặt friendsVideo.srcObject thành object MediaStream. Thao tác này sẽ hiển thị video người kia trên máy tính của bạn và ngược lại. friendsVideo được gọi đến từ HTML.
    10. Thêm dữ liệu vào Firebase bằng hàm sendMessage :
      function sendMessage(senderId, data) {
          var msg = database.push({ sender: senderId, message: data });
          msg.remove();
      }
    11. Thêm hàm show camera của mình showMyFace:
      function showMyFace() {
           navigator.mediaDevices.getUserMedia({audio:true, video:true})
               .then(stream => yourVideo.srcObject = stream)
               .then(stream => pc.addStream(stream));
      }

      Khi gọi hàm getUserMedia, trình duyệt sẽ yêu cầu quyền truy cập camera. Nó sẽ trả về một đối tượng MediaStream cái mà bạn có thể đặt bằng yourVideo.srcObject. Đoạn này có chức năng hiển thị mặt của bạn trên chính máy tính của bạn. Sau đó, ta cần thêm cùng một đối tượng MediaStream vào đối tượng PeerConnection của bạn. Trên máy tính đối phương thực hiện cuộc gọi cũng thực hiện tương tự. Hàm này được gọi ngay khi tải trang, vì vậy bạn sẽ thấy khuôn mặt của mình ngay khi load trang.

    12. Hàm showFriendsFace:
      function showFriendsFace() {
           pc.createOffer()
               .then(offer => pc.setLocalDescription(offer) )
               .then(() => sendMessage(yourId, JSON.stringify({'sdp': pc.localDescription})) );
      }

      Tạo đối tượng Offer bằng cách gọi pc.createOffer(). Đặt local description cho offer này bằng cách gọi pc.setLocalDescription(offer). Cuối cùng gửi đối tượng Offer cho bạn của bạn bằng cách gọi sendMessage.

    13. Hàm readMessage
      function readMessage(data) {
           var msg = JSON.parse(data.val().message);
           var sender = data.val().sender;
           if (sender != yourId) {
               if (msg.ice != undefined) {
                   pc.addIceCandidate(new RTCIceCandidate(msg.ice));
               } else if (msg.sdp.type == "offer") {
                   pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
                       .then(() => pc.createAnswer())
                       .then(answer => pc.setLocalDescription(answer))
                       .then(() => sendMessage(yourId, JSON.stringify({'sdp': pc.localDescription})));
               } else if (msg.sdp.type == "answer") {
                   pc.setRemoteDescription(new RTCSessionDescription(msg.sdp));
               }
           }
      };

      Người nhận cuộc gọi có thể đọc được tin nhắn thông qua hàm readMessage. Với kiểu tin nhắn là offer thì bạn đã gửi cho người nhận một đối tượng Offer mà bạn đã tạo. Người kia sẽ thiết lập mô tả từ xa (remote decription) của họ cho đối tượng Offer mà bạn đã gửi cho họ bằng cách gọi pc.setRemoteDescription(new RTCSessionDescription(msg.sdp)). Người nhận sẽ tạo một đối tượng Answer bằng cách gọi đến pc.createAnswer(). Hàm này trả về một đối tượng Answer mà bạn sẽ thiết lập ở mô tả local. Người nhận làm được điều này bằng cách gọi đến pc.setLocalDescription(answer). Sau đó, người nhận lấy đối tượng Answer và gửi nó cho bạn bằng cách gọi sendMessage.

      Bởi vì kiểu của tin nhắn bây giờ đã là answer nên đoạn sau sẽ thực hiện pc.setRemoteDescription(new RTCSessionDescription(msg.sdp));

    14.  Toàn bộ code trên:
      var config = {
          apiKey: "<API_KEY>",
          authDomain: "<PROJECT_ID>.firebaseapp.com",
          databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
          projectId: "<PROJECT_ID>",
          storageBucket: "<BUCKET>.appspot.com",
          messagingSenderId: "<SENDER_ID>",
        };
        firebase.initializeApp(config);
      
      var database = firebase.database().ref();
      var yourVideo = document.getElementById("yourVideo");
      var friendsVideo = document.getElementById("friendsVideo");
      var yourId = Math.floor(Math.random()*1000000000);
      var servers = {'iceServers': [
          {'urls': 'stun:stun.services.mozilla.com'},
          {'urls': 'stun:stun.l.google.com:19302'}
      ]};
      var pc = new RTCPeerConnection(servers);
      pc.onicecandidate = (event => event.candidate?sendMessage(yourId, JSON.stringify({'ice': event.candidate})):console.log("Sent All Ice") );
      pc.onaddstream = (event => friendsVideo.srcObject = event.stream);
      
      function sendMessage(senderId, data) {
          var msg = database.push({ sender: senderId, message: data });
          msg.remove();
      }
      
      function readMessage(data) {
           var msg = JSON.parse(data.val().message);
           var sender = data.val().sender;
           if (sender != yourId) {
               if (msg.ice != undefined) {
                   pc.addIceCandidate(new RTCIceCandidate(msg.ice));
               } else if (msg.sdp.type == "offer") {
                   pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
                       .then(() => pc.createAnswer())
                       .then(answer => pc.setLocalDescription(answer))
                       .then(() => sendMessage(yourId, JSON.stringify({'sdp': pc.localDescription})));
               } else if (msg.sdp.type == "answer") {
                   pc.setRemoteDescription(new RTCSessionDescription(msg.sdp));
               }
           }
      };
      
      database.on('child_added', readMessage);
      
      function showMyFace() {
           navigator.mediaDevices.getUserMedia({audio:true, video:true})
               .then(stream => yourVideo.srcObject = stream)
               .then(stream => pc.addStream(stream));
      }
      
      function showFriendsFace() {
           pc.createOffer()
               .then(offer => pc.setLocalDescription(offer) )
               .then(() => sendMessage(yourId, JSON.stringify({'sdp': pc.localDescription})) );
      }
      

Tổng kết

Nói tóm lại, WebRTC có thể được sử dụng cho nhiều mục đích, từ việc truyền tải video, âm thanh cho đến gửi dữ liệu theo thời gian thực giữa hai hoặc nhiều thiết bị với nhau mà không nhất thiết phải đi qua server trung gian. Điều này giúp giảm độ trễ trong việc truyền tải, giảm độ phức tạp khi phát triển ứng dụng cũng như giảm chi phí vận hành (vì không phải trả tiền thuê server, tiền điện, tiền bảo dưỡng…), kéo theo đó giá bán dịch vụ nếu có thì cũng sẽ thấp hơn.

  Lập trình PHP và những câu hỏi thường gặp khi phỏng vấn