Membangun layanan backend yang diperlukan untuk aplikasi WebRTC

Apa itu pemberian sinyal?

Pensinyalan adalah proses mengoordinasikan komunikasi. Agar aplikasi WebRTC dapat menyiapkan panggilan, kliennya perlu bertukar informasi berikut:

  • Pesan kontrol sesi yang digunakan untuk membuka atau menutup komunikasi
  • Pesan error
  • Metadata media, seperti codec, setelan codec, bandwidth, dan jenis media
  • Data kunci yang digunakan untuk membuat koneksi aman
  • Data jaringan, seperti alamat IP dan porta {i>host<i} seperti yang terlihat oleh dunia luar

Proses sinyal ini memerlukan cara bagi klien untuk meneruskan pesan bolak-balik. Mekanisme tersebut tidak diterapkan oleh WebRTC API. Anda harus membangunnya sendiri. Nanti dalam artikel ini, Anda akan mempelajari cara membuat layanan sinyal. Namun, pertama-tama Anda membutuhkan sedikit konteks.

Mengapa sinyal tidak ditentukan oleh WebRTC?

Untuk menghindari redundansi dan memaksimalkan kompatibilitas dengan teknologi yang sudah ada, metode dan protokol sinyal tidak ditentukan oleh standar WebRTC. Pendekatan ini diuraikan dalam Protokol Pembuatan Sesi JavaScript (JSEP):

Arsitektur JSEP juga menghindari browser yang harus menyimpan status, yaitu agar berfungsi sebagai mesin status pemberi sinyal. Hal ini akan bermasalah jika, misalnya, memberi sinyal data hilang setiap kali halaman dimuat ulang. Sebagai gantinya, status sinyal dapat disimpan di server.

Diagram arsitektur JSEP
Arsitektur JSEP

JSEP mewajibkan pertukaran antara pembanding offer dan answer, yakni metadata media yang disebutkan di atas. Penawaran dan jawaban disampaikan dalam format Protokol Deskripsi Sesi (SDP), yang terlihat seperti ini:

v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2
…

Ingin tahu apa sebenarnya arti dari semua SDP ini? Lihat contoh Internet Engineering Task Force (IETF).

Perlu diingat bahwa WebRTC dirancang agar penawaran atau jawaban dapat diubah sebelum ditetapkan sebagai deskripsi lokal atau jarak jauh dengan mengedit nilai dalam teks SDP. Misalnya, fungsi preferAudioCodec() di appr.tc dapat digunakan untuk menetapkan codec dan kecepatan bit default. SDP agak menyakitkan untuk dimanipulasi dengan JavaScript dan ada diskusi tentang apakah versi WebRTC mendatang harus menggunakan JSON, tetapi ada beberapa keuntungan untuk tetap menggunakan SDP.

RTCPeerConnection API dan pemberian sinyal: Penawaran, jawaban, dan kandidat

RTCPeerConnection adalah API yang digunakan oleh aplikasi WebRTC untuk membuat koneksi antara pembanding, serta berkomunikasi audio dan video.

Untuk melakukan inisialisasi proses ini, RTCPeerConnection memiliki dua tugas:

  • Pastikan kondisi media lokal, seperti resolusi dan kemampuan codec. Ini adalah metadata yang digunakan untuk mekanisme penawaran dan jawaban.
  • Mendapatkan alamat jaringan potensial untuk host aplikasi, yang dikenal sebagai kandidat.

Setelah dipastikan, data lokal ini harus ditukar melalui mekanisme sinyal dengan peer jarak jauh.

Bayangkan Alice mencoba menelepon Hadi. Berikut mekanisme penawaran/jawaban lengkap dengan semua detail mengerikannya:

  1. Alice membuat objek RTCPeerConnection.
  2. Anita membuat penawaran (deskripsi sesi SDP) dengan metode RTCPeerConnection createOffer().
  3. Anita menghubungi setLocalDescription() untuk memberikan penawarannya.
  4. Anita merangkai penawaran dan menggunakan mekanisme pemberian sinyal untuk mengirimkannya kepada Santi.
  5. Eve menelepon setRemoteDescription() dengan penawaran Alice, sehingga RTCPeerConnection-nya mengetahui penyiapan Anita.
  6. Eve memanggil createAnswer() dan callback berhasil untuk panggilan ini akan dikirimi deskripsi sesi lokal - jawaban Eve.
  7. Eve menetapkan jawabannya sebagai deskripsi lokal dengan memanggil setLocalDescription().
  8. Eve menggunakan mekanisme sinyal untuk mengirimkan jawaban dalam bentuk rangkaian kepada Anita.
  9. Anita menetapkan jawaban Eve sebagai deskripsi sesi jarak jauh menggunakan setRemoteDescription().

Alice dan Eve juga perlu bertukar informasi jaringan. Ekspresi "menemukan kandidat" mengacu pada proses menemukan antarmuka dan port jaringan menggunakan framework ICE.

  1. Anita membuat objek RTCPeerConnection dengan pengendali onicecandidate.
  2. Pengendali dipanggil saat kandidat jaringan tersedia.
  3. Di pengendali, Anita mengirimkan data kandidat string ke Eve melalui saluran sinyal.
  4. Saat Eve menerima pesan kandidat dari Anita, dia memanggil addIceCandidate() untuk menambahkan kandidat tersebut ke deskripsi pembanding jarak jauh.

JSEP mendukung Trickling Kandidat ICE, yang memungkinkan pemanggil secara bertahap memberikan kandidat kepada tujuan panggilan setelah penawaran awal, dan agar tujuan panggilan mulai bertindak atas panggilan serta menyiapkan koneksi tanpa menunggu semua kandidat tiba.

WebRTC kode untuk pemberian sinyal

Cuplikan kode berikut adalah contoh kode W3C yang merangkum proses pemberian sinyal lengkap. Kode ini mengasumsikan keberadaan beberapa mekanisme sinyal, SignalingChannel. Pemberian sinyal akan dibahas secara lebih mendetail nanti.

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // send the offer to the other peer
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

Untuk melihat cara kerja proses penawaran/jawaban dan pertukaran kandidat, lihat simpl.info RTCPeerConnection dan lihat log konsol untuk menemukan contoh video chat satu halaman. Jika ingin lebih, unduh file dump lengkap dari pensinyalan dan statistik WebRTC dari laman about://webrtc-internals di Google Chrome atau laman opera://webrtc-internals di Opera.

Penemuan peer

Ini adalah cara yang elegan untuk bertanya, "Bagaimana cara menemukan seseorang untuk diajak bicara?"

Untuk panggilan telepon, Anda memiliki nomor telepon dan direktori. Untuk video chat dan pesan online, Anda memerlukan sistem pengelolaan identitas dan kehadiran, serta sarana bagi pengguna untuk memulai sesi. Aplikasi WebRTC memerlukan cara agar klien dapat saling memberi tahu bahwa klien ingin memulai atau bergabung ke panggilan.

Mekanisme penemuan peer tidak ditentukan oleh WebRTC dan Anda tidak perlu membuka opsi di sini. Prosesnya sesederhana mengirim email atau mengirim pesan ke URL. Untuk aplikasi video chat, seperti Talky, tawk.to, dan Rapat Browser, Anda dapat mengundang orang ke panggilan dengan membagikan link kustom. Developer Chris Ball membuat eksperimen serverless-webrtc yang menarik yang memungkinkan peserta panggilan WebRTC bertukar metadata dengan layanan pesan apa pun yang mereka inginkan, seperti IM, email, atau homing pigeon.

Bagaimana cara membuat layanan pemberi sinyal?

Untuk mengulanginya, protokol dan mekanisme sinyal tidak ditentukan oleh standar WebRTC. Apa pun yang Anda pilih, Anda memerlukan server perantara untuk bertukar pesan dan data aplikasi antar klien. Sayangnya, sebuah aplikasi web tidak dapat begitu saja berteriak di internet, "Hubungkan saya dengan teman saya!"

Untungnya, pesan yang ditandai memiliki ukuran kecil dan sebagian besar dipertukarkan di awal panggilan. Saat menguji dengan appr.tc untuk sesi video chat, ada total sekitar 30-45 pesan yang ditangani oleh layanan sinyal dengan total ukuran untuk semua pesan sekitar 10 KB.

Selain relatif tidak menuntut dalam hal bandwidth, layanan sinyal WebRTC tidak menghabiskan banyak pemrosesan atau memori karena hanya perlu meneruskan pesan dan menyimpan sejumlah kecil data status sesi, seperti klien mana yang terhubung.

Mengirim pesan dari server ke klien

Layanan pesan untuk pemberian sinyal harus dua arah: klien ke server dan server ke klien. Komunikasi dua arah bertentangan dengan model permintaan/respons klien/server HTTP, tetapi berbagai peretasan seperti polling panjang telah dikembangkan selama bertahun-tahun untuk mendorong data dari layanan yang berjalan di server web ke aplikasi web yang berjalan di browser.

Baru-baru ini, EventSource API telah diterapkan secara luas. Hal ini memungkinkan peristiwa yang dikirim server - data yang dikirim dari server web ke klien browser melalui HTTP. EventSource dirancang untuk pengiriman pesan satu arah, tetapi dapat digunakan bersama dengan XHR untuk membangun layanan guna bertukar pesan pensinyalan. Layanan pemberi sinyal meneruskan pesan dari pemanggil, yang dikirim oleh permintaan XHR, dengan mendorongnya melalui EventSource ke tujuan panggilan.

WebSocket adalah solusi yang lebih alami, yang dirancang untuk komunikasi klien-server full duplex,—pesan yang dapat mengalir di kedua arah secara bersamaan. Salah satu keuntungan dari layanan sinyal yang dibuat dengan WebSocket atau peristiwa yang dikirim server (EventSource) murni adalah bahwa backend untuk API ini dapat diimplementasikan pada berbagai framework web yang umum bagi sebagian besar paket hosting web untuk bahasa seperti PHP, Python, dan Ruby.

Semua browser modern kecuali Opera Mini mendukung WebSocket dan, yang lebih penting, semua browser yang mendukung WebRTC juga mendukung WebSocket, baik di desktop maupun seluler. TLS harus digunakan untuk semua koneksi guna memastikan pesan tidak dapat dicegat tanpa enkripsi dan juga untuk mengurangi masalah terkait traversal proxy. (Untuk informasi lebih lanjut tentang WebSocket dan proxy traversal, lihat bab WebRTC dalam Jaringan Browser Berperforma Tinggi Ilya Grigorik.)

Anda juga dapat menangani sinyal dengan membuat klien WebRTC melakukan polling pada server pesan berulang kali melalui Ajax, tetapi hal tersebut menyebabkan banyak permintaan jaringan redundan, yang dapat menimbulkan masalah bagi perangkat seluler. Bahkan setelah sesi dibuat, rekan-rekan perlu melakukan polling untuk memberi sinyal pesan jika terjadi perubahan atau penghentian sesi oleh rekan-rekan lain. Contoh aplikasi Buku WebRTC menggunakan opsi ini dengan beberapa pengoptimalan untuk frekuensi polling.

Sinyal timbangan

Meskipun layanan pemberian sinyal menggunakan bandwidth dan CPU yang relatif sedikit per klien, server pemberi sinyal untuk aplikasi populer mungkin harus menangani banyak pesan dari lokasi yang berbeda dengan tingkat konkurensi yang tinggi. Aplikasi WebRTC yang mendapatkan banyak traffic memerlukan server pemberi sinyal yang mampu menangani beban yang cukup besar. Anda tidak membahasnya secara mendetail, tetapi ada sejumlah opsi untuk fitur pesan bervolume tinggi dan berperforma tinggi, termasuk opsi berikut:

  • eXtensible Messaging and Presence Protocol (XMPP), awalnya dikenal sebagai protokol Jabber-a yang dikembangkan untuk pesan instan yang dapat digunakan untuk pemberian sinyal (Implementasi server meliputi ejabberd dan Openfire. Klien JavaScript, seperti Strophe.js, menggunakan BOSH untuk mengemulasi streaming dua arah, tetapi karena berbagai alasan, BOSH mungkin tidak seefisien WebSocket dan, karena alasan yang sama, mungkin tidak diskalakan dengan baik.) (Pada tangen, Jingle adalah ekstensi XMPP untuk mengaktifkan suara dan video. Project WebRTC menggunakan komponen jaringan dan transpor dari library libjingle - implementasi C++ dari Jingle.)

  • Library open source, seperti ZeroMQ (seperti yang digunakan oleh TokBox untuk layanan Rumour mereka) dan OpenMQ (NullMQ menerapkan konsep ZeroMQ ke platform web menggunakan protokol STOMP melalui WebSocket.)

  • Platform pesan cloud komersial yang menggunakan WebSocket (meskipun mungkin kembali ke polling yang lama), seperti Pusher, Kaazing, dan PubNub (PubNub juga memiliki API untuk WebRTC.)

  • Platform WebRTC komersial, seperti vLine

(Panduan Teknologi Web Real-Time Developer Phil Leggetter menyediakan daftar lengkap layanan dan library pesan.)

Membangun layanan sinyal dengan Socket.io di Node

Berikut adalah kode untuk aplikasi web sederhana yang menggunakan layanan pemberian sinyal yang dibuat dengan Socket.io di Node. Desain Socket.io memudahkan pembangunan layanan untuk bertukar pesan dan Socket.io sangat sesuai dengan pensinyalan WebRTC karena konsep ruangan bawaannya. Contoh ini tidak dirancang untuk diskalakan sebagai layanan sinyal level produksi, tetapi mudah dipahami oleh sejumlah kecil pengguna.

Socket.io menggunakan WebSocket dengan penggantian: polling panjang AJAX, streaming multibagian AJAX, Forever Iframe, dan polling JSONP. Metode ini telah di-port ke berbagai backend, namun mungkin paling dikenal karena versi Node-nya yang digunakan dalam contoh ini.

Tidak ada WebRTC dalam contoh ini. Codelab ini dirancang hanya untuk menunjukkan cara membuat sinyal ke dalam aplikasi web. Lihat log konsol untuk mengetahui hal yang terjadi saat klien bergabung ke ruang dan bertukar pesan. Codelab WebRTC ini memberikan petunjuk langkah demi langkah tentang cara mengintegrasikannya ke dalam aplikasi chat video WebRTC yang lengkap.

Berikut adalah klien index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>WebRTC client</title>
  </head>
  <body>
    <script src='/socket.io/socket.io.js'></script>
    <script src='js/main.js'></script>
  </body>
</html>

Berikut adalah file JavaScript main.js yang dirujuk di klien:

const isInitiator;

room = prompt('Enter room name:');

const socket = io.connect();

if (room !== '') {
  console.log('Joining room ' + room);
  socket.emit('create or join', room);
}

socket.on('full', (room) => {
  console.log('Room ' + room + ' is full');
});

socket.on('empty', (room) => {
  isInitiator = true;
  console.log('Room ' + room + ' is empty');
});

socket.on('join', (room) => {
  console.log('Making request to join room ' + room);
  console.log('You are the initiator!');
});

socket.on('log', (array) => {
  console.log.apply(console, array);
});

Ini adalah aplikasi server lengkapnya:

const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
  file.serve(req, res);
}).listen(2013);

const io = require('socket.io').listen(app);

io.sockets.on('connection', (socket) => {

  // Convenience function to log server messages to the client
  function log(){
    const array = ['>>> Message from server: '];
    for (const i = 0; i < arguments.length; i++) {
      array.push(arguments[i]);
    }
      socket.emit('log', array);
  }

  socket.on('message', (message) => {
    log('Got message:', message);
    // For a real app, would be room only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', (room) => {
    const numClients = io.sockets.clients(room).length;

    log('Room ' + room + ' has ' + numClients + ' client(s)');
    log('Request to create or join room ' + room);

    if (numClients === 0){
      socket.join(room);
      socket.emit('created', room);
    } else if (numClients === 1) {
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room);
    } else { // max two clients
      socket.emit('full', room);
    }
    socket.emit('emit(): client ' + socket.id +
      ' joined room ' + room);
    socket.broadcast.emit('broadcast(): client ' + socket.id +
      ' joined room ' + room);

  });

});

(Anda tidak perlu mempelajari node-statis untuk ini. Itu kebetulan digunakan dalam contoh ini.)

Untuk menjalankan aplikasi ini di localhost, Anda harus sudah menginstal Node, Socket.IO, dan node-static. Node dapat didownload dari Node.js (penginstalan sangat mudah dan cepat). Untuk menginstal Socket.IO dan node-static, jalankan Node Package Manager dari terminal di direktori aplikasi Anda:

npm install socket.io
npm install node-static

Untuk memulai server, jalankan perintah berikut dari terminal di direktori aplikasi Anda:

node server.js

Dari browser, buka localhost:2013. Buka tab atau jendela baru di browser apa pun dan buka localhost:2013 lagi. Untuk mengetahui apa yang terjadi, periksa konsol. Di Chrome dan Opera, Anda dapat mengakses konsol melalui Developer Tools Google Chrome dengan Ctrl+Shift+J (atau Command+Option+J di Mac).

Apa pun pendekatan yang Anda pilih untuk pemberian sinyal, backend dan aplikasi klien Anda - setidaknya - harus menyediakan layanan yang mirip dengan contoh ini.

Memberi sinyal getcha

  • RTCPeerConnection tidak akan mulai mengumpulkan kandidat hingga setLocalDescription() dipanggil. Hal ini dimandatkan dalam draf JSEP IETF.
  • Manfaatkan Trickle ICE. Hubungi addIceCandidate() segera setelah kandidat tiba.

Server sinyal siap pakai

Jika Anda tidak ingin meluncurkannya sendiri, ada beberapa server sinyal WebRTC yang tersedia, yang menggunakan Socket.IO seperti contoh sebelumnya dan terintegrasi dengan library JavaScript klien WebRTC:

  • webRTC.io adalah salah satu library abstraksi pertama untuk WebRTC.
  • Signalmaster adalah server pemberi sinyal yang dibuat untuk digunakan dengan library klien JavaScript SimpleWebRTC.

Jika Anda tidak ingin menulis kode apa pun, platform WebRTC komersial yang lengkap tersedia dari perusahaan, seperti vLine, OpenTok, dan Asterisk.

Sebagai catatan, Ericsson membuat server sinyal menggunakan PHP di Apache pada awal WebRTC. Kode ini sekarang sudah agak usang, tetapi ada baiknya melihat kode tersebut jika Anda mempertimbangkan sesuatu yang serupa.

Keamanan sinyal

"Keamanan adalah seni untuk membuat tidak terjadi apa-apa."

Salman Rushdie

Enkripsi wajib untuk semua komponen WebRTC.

Namun, mekanisme sinyal tidak ditentukan oleh standar WebRTC, jadi terserah Anda untuk membuat sinyal aman. Jika penyerang berhasil membajak pemberian sinyal, mereka dapat menghentikan sesi, mengalihkan koneksi, dan merekam, mengubah, atau memasukkan konten.

Faktor terpenting dalam mengamankan sinyal adalah menggunakan protokol aman - HTTPS dan WSS (misalnya, TLS) - yang memastikan bahwa pesan tidak dapat disadap tanpa enkripsi. Selain itu, berhati-hatilah agar tidak menyiarkan pesan yang memberi sinyal dengan cara yang dapat diakses oleh penelepon lain menggunakan server pemberi sinyal yang sama.

Setelah memberikan sinyal: Gunakan ICE untuk mengatasi NAT dan firewall

Untuk pemberian sinyal metadata, aplikasi WebRTC menggunakan server perantara, tetapi untuk streaming data dan media aktual setelah sesi dibuat, RTCPeerConnection berupaya menghubungkan klien secara langsung atau peer-to-peer.

Di dunia yang lebih sederhana, setiap endpoint WebRTC memiliki alamat unik yang dapat ditukar dengan peer lain untuk berkomunikasi secara langsung.

Koneksi peer-to-peer sederhana
Dunia tanpa NAT dan firewall

Pada kenyataannya, sebagian besar perangkat berada di belakang satu atau beberapa lapisan NAT. Beberapa di antaranya memiliki software antivirus yang memblokir port dan protokol tertentu, dan banyak lagi yang berada di balik proxy dan firewall perusahaan. Firewall dan NAT sebenarnya dapat diimplementasikan oleh perangkat yang sama, seperti router Wi-Fi rumah.

Rekan di balik NAT dan {i>firewall<i}
Dunia nyata

Aplikasi WebRTC dapat menggunakan framework ICE untuk mengatasi kerumitan jaringan dunia nyata. Agar hal ini dapat terjadi, aplikasi Anda harus meneruskan URL server ICE ke RTCPeerConnection, seperti yang dijelaskan dalam artikel ini.

ICE mencoba menemukan jalur terbaik untuk menghubungkan rekan sejawat. Proses ini mencoba semua kemungkinan secara paralel dan memilih opsi paling efisien yang berfungsi. ICE pertama-tama mencoba membuat koneksi menggunakan alamat host yang diperoleh dari sistem operasi dan kartu jaringan perangkat. Jika gagal (yang juga berlaku untuk perangkat di belakang NAT), ICE akan memperoleh alamat eksternal menggunakan server STUN dan, jika gagal, lalu lintas akan dirutekan melalui server relai TURN.

Dengan kata lain, server STUN digunakan untuk mendapatkan alamat jaringan eksternal dan server TURN digunakan untuk menyampaikan lalu lintas jika koneksi langsung (peer-to-peer) gagal.

Setiap server TURN mendukung STUN. Server TURN adalah server STUN dengan fungsi relai bawaan tambahan. ICE juga mengatasi kerumitan pengaturan NAT. Pada kenyataannya, pembuatan lubang NAT mungkin memerlukan lebih dari sekadar alamat IP:port publik.

URL untuk server STUN dan/atau TURN (secara opsional) ditentukan oleh aplikasi WebRTC di objek konfigurasi iceServers yang merupakan argumen pertama ke konstruktor RTCPeerConnection. Untuk appr.tc, nilai tersebut akan terlihat seperti ini:

{
  'iceServers': [
    {
      'urls': 'stun:stun.l.google.com:19302'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=udp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=tcp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    }
  ]
}

Setelah RTCPeerConnection memiliki informasi tersebut, keajaiban ICE akan terjadi secara otomatis. RTCPeerConnection menggunakan framework ICE untuk mencari jalur terbaik di antara pembanding, bekerja dengan server STUN dan TURN sesuai kebutuhan.

STUN

NAT menyediakan perangkat dengan alamat IP untuk digunakan dalam jaringan lokal pribadi, tetapi alamat ini tidak dapat digunakan secara eksternal. Tanpa alamat publik, peering WebRTC tidak akan dapat berkomunikasi. Untuk mengatasi masalah ini, WebRTC menggunakan STUN.

Server STUN berada di internet publik dan memiliki satu tugas sederhana - memeriksa alamat IP:port dari permintaan yang masuk (dari aplikasi yang berjalan di belakang NAT) dan mengirim kembali alamat tersebut sebagai respons. Dengan kata lain, aplikasi menggunakan server STUN untuk menemukan IP:port dari perspektif publik. Proses ini memungkinkan peer WebRTC mendapatkan alamat yang dapat diakses secara publik untuk dirinya sendiri, lalu meneruskannya ke peer lain melalui mekanisme sinyal untuk menyiapkan link langsung. (Dalam praktiknya, NAT yang berbeda bekerja dengan cara yang berbeda dan mungkin ada beberapa layer NAT, tetapi prinsipnya masih sama.)

Server STUN tidak perlu melakukan banyak hal atau mengingat banyak hal, sehingga server STUN dengan spesifikasi yang relatif rendah dapat menangani permintaan dalam jumlah besar.

Sebagian besar panggilan WebRTC berhasil membuat koneksi menggunakan STUN - 86% menurut Webrtcstats.com, meskipun hal ini dapat lebih sedikit untuk panggilan antara pembanding di balik firewall dan konfigurasi NAT yang kompleks.

Koneksi peer-to-peer menggunakan server STUN
Menggunakan server STUN untuk mendapatkan alamat IP:port publik

PUTAR

RTCPeerConnection mencoba menyiapkan komunikasi langsung antara pembanding melalui UDP. Jika gagal, RTCPeerConnection akan beralih ke TCP. Jika gagal, server TURN dapat digunakan sebagai penggantian, yang meneruskan data antar-endpoint.

Untuk mengingatkan lagi, TURN digunakan untuk menyampaikan audio, video, dan streaming data antar-rekan, bukan memberi sinyal data.

Server TURN memiliki alamat publik, sehingga mereka dapat dihubungi oleh rekan meskipun pembanding berada di belakang firewall atau proxy. Server TURN memiliki tugas yang secara konseptual sederhana - untuk menyampaikan streaming. Namun, tidak seperti server STUN, server ini mengonsumsi banyak bandwidth. Dengan kata lain, server TURN harus lebih besar.

Koneksi peer-to-peer menggunakan server STUN
Full Monty: STUN, TURN, dan sinyal

Diagram ini menunjukkan cara kerja TURN. Pure STUN tidak berhasil, jadi setiap rekan sejawat kembali menggunakan server TURN.

Men-deploy server STUN dan TURN

Untuk pengujian, Google menjalankan server STUN publik, stun.l.google.com:19302, seperti yang digunakan oleh appr.tc. Untuk layanan STUN/TURN produksi, gunakan rfc5766-turn-server. Kode sumber untuk server STUN dan TURN tersedia di GitHub, tempat Anda juga dapat menemukan link ke beberapa sumber informasi tentang penginstalan server. Image VM untuk Amazon Web Services juga tersedia.

Server TURN alternatif adalah restund, yang tersedia sebagai kode sumber dan juga untuk AWS. Berikut adalah petunjuk cara menyiapkan restund di Compute Engine.

  1. Buka firewall yang diperlukan untuk tcp=443, udp/tcp=3478.
  2. Buat empat instance, satu untuk setiap IP publik, image Standar Ubuntu 12.06.
  3. Siapkan konfigurasi firewall lokal (izinkan APAPUN dari APAPUN).
  4. Instal alat: shell sudo apt-get install make sudo apt-get install gcc
  5. Instal libre dari creytiv.com/re.html.
  6. Ambil restund dari creytiv.com/restund.html dan buka paket./
  7. wget hancke.name/restund-auth.patch lalu terapkan dengan patch -p1 < restund-auth.patch.
  8. Jalankan make, sudo make install untuk libre dan restund.
  9. Sesuaikan restund.conf dengan kebutuhan Anda (ganti alamat IP dan pastikan berisi rahasia bersama yang sama) lalu salin ke /etc.
  10. Salin restund/etc/restund ke /etc/init.d/.
  11. Konfigurasi restund:
    1. Setel LD_LIBRARY_PATH.
    2. Salin restund.conf ke /etc/restund.conf.
    3. Tetapkan restund.conf untuk menggunakan 10 yang tepat. dengan Alamat IP tertentu
  12. Jalankan pemulihan
  13. Pengujian menggunakan klien stund dari komputer jarak jauh: ./client IP:port

Lebih dari sekadar one-to-one: WebRTC Multipihak

Anda juga dapat melihat standar IETF yang diusulkan Justin Uberti untuk REST API agar dapat mengakses TURN Services.

Sangat mudah untuk membayangkan kasus penggunaan streaming media yang lebih dari sekadar panggilan empat mata yang sederhana. Misalnya, melakukan konferensi video antara sekelompok kolega atau acara publik dengan satu pembicara dan ratusan atau jutaan penonton.

Aplikasi WebRTC dapat menggunakan beberapa RTCPeerConnections sehingga setiap endpoint terhubung ke setiap endpoint lainnya dalam konfigurasi mesh. Ini adalah pendekatan yang dilakukan oleh aplikasi, seperti talky.io, dan berfungsi sangat baik untuk beberapa pembanding. Selain itu, pemrosesan dan konsumsi bandwidth menjadi berlebihan, terutama untuk klien seluler.

Mesh: panggilan N-arah kecil
Topologi mesh penuh: Semua orang terhubung ke semua orang

Atau, aplikasi WebRTC dapat memilih satu endpoint untuk mendistribusikan streaming ke semua endpoint lainnya dalam konfigurasi bintang. Anda juga dapat menjalankan endpoint WebRTC di server dan membuat mekanisme redistribusi Anda sendiri (aplikasi klien contoh disediakan oleh webrtc.org).

Mulai Chrome 31 dan Opera 18, MediaStream dari satu RTCPeerConnection dapat digunakan sebagai input untuk yang lainnya. Hal ini dapat mengaktifkan arsitektur yang lebih fleksibel karena memungkinkan aplikasi web menangani perutean panggilan dengan memilih peer lain yang akan dihubungkan. Untuk melihat cara kerjanya, lihat Contoh WebRTC Relai koneksi pembanding dan Sampel WebRTC Beberapa koneksi peer.

Unit Kontrol Multipoint

Opsi yang lebih baik untuk endpoint dalam jumlah besar adalah menggunakan Multipoint Control Unit (MCU). Ini adalah server yang berfungsi sebagai jembatan untuk mendistribusikan media di antara sejumlah besar peserta. MCU dapat menangani berbagai resolusi, codec, dan kecepatan frame dalam konferensi video; menangani transcoding; melakukan penerusan streaming selektif; dan mencampur atau merekam audio dan video. Untuk panggilan dari banyak pihak, ada sejumlah masalah yang perlu dipertimbangkan, terutama cara menampilkan beberapa input video dan mencampur audio dari berbagai sumber. Platform cloud, seperti vLine, juga berupaya mengoptimalkan perutean traffic.

Anda dapat membeli paket perangkat keras MCU lengkap atau membuatnya sendiri.

Tampak belakang Cisco MCU5300
Bagian belakang Cisco MCU

Tersedia beberapa opsi software MCU open source. Misalnya, Licode (sebelumnya dikenal sebagai Lynckia) menghasilkan MCU open source untuk WebRTC. OpenTok memiliki Mantis.

Lebih dari sekadar browser: VoIP, telepon, dan pesan

Sifat standar WebRTC memungkinkan komunikasi antara aplikasi WebRTC yang berjalan di browser dan perangkat atau platform yang berjalan di platform komunikasi lain, seperti telepon atau sistem konferensi video.

SIP adalah protokol sinyal yang digunakan oleh sistem konferensi video dan VoIP. Untuk mengaktifkan komunikasi antara aplikasi web WebRTC dan klien SIP, seperti sistem konferensi video, WebRTC memerlukan server proxy untuk memediasi sinyal. Sinyal harus mengalir melalui gateway, tetapi setelah komunikasi dilakukan, traffic SRTP (video dan audio) dapat langsung mengalir secara peer to peer.

Public Switched Telephone Network (PSTN) adalah jaringan yang dialihkan sirkuit dari semua telepon analog "lama biasa". Untuk panggilan antara aplikasi web dan telepon WebRTC, traffic harus melalui gateway PSTN. Demikian juga, aplikasi web WebRTC memerlukan server XMPP perantara untuk berkomunikasi dengan endpoint Jingle seperti klien IM. Jingle dikembangkan oleh Google sebagai perluasan dari XMPP untuk mengaktifkan suara dan video untuk layanan pesan. Implementasi WebRTC saat ini didasarkan pada library libjingle C++, yaitu implementasi Jingle yang awalnya dikembangkan untuk Talk.

Sejumlah aplikasi, library, dan platform memanfaatkan kemampuan WebRTC untuk berkomunikasi dengan dunia luar:

  • sipML5: klien SIP JavaScript open source
  • jsSIP: Library SIP JavaScript
  • Phono: API telepon JavaScript open source yang dibuat sebagai plugin
  • Zingaya: widget ponsel yang dapat disematkan
  • Twilio: suara dan pesan
  • Uberconference: konferensi

Developer sipML5 juga telah membuat gateway webrtc2sip. Tethr dan Tropo telah mendemonstrasikan framework untuk komunikasi bencana "dalam koper" menggunakan sel OpenBTS untuk memungkinkan komunikasi antara ponsel menengah dan komputer melalui WebRTC. Itu adalah komunikasi telepon tanpa operator!

Cari tahu selengkapnya

Codelab WebRTC menyediakan petunjuk langkah demi langkah tentang cara membangun aplikasi video dan chat teks menggunakan layanan sinyal Socket.io yang berjalan di Node.

Presentasi WebRTC Google I/O dari tahun 2013 bersama pemimpin teknologi WebRTC, Justin Uberti

Presentasi SFHTML5 Chris Wilson - Pengantar Aplikasi WebRTC

Buku 350 halaman WebRTC: APIs and RTCWEB Protocols of the HTML5 Real-Time Web memberikan banyak detail tentang data dan jalur sinyal, serta menyertakan sejumlah diagram topologi jaringan yang mendetail.

WebRTC dan Signaling: What Two Years Has Taught Us - Postingan blog TokBox tentang alasan yang membuat sinyal di luar spesifikasi adalah ide bagus

Panduan Praktis untuk Membuat Aplikasi WebRTC dari Ben Strong memberikan banyak informasi tentang topologi dan infrastruktur WebRTC.

Bab WebRTC di Jaringan Browser Berperforma Tinggi Ilya Grigorik membahas arsitektur, kasus penggunaan, dan performa WebRTC secara mendalam.