ΠΠ°ΠΊ-ΡΠΎ Π²
Π‘Π΅Π³ΠΎΠ΄Π½Ρ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΠΌ ΠΎ WebRTC.
Web Real-Time Communication (WebRTC) ΡΡΠΎ Π½Π΅ ΠΎΠ΄ΠΈΠ½ ΠΏΡΠΎΡΠΎΠΊΠΎΠ», ΡΡΠΎ ΡΠ΅Π»Π°Ρ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ ΡΡΠ°Π½Π΄Π°ΡΡΠΎΠ², ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠ² ΠΈ JavaScript API, ΠΊΠΎΡΠΎΡΡΠ΅ Π²ΡΠ΅ Π²ΠΌΠ΅ΡΡΠ΅ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°ΡΡ peer-to-peer Π²ΠΈΠ΄Π΅ΠΎ-Π°ΡΠ΄ΠΈΠΎ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΈ Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½Ρ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π»ΡΠ±ΡΡ Π±ΠΈΠ½Π°ΡΠ½ΡΡ Π΄Π°Π½Π½ΡΡ . ΠΠ±ΡΡΠ½ΠΎ ΠΏΠΈΡΠ°ΠΌΠΈ Π²ΡΡΡΡΠΏΠ°ΡΡ Π±ΡΠ°ΡΠ·Π΅ΡΡ, Π½ΠΎ ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈ ΠΌΠΎΠ±ΠΈΠ»ΡΠ½ΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ. ΠΠ»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ ΠΎΡΠ³Π°Π½ΠΈΠ·ΠΎΠ²Π°ΡΡ p2p ΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° Π±ΡΠ°ΡΠ·Π΅ΡΠΎΠΌ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ Π²ΠΈΠ΄ΠΎΠ² ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎ ΠΈ Π°ΡΠ΄ΠΈΠΎ, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π° ΡΠ΅ΡΠ΅Π²ΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠ², ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΠ΅ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ ΠΆΠ΅Π»Π΅Π·Π° Ρ Π±ΡΠ°ΡΠ·Π΅ΡΠΎΠΌ (ΡΠ΅ΡΠ΅Π· ΡΠ»ΠΎΠΈ ΠΠ‘): Π²Π΅Π±ΠΊΠ°ΠΌΠ΅Ρ, Π·Π²ΡΠΊΠΎΠ²ΡΡ ΠΊΠ°ΡΡ. ΠΡΡ ΡΡΠ° ΠΌΠ΅ΡΠ°Π½ΠΈΠ½Π° ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ ΡΠΊΡΡΡΠ° Π·Π° Π°Π±ΡΡΡΠ°ΠΊΡΠΈΠ΅ΠΉ JavaScript API Π΄Π»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°.
ΠΡΠ΅ ΡΠ²ΠΎΠ΄ΠΈΡΡΡ Π² ΠΈΡΠΎΠ³Π΅ ΠΊ ΡΡΠ΅ΠΌ API:
-
MediaStream API — ΡΠ°Π·Π±ΠΈΡΠ°Π»ΠΈ Π² ΠΏΡΠΎΡΠ»ΡΠΉ ΡΠ°Π·, ΡΠ΅Π³ΠΎΠ΄Π½Ρ Π΅ΡΠ΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π½Π°ΠΏΠΈΡΡ ΠΏΡΠΎ Π½Π΅Π³ΠΎ. Π‘Π»ΡΠΆΠΈΡ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎ/Π°ΡΠ΄ΠΈΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ² ΠΎΡ «ΠΆΠ΅Π»Π΅Π·Π°» -
RTCPeerConnection — ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ (p2p) -
RTCDataChannel — ΡΠ»ΡΠΆΠΈΡ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΡ Π΄Π°Π½Π½ΡΡ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ
ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° Π°ΡΠ΄ΠΈΠΎ ΠΈ Π²ΠΈΠ΄Π΅ΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ² ΠΊ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠ΅
ΠΡΠ΅ Π½Π°ΡΠΈΠ½Π°Π΅ΡΡΡ Ρ «Π·Π°Ρ Π²Π°ΡΠ°» ΠΌΠ΅Π΄ΠΈΠ°ΠΏΠΎΡΠΎΠΊΠΎΠ² Π²Π΅Π±ΠΊΠ°ΠΌΠ΅ΡΡ ΠΈ ΠΌΠΈΠΊΡΠΎΡΠΎΠ½Π°. Π‘ΡΡΡΠ΅ ΠΏΠΎΡΠΎΠΊΠΈ ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ ΠΆΠ΅ Π½Π΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡ Π΄Π»Ρ ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΠΈ ΡΠ΅Π»Π΅ΠΊΠΎΠ½ΡΠ΅ΡΠ΅Π½ΡΠΈΠΈ, ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΏΠΎΡΠΎΠΊ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ: ΡΠ»ΡΡΡΠΈΡΡ ΠΊΠ°ΡΠ΅ΡΡΠ²ΠΎ, ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ Π°ΡΠ΄ΠΈΠΎ Ρ Π²ΠΈΠ΄Π΅ΠΎ, ΡΠ°ΡΡΡΠ°Π²ΠΈΡΡ ΠΌΠ΅ΡΠΊΠΈ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ Π² Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ΅, ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ ΠΌΠ΅Π½ΡΡΡΠ΅ΠΉΡΡ ΡΠΈΡΠΎΡΠ΅ ΠΏΡΠΎΠΏΡΡΠΊΠ°Π½ΠΈΡ ΠΊΠ°Π½Π°Π»Π° Π±ΠΈΡΡΠ΅ΠΉΡ. ΠΡΠ°ΡΠ·Π΅Ρ Π²ΡΠ΅ ΡΡΠΎ Π±Π΅ΡΠ΅Ρ Π½Π° ΡΠ΅Π±Ρ, ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΡ Π΄Π°ΠΆΠ΅ Π½Π΅ Π½Π°Π΄ΠΎ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΈΡΡΡΡ ΠΎΠ± ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΠΈ ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ΅Π΄ΠΈΠ°-ΠΏΠΎΡΠΎΠΊΠΎΠ². ΠΠ½ΡΡΡΠΈ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ Π±ΡΠ°ΡΠ·Π΅ΡΠ° ΡΠΆΠ΅ ΠΏΡΠΈΡΡΡΡΡΠ²ΡΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΠ΅ ΡΠ»ΠΎΠΈ Π·Π°Ρ Π²Π°ΡΠ°, ΡΠ»ΡΡΡΠ΅Π½ΠΈΡ ΠΊΠ°ΡΠ΅ΡΡΠ²Π° (ΡΠ±ΡΠ°ΡΡ ΡΡ ΠΎ ΠΈ ΡΡΠΌ ΠΈΠ· Π·Π²ΡΠΊΠ°, ΡΠ»ΡΡΡΠΈΡΡ ΠΊΠ°ΡΡΠΈΠ½ΠΊΡ), ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎ ΠΈ Π°ΡΠ΄ΠΈΠΎ. Π‘Ρ Π΅ΠΌΠ° ΡΠ»ΠΎΠ΅Π² ΠΏΠΎΠΊΠ°Π·Π°Π½Π° ΡΠΈΡ. 1:
Π ΠΈΡ. 1. Π‘Π»ΠΎΠΈ Π°ΡΠ΄ΠΈΠΎ ΠΈ Π²ΠΈΠ΄Π΅ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅
ΠΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ ΠΏΡΡΠΌΠΎ Π² ΡΠ°ΠΌΠΎΠΌ Π±ΡΠ°ΡΠ·Π΅ΡΠ΅, Π½ΠΈΠΊΠ°ΠΊΠΈΡ
Π΄ΠΎΠΏ. ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ² Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ. ΠΠ΄Π½Π°ΠΊΠΎ Π²ΡΠ΅ Π΅ΡΠ΅ Π½Π΅ ΡΡΠΎΠ»Ρ ΡΠ°Π΄ΡΠΆΠ½ΠΎ Π½Π° 2020 Π³ΠΎΠ΄. ΠΡΡΠ°Π»ΠΈΡΡ Π±ΡΠ°ΡΠ·Π΅ΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠΎΠΊΠ° Π΅ΡΠ΅ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ
Π‘ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠΌΠΈ ΠΏΠΎΡΠΎΠΊΠ°ΠΌΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π΅Π»Π°ΡΡ ΠΎΡΠ΅Π½Ρ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΡΠ΅ Π²Π΅ΡΠΈ: ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠ»ΠΎΠ½ΠΈΡΠΎΠ²Π°ΡΡ, ΠΌΠ΅Π½ΡΡΡ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π²ΠΈΠ΄Π΅ΠΎ, ΠΌΠ°Π½ΠΈΠΏΡΠ»ΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠ°ΡΠ΅ΡΡΠ²ΠΎΠΌ Π°ΡΠ΄ΠΈΠΎ, ΠΌΠΎΠΆΠ½ΠΎ Π²Π·ΡΡΡ ΠΈ «ΠΏΡΠΈΡΠ΅ΠΏΠΈΡΡ» Media Stream ΠΏΠΎΡΠΎΠΊ ΠΊ <video> ΡΠ΅Π³Ρ ΠΈ ΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° ΡΠ΅Π±Ρ Π»ΡΠ±ΠΈΠΌΠΎΠ³ΠΎ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠΊΠ΅ html. Π ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΎΠΊ ΠΈ Π½Π° canvas ΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ, ΠΈ Π½Π°ΡΡΠ°Π²ΠΈΡΡ WebGL ΠΈΠ»ΠΈ CSS3, ΠΈ Π½Π°ΠΊΠ»Π°Π΄ΡΠ²Π°ΡΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΡΠΈΠ»ΡΡΡΡ Π½Π° Π²ΠΈΠ΄Π΅ΠΎ, Π·Π°Ρ Π²Π°ΡΡΠ²Π°ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΠΎΠ΅ Π²ΠΈΠ΄Π΅ΠΎ Ρ canvas ΠΈ Π΄Π°Π»Π΅Π΅ ΡΠΆΠ΅ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΏΠΎ ΡΠ΅ΡΠΈ Π½Π° ΡΠ΅ΡΠ²Π΅Ρ, ΡΡΠ°Π½ΡΠΊΠΎΠ΄ΠΈΡΡ ΠΈ ΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°ΡΡ Π²ΡΠ΅ΠΌ ΠΆΠ΅Π»Π°ΡΡΠΈΠΌ (ΠΏΡΠΈΠ²Π΅Ρ bigo live, twitch ΠΈ ΠΏΡΠΎΡΠΈΠ΅). ΠΠ΄Π΅ΡΡ Ρ Π½Π΅ Π±ΡΠ΄Ρ ΡΠ°Π·Π±ΠΈΡΠ°ΡΡ ΠΊΠ°ΠΊ Π΄Π΅Π»Π°ΡΡΡΡ ΡΠ°ΠΊΠΈΠ΅ Π²Π΅ΡΠΈ, ΠΏΡΠΈΠ²Π΅Π΄Ρ ΠΏΠ°ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ², Π½Π°ΠΉΠ΄Π΅Π½Π½ΡΡ Π½Π° ΠΏΡΠΎΡΡΠΎΡΠ°Ρ ΡΠ΅ΡΠΈ:
RTCPeerConnection
ΠΠΎΡ ΠΌΡ ΠΈ ΠΏΠΎΠ΄ΠΎΡΠ»ΠΈ ΠΊ ΡΠΎΠΌΡ, Π° ΠΊΠ°ΠΊ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π²ΠΈΠ΄Π΅ΠΎ Π΄ΡΡΠ³ΠΎΠΌΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ? ΠΠ° ΠΏΠ΅ΡΠ²ΡΠΉ ΠΏΠ»Π°Π½ Π²ΡΡΡΡΠΏΠ°Π΅Ρ
const peerConnection = new RTCPeerConnection({
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
});
ΠΠ΄Π½ΠΎΠΉ ΠΈΠ· ΠΎΠΏΡΠΈΠΉ ΡΠΊΠ°Π·ΡΠ²Π°Π΅ΠΌ iceServers — ΡΡΠΎ ΡΠ΅ΡΠ²Π΅Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°ΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ Π±ΡΠ°ΡΠ·Π΅ΡΠ°ΠΌΠΈ, Π½Π°Ρ ΠΎΠ΄ΡΡΠΈΠΌΠΈΡΡ Π·Π° NAT’ΠΎΠΌ. Π’ΠΎ Π΅ΡΡΡ Π·Π΄Π΅ΡΡ ΡΠ΅ΡΠ°Π΅ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°: ΠΊΠ°ΠΊ ΡΠ·Π½Π°ΡΡ 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 ΡΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΡΠΎΠ±ΡΡΠΈΠ΅ onnegotiationneeded, Π² ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ΅ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎΠ·Π΄Π°ΡΡ offer (Π² ΡΠ΅ΡΠΌΠΈΠ½Π°Ρ SDP — Session Description Protocol) ΠΈ Π½Π°Π·Π½Π°ΡΠΈΡΡ Π² peerConnection ΡΠ΅ΡΠ΅Π· ΠΌΠ΅ΡΠΎΠ΄ setLocalDescription. ΠΠ± SDP — ΡΡΠΎ ΡΡΠΎ ΡΠ°ΠΊΠΎΠ΅ ΠΈ ΠΎ ΡΠΎΡΠΌΠ°ΡΠ°Ρ offer ΠΈ answer — ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΠΌ Π΄Π°Π»Π΅Π΅.
ΠΠΎΡΠ»Π΅ Π½Π°Π·Π½Π°ΡΠ΅Π½ΠΈΡ LocalDescription peerConnection, Π±ΡΠ°ΡΠ·Π΅Ρ «ΡΠΎΠ±ΠΈΡΠ°Π΅Ρ» ice-ΠΊΠ°Π½Π΄ΠΈΠ΄Π°ΡΠΎΠ², ΡΠΎ Π΅ΡΡΡ Π½Π°Ρ ΠΎΠ΄ΠΈΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΠΏΡΡΠΈ Π΄Π»Ρ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΈ ΡΠ΅ΡΠ΅Π· NAT. Π‘ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΡΠΎΠ±ΡΡΠΈΠ΅ onicegatheringstatechange. Π ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ΅ onicegatheringstatechange ΡΠ°Π·ΡΠ΅ΡΠ°Π΅ΠΌ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Ρ webrtc-signaling-ΡΠ΅ΡΠ²Π΅ΡΠΎΠΌ stream Π΄Π»Ρ ΠΎΠ±ΠΌΠ΅Π½Π° Session Description ΠΌΠ΅ΠΆΠ΄Ρ ΠΏΠΈΡΠ°ΠΌΠΈ:
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-ΡΠ΅ΡΠ²Π΅Ρ — ΡΡΠΎ ΡΠ΅ΡΠ²Π΅Ρ, Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠΉ Π΄Π»Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ ΠΎΠ±ΠΌΠ΅Π½Π° session description ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΠΏΠΈΡΠ°ΠΌΠΈ, ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΠΎΡΡΠ΅ΠΉΡΠΈΠΉ websocket ΠΈΠ»ΠΈ xhr-ΡΠ΅ΡΠ²Π΅Ρ Π½Π° Π»ΡΠ±ΠΎΠΌ Π―Π. ΠΠ³ΠΎ Π·Π°Π΄Π°ΡΠ° ΠΏΡΠΎΡΡΠ°: ΠΏΡΠΈΠ½ΡΡΡ session description ΠΎΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΈΡΠ° ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π΄ΡΡΠ³ΠΎΠΌΡ.
ΠΠΎΡΠ»Π΅ ΠΎΠ±ΠΌΠ΅Π½Π° Session descriptions ΠΎΠ±Π΅ ΡΡΠΎΡΠΎΠ½Ρ Π³ΠΎΡΠΎΠ²Ρ ΡΡΠ°Π½ΡΠ»ΠΈΡΠΎΠ²Π°ΡΡ ΠΈ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠΈ, Π½Π° ΡΡΠΎΡΠΎΠ½Π΅, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΡΠΎΠ±ΡΡΠΈΠ΅ ontrack Π½Π° peerConnection, Π² ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ΅ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ, ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌΡΠ΅ ΡΡΠ΅ΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°Π·Π½Π°ΡΠΈΡΡ Π½Π° <video> ΠΈ ΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° Π»ΡΠ±ΠΈΠΌΠΎΠ³ΠΎ ΡΠΎΠ±Π΅ΡΠ΅Π΄Π½ΠΈΠΊΠ°. ΠΠ°Π»Π΅Π΅ ΡΠ΅ΠΎΡΠΈΡ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠΈ.
Π‘ΡΡΠ»ΠΊΠΈ ΠΈ Π»ΠΈΡΠ΅ΡΠ°ΡΡΡΠ°:
Π ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΡΠ°ΡΡΠΈ Ρ ΠΎΡΡ Π΄Π°ΡΡ Π΅ΡΠ΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΡΡΠΈΠΈ ΡΠ΅ΠΎΡΠΈΠΈ ΠΈ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΡΠ°Π·ΠΎΠ±ΡΠ°ΡΡ ΠΏΡΠΈΠ΅ΠΌ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ° Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ΅ Ρ ΠΏΠΎΠΌΠΎΡΡΡ pion, ΡΡΠ°Π½ΡΠΊΠΎΠ΄ΠΈΠ½Π³ Π² HLS ΡΠ΅ΡΠ΅Π· ffmpeg Π΄Π»Ρ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΡΡΠ°Π½ΡΠ»ΡΡΠΈΠΈ Π·ΡΠΈΡΠ΅Π»ΡΠΌ Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅.
ΠΠ»Ρ Π½Π΅ΡΠ΅ΡΠΏΠ΅Π»ΠΈΠ²ΡΡ
:
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com