(αžŸαŸ’αž‘αžΎαžšαžαŸ‚) αž€αžΆαžšαžŸαŸ’αž‘αŸ’αžšαžΈαž˜ webcam αžŠαŸ‚αž›αž‚αŸ’αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αŸ” αž•αŸ’αž“αŸ‚αž€αž‘αžΈ 2. WebRTC

αžŠαžΌαž…αž˜αŸ’αžŠαŸαž… αž˜αž½αž™ αž–αžΈαž’αžαŸ’αžαž”αž‘αž…αžΆαžŸαŸ‹ αž“αž·αž„αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ„αŸ‡αž”αž„αŸ‹αž…αŸ„αž›αžšαž½αž…αž αžΎαž™ αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžŸαžšαžŸαŸαžšαž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αž…αžΆαž€αŸ‹αžœαžΈαžŠαŸαž’αžΌαž–αžΈαž•αŸ’αž‘αžΆαŸ†αž„αž€αŸ’αžšαžŽαžΆαžαŸ‹αžαžΆαž˜αžšαž™αŸˆ websockets αž”αžΆαž“αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž› αž“αž·αž„αžŠαŸ„αž™αž’αž˜αŸ’αž˜αž‡αžΆαžαž·αŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸ„αŸ‡ αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž“αž·αž™αžΆαž™αž™αŸ‰αžΆαž„αžαŸ’αž›αžΈαž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžαžαžœαžΈαžŠαŸαž’αžΌαž–αžΈαž€αžΆαž˜αŸαžšαŸ‰αžΆ αž“αž·αž„αžŸαŸ†αž‘αŸαž„αž–αžΈαž˜αžΈαž€αŸ’αžšαžΌαž αŸ’αžœαžΌαž“αžŠαŸ„αž™αž”αŸ’αžšαžΎ MediaStream API, αžšαž”αŸ€αž”αž’αŸŠαž·αž“αž€αžΌαžŠαžŸαŸ’αž‘αŸ’αžšαžΈαž˜αžŠαŸ‚αž›αž”αžΆαž“αž‘αž‘αž½αž› αž“αž·αž„αž•αŸ’αž‰αžΎαžœαžΆαžαžΆαž˜αžšαž™αŸˆαžšαž“αŸ’αž’αž”αžŽαŸ’αžαžΆαž‰αž‘αŸ…αž€αžΆαž“αŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αžαžΆαž˜αž€αžΆαžšαž–αž·αž αž–αž½αž€αž‚αŸαž˜αž·αž“αž’αŸ’αžœαžΎαž”αŸ‚αž”αž“αŸαŸ‡αž‘αŸ αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αžŸαžΆαž™ αž–αž½αž€αž‚αŸαž”αŸ’αžšαžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž–αž·αžŸαŸαžŸαžŽαžΆαž˜αž½αž™αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαžŠαŸ†αž‘αžΎαž„ αž“αž·αž„αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αŸ– offhand αž“αŸαŸ‡αž’αžΆαž…αž‡αžΆ αž”αžΎαž€αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αŸ’αžŸαžΆαž™αŸ”αž¬αž–αž½αž€αž‚αŸαž”αŸ’αžšαžΎ WebRTC αžŠαŸ‚αž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž—αŸ’αž›αžΆαž˜αŸ—αž…αŸαž‰αž–αžΈαž”αŸ’αžšαž’αž”αŸ‹ αž–αŸ„αž›αž‚αžΊαžœαžΆαž˜αž·αž“αžαž˜αŸ’αžšαžΌαžœαž±αŸ’αž™αžŠαŸ†αž‘αžΎαž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αŸ†αž“αž½αž™αžŽαžΆαž˜αž½αž™ a la flash player αžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž€αžΆαžαŸ‹αž…αŸαž‰αž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€ Chromium αžšαž½αž…αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αžαŸ‚αž’αŸ’αž“αžΌαŸ”

αžαŸ’αž„αŸƒαž“αŸαŸ‡αž™αžΎαž„αž“αžΉαž„αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈ WebRTC αŸ”

Web Real-Time Communication (WebRTC) αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαž–αž·αž’αžΈαž€αžΆαžšαžαŸ‚αž˜αž½αž™αž‘αŸ αžœαžΆαž‚αžΊαž‡αžΆαž”αžŽαŸ’αžαž»αŸ†αž‘αžΆαŸ†αž„αž˜αžΌαž›αž“αŸƒαžŸαŸ’αžαž„αŸ‹αžŠαžΆαžš αž–αž·αž’αžΈαž€αžΆαžš αž“αž·αž„ JavaScript APIs αžŠαŸ‚αž›αžšαž½αž˜αž‚αŸ’αž“αžΆαž•αŸ’αžαž›αŸ‹αž“αžΌαžœαž€αžΆαžšαž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„αžαžΆαž˜αžœαžΈαžŠαŸαž’αžΌ-αž’αžΌαžŒαžΈαž™αŸ‰αžΌαžαžΆαž˜αž–αŸαž›αžœαŸαž›αžΆαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž–αžΈαž‚αŸ’αž“αžΆαž‘αŸ…αžœαž·αž‰αž‘αŸ…αž˜αž€ αž αžΎαž™αž€αŸαž’αžΆαž…αž”αŸ’αžšαžΎαžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž‘αŸαžšαžŽαžΆαž˜αž½αž™αž•αž„αžŠαŸ‚αžšαŸ” αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‚αŸ„αž›αž–αžΈαžšαŸ” αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžŠαžΎαžšαžαž½αž“αžΆαž‘αžΈαž‡αžΆαž˜αž·αžαŸ’αžαž—αŸαž€αŸ’αžαž· αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžœαžΆαž€αŸαž’αžΆαž…αž‡αžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‘αžΌαžšαžŸαŸαž–αŸ’αž‘αž•αž„αžŠαŸ‚αžšαŸ” αžŠαžΎαž˜αŸ’αž”αžΈαžšαŸ€αž”αž…αŸ†αž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„ p2p αžšαžœαžΆαž„αž’αžαž·αžαž·αž‡αž“ αž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžαžΆαž˜αž’αŸŠαžΈαž“αž’αžΊαžŽαž·αžαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αŸ’αžšαž—αŸαž‘αž•αŸ’αžŸαŸαž„αŸ—αž“αŸƒαž€αžΆαžšαž’αŸŠαž·αž“αž€αžΌαžŠαžœαžΈαžŠαŸαž’αžΌ αž“αž·αž„αž’αžΌαžŒαžΈαž™αŸ‰αžΌαž‚αžΊαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‘αžΆαž˜αž‘αžΆαžš αž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αž·αž’αžΈαž€αžΆαžšαž”αžŽαŸ’αžαžΆαž‰αž•αŸ’αžŸαŸαž„αŸ— αž’αžΆαž“αžΆαž“αžΌαžœαž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜αž“αŸƒαž•αŸ’αž“αŸ‚αž€αžšαžΉαž„αž‡αžΆαž˜αž½αž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžαžΆαž˜αž’αŸŠαžΈαž“αž’αžΊαžŽαž·αž (αžαžΆαž˜αžšαž™αŸˆαžŸαŸ’αžšαž‘αžΆαž”αŸ‹ OS)αŸ– αž€αžΆαž˜αŸαžšαŸ‰αžΆαž”αžŽαŸ’αžŠαžΆαž‰ αž€αžΆαžαžŸαŸ†αž‘αŸαž„αŸ” αž”αž…αŸ’αž…αŸαž€αžœαž·αž‘αŸ’αž™αžΆ hodgepodge αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž›αžΆαž€αŸ‹αž“αŸ…αž–αžΈαž€αŸ’αžšαŸ„αž™ JavaScript API abstraction αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž—αžΆαž–αž„αžΆαž™αžŸαŸ’αžšαž½αž›αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž’αž—αž·αžœαžŒαŸ’αžαž“αŸαŸ”

αžœαžΆαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž’αŸ’αž›αžΆαž€αŸ‹αž…αž»αŸ‡αžŠαž›αŸ‹ APIs αž”αžΈ:

  • MediaStream API - αžšαž»αŸ‡αžšαžΎαž›αžΎαž€αž˜αž»αž“ αžαŸ’αž„αŸƒαž“αŸαŸ‡αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αžŸαžšαžŸαŸαžšαž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαž’αŸ†αž–αžΈαž‚αžΆαžαŸ‹αŸ” αž”αž˜αŸ’αžšαžΎαžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αžœαžΈαžŠαŸαž’αžΌ / αž’αžΌαžŒαžΈαž™αŸ‰αžΌαž–αžΈαž•αŸ’αž“αŸ‚αž€αžšαžΉαž„

  • RTCPeerConnection - αž•αŸ’αžαž›αŸ‹αž€αžΆαžšαž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„αžšαžœαžΆαž„αž’αžαž·αžαž·αž‡αž“αž–αžΈαžšαž“αžΆαž€αŸ‹ (p2p)

  • αž†αžΆαž“αŸ‚αž› RTCData - αž”αž˜αŸ’αžšαžΎαžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž‘αŸαžšαž‘αž·αž“αŸ’αž“αž“αŸαž™αž”αŸ†αž–αžΆαž“αžšαžœαžΆαž„αž’αžαž·αžαž·αž‡αž“αž–αžΈαžšαž“αžΆαž€αŸ‹

αž€αŸ†αž–αž»αž„αžšαŸ€αž”αž…αŸ†αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž’αžΌαžŒαžΈαž™αŸ‰αžΌ αž“αž·αž„αžœαžΈαžŠαŸαž’αžΌαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“

αžœαžΆαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™ "αž…αžΆαž”αŸ‹αž™αž€" αž”αžŽαŸ’αžαžΆαž‰αž€αžΆαž˜αŸαžšαŸ‰αžΆ αž“αž·αž„αž˜αžΈαž€αŸ’αžšαžΌαž αŸ’αžœαžΌαž“αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž˜αŸαžŒαŸ€αŸ” αž‡αžΆαž€αžΆαžšαž–αž·αžαžŽαžΆαžŸαŸ‹ αž€αžΆαžšαžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž†αŸ…αž˜αž·αž“αžŸαŸαž€αŸ’αžαž·αžŸαž˜αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αžŸαž“αŸ’αž“αž·αžŸαžΈαž‘αž‘αžΌαžšαž‚αž˜αž“αžΆαž‚αž˜αž“αŸαž‘αŸ αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž“αžΈαž˜αž½αž™αŸ—αžαŸ’αžšαžΌαžœαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ– αž’αŸ’αžœαžΎαž’αŸ„αž™αž”αŸ’αžšαžŸαžΎαžšαž‘αžΎαž„αž“αžΌαžœαž‚αž»αžŽαž—αžΆαž– αž’αŸ’αžœαžΎαžŸαž˜αž€αžΆαž›αž€αž˜αŸ’αž˜αž’αžΌαžŒαžΈαž™αŸ‰αžΌαž‡αžΆαž˜αž½αž™αžœαžΈαžŠαŸαž’αžΌ αžŠαžΆαž€αŸ‹αžŸαž‰αŸ’αž‰αžΆαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž€αžΆαžšαž’αŸ’αžœαžΎαžŸαž˜αž€αžΆαž›αž€αž˜αŸ’αž˜αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αžœαžΈαžŠαŸαž’αžΌ αž“αž·αž„αž’αžΆαž“αžΆαž”αžΆαž“αž“αžΌαžœαž’αžαŸ’αžšαžΆαž”αŸŠαžΈαžαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαž‘αŸ…αž“αžΉαž„αž€αž˜αŸ’αžšαž·αžαž”αž‰αŸ’αž‡αžΌαž“αžŠαŸ‚αž›αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž₯αžαžˆαž”αŸ‹αžˆαžšαžšαž”αžŸαŸ‹αž”αŸ‰αž»αžŸαŸ’αžαž·αŸαŸ” . αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž›αžΎαž’αŸ’αžœαžΈαŸ—αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸαŸ‡ αž’αŸ’αž“αž€αž’αž—αž·αžœαžŒαŸ’αžαž“αŸαž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž–αŸ’αžšαž½αž™αž”αžΆαžšαž˜αŸ’αž—αž’αŸ†αž–αžΈαž€αžΆαžšαž•αŸ’αžŠαž›αŸ‹αž€αžΆαžšαž’αŸŠαž·αž“αž€αžΌαžŠαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž˜αŸαžŒαŸ€αž‘αŸαŸ” αž“αŸ…αžαžΆαž„αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžαžΆαž˜αž’αŸŠαžΈαž“αž’αžΊαžŽαž·αžαž‘αŸ†αž“αžΎαž” αž˜αžΆαž“αžŸαŸ’αžšαž‘αžΆαž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž½αž…αž αžΎαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž…αžΆαž”αŸ‹αž™αž€ αž€αžΆαžšαž€αŸ‚αž›αž˜αŸ’αž’αž‚αž»αžŽαž—αžΆαž– (αž›αž»αž”αžŸαŸ†αž‘αŸαž„ αž“αž·αž„αžŸαŸ†αž‘αŸαž„αž…αŸαž‰αž–αžΈαžŸαŸ†αž‘αŸαž„ αž€αŸ‚αž›αž˜αŸ’αž’αžšαžΌαž”αž—αžΆαž–) αž€αžΆαžšαž’αŸŠαž·αž“αž€αžΌαžŠαžœαžΈαžŠαŸαž’αžΌ αž“αž·αž„αžŸαŸ†αž‘αŸαž„αŸ” αž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸαžŸαŸ’αžšαž‘αžΆαž”αŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αž“αŸ…αž€αŸ’αž“αž»αž„αžšαžΌαž”αž—αž–αŸ” 1:

(αžŸαŸ’αž‘αžΎαžšαžαŸ‚) αž€αžΆαžšαžŸαŸ’αž‘αŸ’αžšαžΈαž˜ webcam αžŠαŸ‚αž›αž‚αŸ’αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αŸ” αž•αŸ’αž“αŸ‚αž€αž‘αžΈ 2. WebRTCαž’αž„αŸ’αž€αžšαŸ” 1. αžŸαŸ’αžšαž‘αžΆαž”αŸ‹αž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž’αžΌαžŒαžΈαž™αŸ‰αžΌ αž“αž·αž„αžœαžΈαžŠαŸαž’αžΌαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€

αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„ αž˜αž·αž“αž˜αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸαŸ” αž˜αž·αž“αžαŸ’αžšαžΌαžœαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αŸ†αž“αž½αž™αž‘αŸαŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž’αŸ’αžœαžΈαŸ—αž“αŸ…αžαŸ‚αž˜αž·αž“αž˜αžΆαž“αž—αžΆαž–αžšαžŸαŸ‹αžšαžœαžΎαž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž†αŸ’αž“αžΆαŸ† αŸ’αŸ αŸ’αŸ αŸ” αž˜αžΆαž“αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžŠαŸ‚αž›αž˜αž·αž“αž‘αžΆαž“αŸ‹αž‚αžΆαŸ†αž‘αŸ’αžšαž–αŸαž‰αž›αŸαž‰ MediaStream APIαž’αŸ’αž“αž€αž’αžΆαž…αž’αŸ’αžœαžΎαžαžΆαž˜αžαŸ†αžŽ αž“αž·αž„αž˜αžΎαž›αžαžΆαžšαžΆαž„αž—αžΆαž–αž†αž”αž‚αŸ’αž“αžΆαž“αŸ…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž”αŸ†αž•αž»αžαŸ” αž‡αžΆαž–αž·αžŸαŸαžŸ IE αž˜αžΆαž“αž€αžΆαžšαžαž€αž…αž·αžαŸ’αžαž˜αŸ’αžαž„αž‘αŸ€αžαŸ”

αž’αŸ’αž“αž€αž’αžΆαž…αž’αŸ’αžœαžΎαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž‚αž½αžšαž±αŸ’αž™αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαž‡αžΆαž˜αž½αž™αž“αžΉαž„αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αžŠαŸ‚αž›αž‘αž‘αž½αž›αž”αžΆαž“αŸ– αž’αŸ’αž“αž€αž’αžΆαž…αž€αŸ’αž›αžΌαž“ αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‚αž»αžŽαž—αžΆαž–αž”αž„αŸ’αž αžΆαž‰αžœαžΈαžŠαŸαž’αžΌ αžšαŸ€αž”αž…αŸ†αž‚αž»αžŽαž—αžΆαž–αžŸαŸ†αž‘αŸαž„ αž’αŸ’αž“αž€αž’αžΆαž…αž™αž€ αž“αž·αž„ "αž—αŸ’αž‡αžΆαž”αŸ‹" αžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž˜αŸαžŒαŸ€αž‘αŸ… tag αž αžΎαž™αž˜αžΎαž›αžαŸ’αž›αž½αž“αž―αž„αž“αŸ…αž›αžΎαž‘αŸ†αž–αŸαžš html αŸ” αž¬αž’αŸ’αž“αž€αž’αžΆαž…αž‚αžΌαžšαžŸαŸ’αž‘αŸ’αžšαžΈαž˜αž“αŸ…αž›αžΎαž•αŸ’αž‘αžΆαŸ†αž„αž€αŸ’αžšαžŽαžΆαžαŸ‹ αž αžΎαž™αž€αŸ†αžŽαžαŸ‹ WebGL ឬ CSS3 αž αžΎαž™αž’αž“αž»αžœαžαŸ’αžαžαž˜αŸ’αžšαž„αž•αŸ’αžŸαŸαž„αŸ—αž‘αŸ…αžœαžΈαžŠαŸαž’αžΌ αž…αžΆαž”αŸ‹αž™αž€αžœαžΈαžŠαŸαž’αžΌαžŠαŸ‚αž›αž”αžΆαž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΈαž•αŸ’αž‘αžΆαŸ†αž„αž€αŸ’αžšαžŽαžΆαžαŸ‹ αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž•αŸ’αž‰αžΎαžœαžΆαžαžΆαž˜αž”αžŽαŸ’αžαžΆαž‰αž‘αŸ…αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ αž”αž˜αŸ’αž›αŸ‚αž„αž€αžΌαžŠ αž“αž·αž„αž•αŸ’αžŸαž–αŸ’αžœαž•αŸ’αžŸαžΆαž™αžŠαž›αŸ‹αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αž“αžΆ (αž‡αŸ†αžšαžΆαž”αžŸαž½αžš 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 αž‡αžΆαž‡αž˜αŸ’αžšαžΎαžŸαž˜αž½αž™αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αž‡αž˜αŸ’αžšαžΎαžŸ - αž“αŸαŸ‡αž‚αžΊαž‡αžΆ server αžŠαŸ‚αž›αž‡αž½αž™αž•αŸ’αžαž›αŸ‹αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αžšαžœαžΆαž„ browsers αž–αžΈαžšαž“αŸ…αž–αžΈαž€αŸ’αžšαŸ„αž™ NAT'omαŸ” αž“αŸ„αŸ‡αž‚αžΊαž”αž‰αŸ’αž αžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž“αŸ…αž‘αžΈαž“αŸαŸ‡αŸ– αžšαž”αŸ€αž”αžŸαŸ’αžœαŸ‚αž„αžšαž€ ip αž“αŸƒ interlocutor αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž‚αžΆαžαŸ‹αž“αŸ…αž–αžΈαž€αŸ’αžšαŸ„αž™ 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 handler αž™αžΎαž„αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž—αŸ’αž‡αžΆαž”αŸ‹αž‘αŸ…αž”αžŽαŸ’αžαžΆαž‰ webrtc-signaling-server 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-server αž‚αžΊαž‡αžΆαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αžΆαžšαž–αžŽαŸŒαž“αžΆαžŸαž˜αŸαž™αžšαžœαžΆαž„αž˜αž·αžαŸ’αžαž—αž€αŸ’αžŠαž·αž–αžΈαžšαž“αžΆαž€αŸ‹ αžœαžΆαž’αžΆαž…αž‡αžΆ websocket ឬ xhr-server αžŸαžΆαž˜αž‰αŸ’αž‰αž”αŸ†αž•αž»αžαž“αŸ…αž›αžΎ PL αžŽαžΆαž˜αž½αž™αŸ” αž—αžΆαžšαž€αž·αž…αŸ’αž…αžšαž”αžŸαŸ‹αžœαžΆαž‚αžΊαžŸαžΆαž˜αž‰αŸ’αž‰αŸ– αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž™αž€αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαžœαž‚αŸ’αž‚αž–αžΈαž˜αž·αžαŸ’αžαž—αŸαž€αŸ’αžαž·αž˜αž½αž™ αž αžΎαž™αž•αŸ’αž‘αŸαžšαžœαžΆαž‘αŸ…αž˜αž½αž™αž‘αŸ€αžαŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαžœαž‚αŸ’αž‚ αž—αžΆαž‚αžΈαž‘αžΆαŸ†αž„αžŸαž„αžαžΆαž„αžαŸ’αžšαŸ€αž˜αžαŸ’αž›αž½αž“αž‡αžΆαžŸαŸ’αžšαŸαž…αžŠαžΎαž˜αŸ’αž”αžΈαž…αžΆαž€αŸ‹αž•αŸ’αžŸαžΆαž™ αž“αž·αž„αž‘αž‘αž½αž›αž€αžΆαžšαž•αŸ’αžŸαžΆαž™αžœαžΈαžŠαŸαž’αžΌ αž“αŸ…αž•αŸ’αž“αŸ‚αž€αžŠαŸ‚αž›αž‘αž‘αž½αž›αž€αžΆαžšαž•αŸ’αžŸαžΆαž™αžœαžΈαžŠαŸαž’αžΌ αž–αŸ’αžšαžΉαžαŸ’αžαž·αž€αžΆαžšαžŽαŸαž“αŸ…αž›αžΎαž•αŸ’αž›αžΌαžœαžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸαŸ‡αž“αŸ…αž›αžΎ peerConnection αž“αŸ…αž€αŸ’αž“αž»αž„αž§αž”αž€αžšαžŽαŸαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŠαŸ‚αž›αž”αž‘αžŠαŸ‚αž›αž‘αž‘αž½αž›αž”αžΆαž“αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αž‘αŸ… αž αžΎαž™αž˜αžΎαž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΆαžŸαŸ’αžšαŸαž™αž‘αžΆαž€αŸ‹αž‘αž„αžŠαŸ‚αž›αž’αŸ’αž“αž€αž…αžΌαž›αž…αž·αžαŸ’αžαŸ” αž‘αŸ’αžšαžΉαžŸαŸ’αžαžΈ αž“αž·αž„αž–αŸαžαŸŒαž˜αžΆαž“αž›αž˜αŸ’αž’αž·αžαž”αž“αŸ’αžαŸ‚αž˜αŸ”

αžαŸ†αžŽαž—αŸ’αž‡αžΆαž”αŸ‹ αž“αž·αž„αž’αž€αŸ’αžŸαžšαžŸαž·αž›αŸ’αž”αŸαŸ–

https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection - αž―αž€αžŸαžΆαžš RTCPeerConnection

https://github.com/pion/webrtc - αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž–αž·αž’αžΈαž€αžΆαžš WebRTC αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš

https://webrtcforthecurious.com/ - αžŸαŸ€αžœαž—αŸ…αž–αžΈαž’αŸ’αž“αž€αž”αž„αŸ’αž€αžΎαž pion

https://hpbn.co/ - αžŸαŸ€αžœαž—αŸ…αž”αžŽαŸ’αžαžΆαž‰αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžŠαŸ‚αž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžαŸ’αž–αžŸαŸ‹αŸ” αž”αž‰αŸ’αž αžΆαž“αŸƒαž€αžΆαžšαž’αžΆαž“αžΆαž“αžΌαžœαž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžαŸ’αž–αžŸαŸ‹αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‚αŸαž αž‘αŸ†αž–αŸαžšαžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž—αžΆαž€αŸ’αžŸαžΆαž›αž˜αŸ’αž’αž·αžαŸ” αž“αŸ…αž…αž»αž„αž”αž‰αŸ’αž…αž”αŸ‹ WebRTC αžαŸ’αžšαžΌαžœαž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαŸ” αžŸαŸ€αžœαž—αŸ…αž“αŸαŸ‡αž–αž·αžαž‡αžΆαž…αžΆαžŸαŸ‹ (2013) αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αž·αž“αž”αžΆαžαŸ‹αž”αž„αŸ‹αž—αžΆαž–αž–αžΆαž€αŸ‹αž–αŸαž“αŸ’αž’αžšαž”αžŸαŸ‹αžœαžΆαž‘αŸαŸ”

αž“αŸ…αž•αŸ’αž“αŸ‚αž€αž”αž“αŸ’αž‘αžΆαž”αŸ‹ αžαŸ’αž‰αž»αŸ†αž…αž„αŸ‹αž•αŸ’αžαž›αŸ‹αž•αŸ’αž“αŸ‚αž€αž˜αž½αž™αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαž“αŸƒαž‘αŸ’αžšαžΉαžŸαŸ’αžαžΈ αž“αž·αž„αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αž αžŠαžΎαž˜αŸ’αž”αžΈαžœαž·αž—αžΆαž‚αž€αžΆαžšαž‘αž‘αž½αž› αž“αž·αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΆαžšαž•αŸ’αžŸαžΆαž™αžœαžΈαžŠαŸαž’αžΌαž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαžŠαŸ„αž™αž”αŸ’αžšαžΎ pion αž”αŸ†αž”αŸ’αž›αŸ‚αž„αž‘αŸ…αž‡αžΆ HLS αžαžΆαž˜αžšαž™αŸˆ ffmpeg αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αžŸαžΆαž™αž‡αžΆαž”αž“αŸ’αžαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‘αŸ…αž€αžΆαž“αŸ‹αž’αŸ’αž“αž€αž˜αžΎαž›αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αŸ”

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž˜αž·αž“αž…αŸαŸ‡αž’αžαŸ‹αž’αŸ’αž˜αžαŸ‹αŸ– αž‚αŸ†αžšαžΌαžŠαžΎαž˜αžŠαŸαž–αŸ’αžšαŸƒαž•αŸ’αžŸαŸƒαžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αž“αŸƒαž€αžΆαžšαž•αŸ’αžŸαžΆαž™αžœαžΈαžŠαŸαž’αžΌαž–αžΈ webcam αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž”αŸ’αžšαžαž·αž€αž˜αŸ’αž˜αžαžΆαž˜αžšαž™αŸˆαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαžŠαŸ‚αž›αž˜αžΆαž“αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž›αžΎ pion αž“αŸ…αž€αŸ’αž“αž»αž„ twitch (αž“αŸαŸ‡αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž‡αžΆαž€αžΆαžšαž–αž·αžŸαŸ„αž’αž“αŸ)αŸ”

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹