ΠΠ°ΠΊ-ΡΠΎ Π² ΠΈΠ· ΡΡΠ°ΡΠΈΠ½Π½ΡΡ ΠΈ ΡΠΆΠ΅ Π·Π°Π±ΡΠΎΡΠ΅Π½Π½ΡΡ ΡΡΠ°ΡΠ΅ΠΉ Ρ ΠΏΠΈΡΠ°Π» ΠΎ ΡΠΎΠΌ, ΠΊΠ°ΠΊ Π»Π΅Π³ΠΊΠΎ ΠΈ Π½Π΅ΠΏΡΠΈΠ½ΡΠΆΠ΄Π΅Π½Π½ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΡΠ°Π½ΡΠ»ΠΈΡΠΎΠ²Π°ΡΡ Π²ΠΈΠ΄Π΅ΠΎ Ρ canvas ΡΠ΅ΡΠ΅Π· websockets. Π ΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ ΠΏΠΎΠ²Π΅ΡΡ Π½ΠΎΡΡΠ½ΠΎ ΡΠ°ΡΡΠΊΠ°Π·ΡΠ²Π°Π» ΠΎ ΡΠΎΠΌ, ΠΊΠ°ΠΊ Π·Π°Ρ Π²Π°ΡΠΈΡΡ Π²ΠΈΠ΄Π΅ΠΎ Ρ ΠΊΠ°ΠΌΠ΅ΡΡ ΠΈ Π·Π²ΡΠΊ Ρ ΠΌΠΈΠΊΡΠΎΡΠΎΠ½Π° ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²ΠΎΠΌ , ΠΊΠ°ΠΊ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠΉ ΠΏΠΎΡΠΎΠΊ ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°ΡΡ ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ ΡΠ΅ΡΠ΅Π· websockets Π½Π° ΡΠ΅ΡΠ²Π΅Ρ. ΠΠ΄Π½Π°ΠΊΠΎ Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΡΡΠΈ ΡΠ°ΠΊ Π½Π΅ Π΄Π΅Π»Π°ΡΡ, Π΄Π»Ρ ΡΡΠ°Π½ΡΠ»ΡΡΠΈΠΉ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ Π»ΠΈΠ±ΠΎ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠΉ ΡΠΎΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π½ΡΠΆΠ½ΠΎ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°ΡΡ ΠΈ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°ΡΡ: Π½Π°Π²ΡΠΊΠΈΠ΄ΠΊΡ ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ , Π»ΠΈΠ±ΠΎ Π·Π°Π΄Π΅ΠΉΡΡΠ²ΡΡΡ WebRTC, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΠΏΡΡΠΌΠΎ ΠΈΠ· ΠΊΠΎΡΠΎΠ±ΠΊΠΈ, ΡΠΎ Π΅ΡΡΡ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ Π½ΠΈΠΊΠ°ΠΊΠΈΡ ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ² Π°Π»Ρ flash player, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΠΎΡ ΡΠΆΠ΅ Π² Π΄Π΅ΠΊΠ°Π±ΡΠ΅ Π²ΡΠΏΠΈΠ»ΡΡ ΠΈΠ· Chromium Π±ΡΠ°ΡΠ·Π΅ΡΠ°.
Π‘Π΅Π³ΠΎΠ΄Π½Ρ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΠΌ ΠΎ WebRTC.
Web Real-Time Communication (WebRTC) ΡΡΠΎ Π½Π΅ ΠΎΠ΄ΠΈΠ½ ΠΏΡΠΎΡΠΎΠΊΠΎΠ», ΡΡΠΎ ΡΠ΅Π»Π°Ρ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ ΡΡΠ°Π½Π΄Π°ΡΡΠΎΠ², ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠ² ΠΈ JavaScript API, ΠΊΠΎΡΠΎΡΡΠ΅ Π²ΡΠ΅ Π²ΠΌΠ΅ΡΡΠ΅ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°ΡΡ peer-to-peer Π²ΠΈΠ΄Π΅ΠΎ-Π°ΡΠ΄ΠΈΠΎ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΈ Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½Ρ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π»ΡΠ±ΡΡ Π±ΠΈΠ½Π°ΡΠ½ΡΡ Π΄Π°Π½Π½ΡΡ . ΠΠ±ΡΡΠ½ΠΎ ΠΏΠΈΡΠ°ΠΌΠΈ Π²ΡΡΡΡΠΏΠ°ΡΡ Π±ΡΠ°ΡΠ·Π΅ΡΡ, Π½ΠΎ ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈ ΠΌΠΎΠ±ΠΈΠ»ΡΠ½ΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ. ΠΠ»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ ΠΎΡΠ³Π°Π½ΠΈΠ·ΠΎΠ²Π°ΡΡ p2p ΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° Π±ΡΠ°ΡΠ·Π΅ΡΠΎΠΌ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ Π²ΠΈΠ΄ΠΎΠ² ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎ ΠΈ Π°ΡΠ΄ΠΈΠΎ, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π° ΡΠ΅ΡΠ΅Π²ΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠ², ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΠ΅ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ ΠΆΠ΅Π»Π΅Π·Π° Ρ Π±ΡΠ°ΡΠ·Π΅ΡΠΎΠΌ (ΡΠ΅ΡΠ΅Π· ΡΠ»ΠΎΠΈ ΠΠ‘): Π²Π΅Π±ΠΊΠ°ΠΌΠ΅Ρ, Π·Π²ΡΠΊΠΎΠ²ΡΡ ΠΊΠ°ΡΡ. ΠΡΡ ΡΡΠ° ΠΌΠ΅ΡΠ°Π½ΠΈΠ½Π° ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ ΡΠΊΡΡΡΠ° Π·Π° Π°Π±ΡΡΡΠ°ΠΊΡΠΈΠ΅ΠΉ JavaScript API Π΄Π»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°.
ΠΡΠ΅ ΡΠ²ΠΎΠ΄ΠΈΡΡΡ Π² ΠΈΡΠΎΠ³Π΅ ΠΊ ΡΡΠ΅ΠΌ API:
β ΡΠ°Π·Π±ΠΈΡΠ°Π»ΠΈ Π² ΠΏΡΠΎΡΠ»ΡΠΉ ΡΠ°Π·, ΡΠ΅Π³ΠΎΠ΄Π½Ρ Π΅ΡΠ΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π½Π°ΠΏΠΈΡΡ ΠΏΡΠΎ Π½Π΅Π³ΠΎ. Π‘Π»ΡΠΆΠΈΡ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎ/Π°ΡΠ΄ΠΈΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ² ΠΎΡ Β«ΠΆΠ΅Π»Π΅Π·Π°Β»
β ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΠ²Π°Π΅Ρ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ (p2p)
β ΡΠ»ΡΠΆΠΈΡ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΡ Π΄Π°Π½Π½ΡΡ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°ΠΌΠΈ
ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° Π°ΡΠ΄ΠΈΠΎ ΠΈ Π²ΠΈΠ΄Π΅ΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ² ΠΊ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠ΅
ΠΡΠ΅ Π½Π°ΡΠΈΠ½Π°Π΅ΡΡΡ Ρ Β«Π·Π°Ρ Π²Π°ΡΠ°Β» ΠΌΠ΅Π΄ΠΈΠ°ΠΏΠΎΡΠΎΠΊΠΎΠ² Π²Π΅Π±ΠΊΠ°ΠΌΠ΅ΡΡ ΠΈ ΠΌΠΈΠΊΡΠΎΡΠΎΠ½Π°. Π‘ΡΡΡΠ΅ ΠΏΠΎΡΠΎΠΊΠΈ ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ ΠΆΠ΅ Π½Π΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡ Π΄Π»Ρ ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΠΈ ΡΠ΅Π»Π΅ΠΊΠΎΠ½ΡΠ΅ΡΠ΅Π½ΡΠΈΠΈ, ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΏΠΎΡΠΎΠΊ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ: ΡΠ»ΡΡΡΠΈΡΡ ΠΊΠ°ΡΠ΅ΡΡΠ²ΠΎ, ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ Π°ΡΠ΄ΠΈΠΎ Ρ Π²ΠΈΠ΄Π΅ΠΎ, ΡΠ°ΡΡΡΠ°Π²ΠΈΡΡ ΠΌΠ΅ΡΠΊΠΈ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ Π² Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ΅, ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ ΠΌΠ΅Π½ΡΡΡΠ΅ΠΉΡΡ ΡΠΈΡΠΎΡΠ΅ ΠΏΡΠΎΠΏΡΡΠΊΠ°Π½ΠΈΡ ΠΊΠ°Π½Π°Π»Π° Π±ΠΈΡΡΠ΅ΠΉΡ. ΠΡΠ°ΡΠ·Π΅Ρ Π²ΡΠ΅ ΡΡΠΎ Π±Π΅ΡΠ΅Ρ Π½Π° ΡΠ΅Π±Ρ, ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΡ Π΄Π°ΠΆΠ΅ Π½Π΅ Π½Π°Π΄ΠΎ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΈΡΡΡΡ ΠΎΠ± ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΠΈ ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ΅Π΄ΠΈΠ°-ΠΏΠΎΡΠΎΠΊΠΎΠ². ΠΠ½ΡΡΡΠΈ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ Π±ΡΠ°ΡΠ·Π΅ΡΠ° ΡΠΆΠ΅ ΠΏΡΠΈΡΡΡΡΡΠ²ΡΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΠ΅ ΡΠ»ΠΎΠΈ Π·Π°Ρ Π²Π°ΡΠ°, ΡΠ»ΡΡΡΠ΅Π½ΠΈΡ ΠΊΠ°ΡΠ΅ΡΡΠ²Π° (ΡΠ±ΡΠ°ΡΡ ΡΡ ΠΎ ΠΈ ΡΡΠΌ ΠΈΠ· Π·Π²ΡΠΊΠ°, ΡΠ»ΡΡΡΠΈΡΡ ΠΊΠ°ΡΡΠΈΠ½ΠΊΡ), ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎ ΠΈ Π°ΡΠ΄ΠΈΠΎ. Π‘Ρ Π΅ΠΌΠ° ΡΠ»ΠΎΠ΅Π² ΠΏΠΎΠΊΠ°Π·Π°Π½Π° ΡΠΈΡ. 1:
Π ΠΈΡ. 1. Π‘Π»ΠΎΠΈ Π°ΡΠ΄ΠΈΠΎ ΠΈ Π²ΠΈΠ΄Π΅ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅
ΠΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΠΏΡΡΠΌΠΎ Π² ΡΠ°ΠΌΠΎΠΌ Π±ΡΠ°ΡΠ·Π΅ΡΠ΅, Π½ΠΈΠΊΠ°ΠΊΠΈΡ Π΄ΠΎΠΏ. ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ² Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ. ΠΠ΄Π½Π°ΠΊΠΎ Π²ΡΠ΅ Π΅ΡΠ΅ Π½Π΅ ΡΡΠΎΠ»Ρ ΡΠ°Π΄ΡΠΆΠ½ΠΎ Π½Π° 2020 Π³ΠΎΠ΄. ΠΡΡΠ°Π»ΠΈΡΡ Π±ΡΠ°ΡΠ·Π΅ΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠΎΠΊΠ° Π΅ΡΠ΅ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ , Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΉΡΠΈ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅ ΠΈ Π² ΡΠ°ΠΌΠΎΠΌ Π½ΠΈΠ·Ρ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ ΡΠ°Π±Π»ΠΈΡΡ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΠΈ. Π ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ IE ΡΠ½ΠΎΠ²Π° ΡΠ°Π·ΠΎΡΠ°ΡΠΎΠ²ΡΠ²Π°Π΅Ρ.
Π‘ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠΌΠΈ ΠΏΠΎΡΠΎΠΊΠ°ΠΌΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π΅Π»Π°ΡΡ ΠΎΡΠ΅Π½Ρ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΡΠ΅ Π²Π΅ΡΠΈ: ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠ»ΠΎΠ½ΠΈΡΠΎΠ²Π°ΡΡ, ΠΌΠ΅Π½ΡΡΡ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π²ΠΈΠ΄Π΅ΠΎ, ΠΌΠ°Π½ΠΈΠΏΡΠ»ΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠ°ΡΠ΅ΡΡΠ²ΠΎΠΌ Π°ΡΠ΄ΠΈΠΎ, ΠΌΠΎΠΆΠ½ΠΎ Π²Π·ΡΡΡ ΠΈ Β«ΠΏΡΠΈΡΠ΅ΠΏΠΈΡΡΒ» Media Stream ΠΏΠΎΡΠΎΠΊ ΠΊ <video> ΡΠ΅Π³Ρ ΠΈ ΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° ΡΠ΅Π±Ρ Π»ΡΠ±ΠΈΠΌΠΎΠ³ΠΎ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠΊΠ΅ html. Π ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΎΠΊ ΠΈ Π½Π° canvas ΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ, ΠΈ Π½Π°ΡΡΠ°Π²ΠΈΡΡ WebGL ΠΈΠ»ΠΈ CSS3, ΠΈ Π½Π°ΠΊΠ»Π°Π΄ΡΠ²Π°ΡΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΡΠΈΠ»ΡΡΡΡ Π½Π° Π²ΠΈΠ΄Π΅ΠΎ, Π·Π°Ρ Π²Π°ΡΡΠ²Π°ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΠΎΠ΅ Π²ΠΈΠ΄Π΅ΠΎ Ρ canvas ΠΈ Π΄Π°Π»Π΅Π΅ ΡΠΆΠ΅ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΏΠΎ ΡΠ΅ΡΠΈ Π½Π° ΡΠ΅ΡΠ²Π΅Ρ, ΡΡΠ°Π½ΡΠΊΠΎΠ΄ΠΈΡΡ ΠΈ ΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°ΡΡ Π²ΡΠ΅ΠΌ ΠΆΠ΅Π»Π°ΡΡΠΈΠΌ (ΠΏΡΠΈΠ²Π΅Ρ bigo live, twitch ΠΈ ΠΏΡΠΎΡΠΈΠ΅). ΠΠ΄Π΅ΡΡ Ρ Π½Π΅ Π±ΡΠ΄Ρ ΡΠ°Π·Π±ΠΈΡΠ°ΡΡ ΠΊΠ°ΠΊ Π΄Π΅Π»Π°ΡΡΡΡ ΡΠ°ΠΊΠΈΠ΅ Π²Π΅ΡΠΈ, ΠΏΡΠΈΠ²Π΅Π΄Ρ ΠΏΠ°ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ², Π½Π°ΠΉΠ΄Π΅Π½Π½ΡΡ Π½Π° ΠΏΡΠΎΡΡΠΎΡΠ°Ρ ΡΠ΅ΡΠΈ:
β ΡΠ΅Π±ΡΡΠ° Π·Π°Π½ΠΈΠΌΠ°ΡΡΡΡ realtime CV Π½Π° Javascript. Π£ Π½ΠΈΡ Π΅ΡΡΡ ΡΠ΅Π»ΡΠΉ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ js-Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠΎΠΌ Π½Π° canvas: Π΄Π΅ΡΠ΅ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π»ΠΈΡ, ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², Π½Π°Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΡΠΈΠ»ΡΡΡΠΎΠ² (ΠΌΠ°ΡΠΎΠΊ, ΠΊΠ°ΠΊ Π² ΠΈΠ½ΡΡΠ΅) ΠΈ ΠΏΡ. ΠΡΠ»ΠΈΡΠ½ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π±Π΅Π· Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΡ ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΡΠΌΠΎ Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ Π²ΠΈΠ΄Π΅ΠΎ Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ.
β Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ API ΠΏΠΎ Π·Π°Ρ Π²Π°ΡΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ° Ρ canvas. Π£ΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΡΡΡ Π² Chrome, Opera ΠΈ Firefox
RTCPeerConnection
ΠΠΎΡ ΠΌΡ ΠΈ ΠΏΠΎΠ΄ΠΎΡΠ»ΠΈ ΠΊ ΡΠΎΠΌΡ, Π° ΠΊΠ°ΠΊ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π²ΠΈΠ΄Π΅ΠΎ Π΄ΡΡΠ³ΠΎΠΌΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ? ΠΠ° ΠΏΠ΅ΡΠ²ΡΠΉ ΠΏΠ»Π°Π½ Π²ΡΡΡΡΠΏΠ°Π΅Ρ . ΠΡΠ»ΠΈ Π³ΠΎΠ²ΠΎΡΠΈΡΡ ΠΊΡΠ°ΡΠΊΠΎ, ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π½Π° ΡΡΠΎΠΌ ΡΠ°Π³Π΅ Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ 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> ΠΈ ΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° Π»ΡΠ±ΠΈΠΌΠΎΠ³ΠΎ ΡΠΎΠ±Π΅ΡΠ΅Π΄Π½ΠΈΠΊΠ°. ΠΠ°Π»Π΅Π΅ ΡΠ΅ΠΎΡΠΈΡ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠΈ.
Π‘ΡΡΠ»ΠΊΠΈ ΠΈ Π»ΠΈΡΠ΅ΡΠ°ΡΡΡΠ°:
β Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ
β ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠ² WebRTC Π½Π° go
β ΠΊΠ½ΠΈΠΆΠ΅ΡΠΊΠ° ΠΎΡ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Π΅ΠΉ pion
β ΠΊΠ½ΠΈΠ³Π° High Perfomance Browser Networking. Π ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΡΡ ΡΠ°Π·Π±ΠΈΡΠ°ΡΡΡΡ Π²ΠΎΠΏΡΠΎΡΡ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ Π²ΡΡΠΎΠΊΠΎΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ web-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. Π ΠΊΠΎΠ½ΡΠ΅ ΠΎΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ WebRTC. ΠΠ½ΠΈΠΆΠΊΠ° ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ ΡΡΠ°ΡΠ°Ρ (2013), Π½ΠΎ Π½Π΅ ΡΠ΅ΡΡΠ΅Ρ ΡΠ²ΠΎΠ΅ΠΉ Π°ΠΊΡΡΠ°Π»ΡΠ½ΠΎΡΡΠΈ.
Π ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΡΠ°ΡΡΠΈ Ρ ΠΎΡΡ Π΄Π°ΡΡ Π΅ΡΠ΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΡΡΠΈΠΈ ΡΠ΅ΠΎΡΠΈΠΈ ΠΈ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΡΠ°Π·ΠΎΠ±ΡΠ°ΡΡ ΠΏΡΠΈΠ΅ΠΌ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ° Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ΅ Ρ ΠΏΠΎΠΌΠΎΡΡΡ pion, ΡΡΠ°Π½ΡΠΊΠΎΠ΄ΠΈΠ½Π³ Π² HLS ΡΠ΅ΡΠ΅Π· ffmpeg Π΄Π»Ρ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΡΡΠ°Π½ΡΠ»ΡΡΠΈΠΈ Π·ΡΠΈΡΠ΅Π»ΡΠΌ Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅.
ΠΠ»Ρ Π½Π΅ΡΠ΅ΡΠΏΠ΅Π»ΠΈΠ²ΡΡ : (ΡΡΠΎ ΠΏΡΠΎΡΡΠΎ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Ρ).
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com
