WebRTC के साथ रीयल टाइम कम्यूनिकेशन

1. परिचय

WebRTC एक ओपन सोर्स प्रोजेक्ट है. इसका इस्तेमाल, वेब और नेटिव ऐप्लिकेशन में ऑडियो, वीडियो, और डेटा के रीयलटाइम कम्यूनिकेशन को चालू करने के लिए किया जाता है.

WebRTC में कई JavaScript API होते हैं. डेमो देखने के लिए, लिंक पर क्लिक करें.

  • getUserMedia(): ऑडियो और वीडियो कैप्चर करना.
  • MediaRecorder: ऑडियो और वीडियो रिकॉर्ड करें.
  • RTCPeerConnection: उपयोगकर्ताओं के बीच ऑडियो और वीडियो स्ट्रीम करने की सुविधा.
  • RTCDataChannel: उपयोगकर्ताओं के बीच डेटा स्ट्रीम करना.

WebRTC का इस्तेमाल कहाँ किया जा सकता है?

Firefox, Opera, और डेस्कटॉप और Android पर Chrome में. WebRTC, iOS और Android पर नेटिव ऐप्लिकेशन के लिए भी उपलब्ध है.

सिग्नलिंग क्या है?

WebRTC, ब्राउज़र के बीच स्ट्रीमिंग डेटा को ट्रांसफ़र करने के लिए RTCPeerConnection का इस्तेमाल करता है. हालांकि, इसे कम्यूनिकेशन को मैनेज करने और कंट्रोल मैसेज भेजने के लिए भी एक सिस्टम की ज़रूरत होती है. इस प्रोसेस को सिग्नलिंग कहा जाता है. WebRTC, सिग्नल भेजने के तरीकों और प्रोटोकॉल के बारे में नहीं बताता. इस कोडलैब में, मैसेज भेजने के लिए Socket.IO का इस्तेमाल किया जाएगा. हालांकि, इसके कई विकल्प उपलब्ध हैं.

STUN और TURN क्या हैं?

WebRTC को पीयर-टू-पीयर काम करने के लिए डिज़ाइन किया गया है, ताकि उपयोगकर्ता सबसे सीधे तरीके से कनेक्ट हो सकें. हालांकि, WebRTC को असल दुनिया में नेटवर्क की समस्याओं से निपटने के लिए बनाया गया है: क्लाइंट ऐप्लिकेशन को NAT गेटवे और फ़ायरवॉल को पार करना होता है. साथ ही, डायरेक्ट कनेक्शन काम न करने पर पीयर टू पीयर नेटवर्किंग को फ़ॉलबैक की ज़रूरत होती है. इस प्रोसेस के तहत, WebRTC एपीआई, STUN सर्वर का इस्तेमाल करके आपके कंप्यूटर का आईपी पता हासिल करते हैं. साथ ही, पीयर-टू-पीयर कम्यूनिकेशन के काम न करने पर, TURN सर्वर का इस्तेमाल करके रिले सर्वर के तौर पर काम करते हैं. (WebRTC in the real world में इसके बारे में ज़्यादा जानकारी दी गई है.)

क्या WebRTC सुरक्षित है?

WebRTC के सभी कॉम्पोनेंट के लिए एन्क्रिप्शन ज़रूरी है. साथ ही, इसके JavaScript API का इस्तेमाल सिर्फ़ सुरक्षित ऑरिजिन (एचटीटीपीएस या लोकलहोस्ट) से किया जा सकता है. सिग्नलिंग के तरीकों को WebRTC के मानकों के हिसाब से तय नहीं किया जाता. इसलिए, यह आपकी ज़िम्मेदारी है कि आप सुरक्षित प्रोटोकॉल का इस्तेमाल करें.

2. खास जानकारी

वेबकैम से वीडियो पाने और स्नैपशॉट लेने के लिए, एक ऐप्लिकेशन बनाएं. इसके बाद, WebRTC की मदद से उन्हें पीयर-टू-पीयर शेयर करें. इस दौरान, आपको WebRTC के मुख्य एपीआई इस्तेमाल करने और Node.js का इस्तेमाल करके मैसेजिंग सर्वर सेट अप करने का तरीका पता चलेगा.

आपको क्या सीखने को मिलेगा

  • वेबकैम से वीडियो पाना
  • RTCPeerConnection की मदद से वीडियो स्ट्रीम करना
  • RTCDataChannel की मदद से डेटा स्ट्रीम करना
  • मैसेज एक्सचेंज करने के लिए, सिग्नलिंग सेवा सेट अप करना
  • पीयर कनेक्शन और सिग्नलिंग को एक साथ इस्तेमाल करना
  • फ़ोटो खींचें और उसे डेटा चैनल के ज़रिए शेयर करें

आपको किन चीज़ों की ज़रूरत होगी

  • Chrome 47 या उसके बाद का वर्शन
  • Web Server for Chrome का इस्तेमाल करें या अपनी पसंद का कोई वेब सर्वर इस्तेमाल करें.
  • सैंपल कोड
  • टेक्स्ट एडिटर
  • एचटीएमएल, सीएसएस, और JavaScript की बुनियादी जानकारी

3. सैंपल कोड पाना

कोड डाउनलोड करना

अगर आपको git के बारे में जानकारी है, तो इस कोडलब के लिए कोड को GitHub से डाउनलोड किया जा सकता है. इसके लिए, इसे क्लोन करें:

git clone https://github.com/googlecodelabs/webrtc-web

इसके अलावा, कोड की .zip फ़ाइल डाउनलोड करने के लिए, इस बटन पर क्लिक करें:

डाउनलोड की गई zip फ़ाइल खोलें. इससे एक प्रोजेक्ट फ़ोल्डर (adaptive-web-media) अनपैक होगा. इसमें इस कोडलैब के हर चरण के लिए एक फ़ोल्डर होगा. साथ ही, इसमें वे सभी संसाधन होंगे जिनकी आपको ज़रूरत होगी.

आपको कोडिंग से जुड़ा सारा काम work नाम की डायरेक्ट्री में करना होगा.

step-nn फ़ोल्डर में, इस कोडलैब के हर चरण का पूरा वर्शन होता है. ये सिर्फ़ रेफ़रंस के लिए हैं.

वेब सर्वर इंस्टॉल करना और उसकी पुष्टि करना

आपके पास अपने वेब सर्वर का इस्तेमाल करने का विकल्प होता है. हालांकि, यह कोडलैब Chrome Web Server के साथ अच्छी तरह से काम करने के लिए डिज़ाइन किया गया है. अगर आपने अब तक यह ऐप्लिकेशन इंस्टॉल नहीं किया है, तो इसे Chrome Web Store से इंस्टॉल किया जा सकता है.

6ddeb4aee53c0f0e.png

Web Server for Chrome ऐप्लिकेशन इंस्टॉल करने के बाद, बुकमार्क बार, नए टैब पेज या ऐप्लिकेशन लॉन्चर से Chrome ऐप्लिकेशन के शॉर्टकट पर क्लिक करें:

1d2b4aa977ab7e24.png

वेब सर्वर आइकॉन पर क्लिक करें:

27fce4494f641883.png

इसके बाद, आपको यह डायलॉग दिखेगा. इसकी मदद से, अपने लोकल वेब सर्वर को कॉन्फ़िगर किया जा सकता है:

Screen Shot 2016-02-18 at 11.48.14 AM.png

फ़ोल्डर चुनें बटन पर क्लिक करें. इसके बाद, अभी बनाया गया work फ़ोल्डर चुनें. इससे, Chrome में अपने काम की प्रोग्रेस देखी जा सकेगी. इसके लिए, वेब सर्वर यूआरएल सेक्शन में, वेब सर्वर डायलॉग में हाइलाइट किया गया यूआरएल इस्तेमाल करें.

विकल्प में जाकर, index.html को अपने-आप दिखाएं के बगल में मौजूद बॉक्स को चुनें. यह बॉक्स यहां दिखाया गया है:

Screen Shot 2016-02-18 at 11.56.30 AM.png

इसके बाद, वेब सर्वर: चालू है लेबल वाले टॉगल को बाईं ओर स्लाइड करके सर्वर को बंद करें. इसके बाद, इसे दाईं ओर स्लाइड करके फिर से चालू करें.

Screen Shot 2016-02-18 at 12.22.18 PM.png

अब अपने वेब ब्राउज़र में, हाइलाइट किए गए वेब सर्वर यूआरएल पर क्लिक करके, अपनी वर्क साइट पर जाएं. आपको इस तरह का पेज दिखेगा, जो work/index.html से मेल खाता है:

18a705cb6ccc5181.png

ज़ाहिर है, यह ऐप्लिकेशन अभी तक कोई दिलचस्प काम नहीं कर रहा है. फ़िलहाल, यह सिर्फ़ एक बुनियादी ढांचा है. इसका इस्तेमाल हम यह पक्का करने के लिए कर रहे हैं कि आपका वेब सर्वर ठीक से काम कर रहा है. इसके बाद के चरणों में, आपको लेआउट और फ़ंक्शन से जुड़ी सुविधाएं जोड़नी होंगी.

4. वेबकैम से वीडियो स्ट्रीम करना

आपको क्या सीखने को मिलेगा

इस चरण में, आपको इनके बारे में जानकारी मिलेगी:

  • वेबकैम से वीडियो स्ट्रीम पाएं.
  • स्ट्रीम चलाने की सुविधा में बदलाव करना.
  • वीडियो में बदलाव करने के लिए, सीएसएस और एसवीजी का इस्तेमाल करें.

इस चरण का पूरा वर्शन, step-01 फ़ोल्डर में है.

थोड़ा सा एचटीएमएल...

अपनी work डायरेक्ट्री में मौजूद index.html में video और script एलिमेंट जोड़ें:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <video autoplay playsinline></video>

  <script src="js/main.js"></script>

</body>

</html>

...और थोड़ी सी JavaScript

अपने js फ़ोल्डर में मौजूद main.js फ़ाइल में, यह कोड जोड़ें:

'use strict';

// On this codelab, you will be streaming only video (video: true).
const mediaStreamConstraints = {
  video: true,
};

// Video element where stream will be placed.
const localVideo = document.querySelector('video');

// Local stream that will be reproduced on the video.
let localStream;

// Handles success by adding the MediaStream to the video element.
function gotLocalMediaStream(mediaStream) {
  localStream = mediaStream;
  localVideo.srcObject = mediaStream;
}

// Handles error by logging a message to the console with the error message.
function handleLocalMediaStreamError(error) {
  console.log('navigator.getUserMedia error: ', error);
}

// Initializes media stream.
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
  .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);

इसे आज़माएं

अपने ब्राउज़र में index.html खोलें. आपको कुछ ऐसा दिखेगा (इसमें आपके वेबकैम से दिखने वाला व्यू दिखेगा!):

9297048e43ed0f3d.png

यह कैसे काम करता है

getUserMedia() कॉल के बाद, ब्राउज़र उपयोगकर्ता से उसके कैमरे को ऐक्सेस करने की अनुमति मांगता है. ऐसा तब होता है, जब मौजूदा ऑरिजिन के लिए पहली बार कैमरे का ऐक्सेस मांगा गया हो. अगर यह प्रोसेस पूरी हो जाती है, तो एक MediaStream ऑब्जेक्ट दिखता है. इसका इस्तेमाल मीडिया एलिमेंट में srcObject एट्रिब्यूट के ज़रिए किया जा सकता है:

navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
  .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);


}
function gotLocalMediaStream(mediaStream) {
  localVideo.srcObject = mediaStream;
}

constraints आर्ग्युमेंट की मदद से, यह तय किया जा सकता है कि आपको किस तरह का मीडिया चाहिए. इस उदाहरण में, सिर्फ़ वीडियो का इस्तेमाल किया गया है, क्योंकि ऑडियो डिफ़ॉल्ट रूप से बंद होता है:

const mediaStreamConstraints = {
  video: true,
};

वीडियो रिज़ॉल्यूशन जैसी अन्य ज़रूरी शर्तों के लिए, ये कंस्ट्रेंट इस्तेमाल किए जा सकते हैं:

const hdConstraints = {
  video: {
    width: {
      min: 1280
    },
    height: {
      min: 720
    }
  }
}

MediaTrackConstraints स्पेसिफ़िकेशन में, सभी संभावित कंस्ट्रेंट टाइप की सूची दी गई है. हालांकि, सभी ब्राउज़र पर सभी विकल्प काम नहीं करते. अगर मौजूदा कैमरे से, अनुरोध किया गया रिज़ॉल्यूशन इस्तेमाल नहीं किया जा सकता, तो getUserMedia() को OverconstrainedError के साथ अस्वीकार कर दिया जाएगा. साथ ही, उपयोगकर्ता को अपना कैमरा ऐक्सेस करने की अनुमति देने के लिए नहीं कहा जाएगा.

अगर getUserMedia() पूरा हो जाता है, तो वेबकैम से मिलने वाली वीडियो स्ट्रीम को वीडियो एलिमेंट के सोर्स के तौर पर सेट किया जाता है:

function gotLocalMediaStream(mediaStream) {
  localVideo.srcObject = mediaStream;
}

बोनस पॉइंट

  • localStream को पास किया गया localStream ऑब्जेक्ट, ग्लोबल स्कोप में होता है. इसलिए, इसे ब्राउज़र कंसोल से देखा जा सकता है: कंसोल खोलें, stream टाइप करें, और Return दबाएं.getUserMedia() (Chrome में कंसोल देखने के लिए, Ctrl-Shift-J दबाएं. अगर Mac का इस्तेमाल किया जा रहा है, तो Command-Option-J दबाएं.)
  • localStream.getVideoTracks() क्या दिखाता है?
  • localStream.getVideoTracks()[0].stop() को कॉल करके देखें.
  • constraints ऑब्जेक्ट को देखें: इसे {audio: true, video: true} में बदलने पर क्या होता है?
  • वीडियो एलिमेंट का साइज़ क्या है? डिसप्ले साइज़ के बजाय, JavaScript से वीडियो का नैचुरल साइज़ कैसे पाया जा सकता है? जांच करने के लिए, Chrome DevTools का इस्तेमाल करें.
  • वीडियो एलिमेंट में सीएसएस फ़िल्टर जोड़कर देखें. उदाहरण के लिए:
video {
  filter: blur(4px) invert(1) opacity(0.5);
}
  • एसवीजी फ़िल्टर जोड़कर देखें. उदाहरण के लिए:
video {
   filter: hue-rotate(180deg) saturate(200%);
 }

आपको क्या सीखने को मिला

इस चरण में, आपने इनके बारे में जाना:

  • अपने वेबकैम से वीडियो पाना.
  • मीडिया से जुड़ी पाबंदियां सेट करें.
  • वीडियो एलिमेंट में बदलाव करना.

इस चरण का पूरा वर्शन, step-01 फ़ोल्डर में है.

सलाह

  • video एलिमेंट पर autoplay एट्रिब्यूट को शामिल करना न भूलें. इसके बिना, आपको सिर्फ़ एक फ़्रेम दिखेगा!
  • getUserMedia() की सीमाओं के लिए कई और विकल्प उपलब्ध हैं. webrtc.github.io/samples/src/content/peerconnection/constraints पर जाकर डेमो देखें. आपको उस साइट पर WebRTC के कई दिलचस्प सैंपल दिखेंगे.

सबसे सही तरीका

  • पक्का करें कि वीडियो एलिमेंट, कंटेनर से बाहर न जा रहा हो. हमने वीडियो के लिए, पसंदीदा साइज़ और ज़्यादा से ज़्यादा साइज़ सेट करने के लिए width और max-width को जोड़ा है. ब्राउज़र, ऊंचाई का हिसाब अपने-आप लगाएगा:
video {
  max-width: 100%;
  width: 320px;
}

अगला

आपके पास वीडियो है, लेकिन उसे स्ट्रीम कैसे किया जाए? अगले चरण में जानें!

5. RTCPeerConnection की मदद से वीडियो स्ट्रीम करना

आपको क्या सीखने को मिलेगा

इस चरण में, आपको इनके बारे में जानकारी मिलेगी:

  • WebRTC शिम, adapter.js की मदद से, ब्राउज़र के बीच के अंतर को कम करें.
  • वीडियो स्ट्रीम करने के लिए, RTCPeerConnection API का इस्तेमाल करें.
  • मीडिया कैप्चर और स्ट्रीमिंग को कंट्रोल करना.

इस चरण का पूरा वर्शन, step-2 फ़ोल्डर में है.

RTCPeerConnection क्या है?

RTCPeerConnection एक एपीआई है. इसका इस्तेमाल, वीडियो और ऑडियो स्ट्रीम करने और डेटा ट्रांसफ़र करने के लिए WebRTC कॉल करने के लिए किया जाता है.

इस उदाहरण में, एक ही पेज पर दो RTCPeerConnection ऑब्जेक्ट (जिन्हें पीयर कहा जाता है) के बीच कनेक्शन सेट अप किया गया है.

यह ज़्यादा काम का नहीं है, लेकिन इससे यह समझने में मदद मिलती है कि RTCPeerConnection कैसे काम करता है.

वीडियो के एलिमेंट और कंट्रोल बटन जोड़ना

index.html में, एक वीडियो एलिमेंट को दो वीडियो एलिमेंट और तीन बटन से बदलें:

<video id="localVideo" autoplay playsinline></video>
<video id="remoteVideo" autoplay playsinline></video>


<div>
  <button id="startButton">Start</button>
  <button id="callButton">Call</button>
  <button id="hangupButton">Hang Up</button>
</div>

एक वीडियो एलिमेंट, getUserMedia() से स्ट्रीम दिखाएगा. वहीं, दूसरा वीडियो एलिमेंट, RTCPeerconnection के ज़रिए स्ट्रीम किया गया वही वीडियो दिखाएगा. (असल दुनिया में इस्तेमाल किए जाने वाले ऐप्लिकेशन में, एक वीडियो एलिमेंट लोकल स्ट्रीम और दूसरा रिमोट स्ट्रीम दिखाएगा.)

adapter.js शिम जोड़ना

main.js के लिंक के ऊपर, adapter.js के मौजूदा वर्शन का लिंक जोड़ें:

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

Index.html अब ऐसा दिखना चाहिए:

<!DOCTYPE html>
<html>

<head>
  <title>Realtime communication with WebRTC</title>
  <link rel="stylesheet" href="css/main.css" />
</head>

<body>
  <h1>Realtime communication with WebRTC</h1>

  <video id="localVideo" autoplay playsinline></video>
  <video id="remoteVideo" autoplay playsinline></video>

  <div>
    <button id="startButton">Start</button>
    <button id="callButton">Call</button>
    <button id="hangupButton">Hang Up</button>
  </div>

  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>
</body>
</html>

RTCPeerConnection कोड इंस्टॉल करना

main.js को step-02 फ़ोल्डर में मौजूद वर्शन से बदलें.

कॉल करो

index.html खोलें. अपने वेबकैम से वीडियो पाने के लिए, शुरू करें बटन पर क्लिक करें. इसके बाद, पीयर कनेक्शन बनाने के लिए कॉल करें पर क्लिक करें. आपको दोनों वीडियो एलिमेंट में एक ही वीडियो (आपके वेबकैम से) दिखना चाहिए. WebRTC लॉगिंग देखने के लिए, ब्राउज़र कंसोल देखें.

यह कैसे काम करता है

इस चरण में कई काम किए जाते हैं...

WebRTC, RTCPeerConnection API का इस्तेमाल करके, WebRTC क्लाइंट के बीच वीडियो स्ट्रीम करने के लिए कनेक्शन सेट अप करता है. इन्हें पीयर कहा जाता है.

इस उदाहरण में, दो RTCPeerConnection ऑब्जेक्ट एक ही पेज पर हैं: pc1 और pc2. यह ज़्यादा काम का नहीं है, लेकिन इससे यह पता चलता है कि एपीआई कैसे काम करते हैं.

WebRTC पियर के बीच कॉल सेट अप करने के लिए, ये तीन टास्क पूरे करने होते हैं:

  • कॉल के हर एंड के लिए एक RTCPeerConnection बनाएं. साथ ही, हर एंड पर getUserMedia() से लोकल स्ट्रीम जोड़ें.
  • नेटवर्क की जानकारी पाना और शेयर करना: संभावित कनेक्शन एंडपॉइंट को ICE कैंडिडेट कहा जाता है.
  • स्थानीय और रिमोट मीडिया के बारे में जानकारी पाना और शेयर करना: एसडीपी फ़ॉर्मैट में स्थानीय मीडिया के बारे में मेटाडेटा.

मान लें कि ऐलिस और बॉब को वीडियो चैट सेट अप करने के लिए, RTCPeerConnection का इस्तेमाल करना है.

सबसे पहले, एलिस और बॉब नेटवर्क की जानकारी शेयर करते हैं. ‘कैंडिडेट ढूंढना’ का मतलब, ICE फ़्रेमवर्क का इस्तेमाल करके नेटवर्क इंटरफ़ेस और पोर्ट ढूंढने की प्रोसेस से है.

  1. ऐलिस, onicecandidate (addEventListener('icecandidate')) हैंडलर की मदद से एक RTCPeerConnection ऑब्जेक्ट बनाती है. यह main.js के इस कोड से मेल खाता है:
let localPeerConnection;
localPeerConnection = new RTCPeerConnection(servers);
localPeerConnection.addEventListener('icecandidate', handleConnection);
localPeerConnection.addEventListener(
    'iceconnectionstatechange', handleConnectionChange);
  1. ऐलिस, getUserMedia() को कॉल करती है और उसे स्ट्रीम पास करती है:
navigator.mediaDevices.getUserMedia(mediaStreamConstraints).
  then(gotLocalMediaStream).
  catch(handleLocalMediaStreamError);
function gotLocalMediaStream(mediaStream) {
  localVideo.srcObject = mediaStream;
  localStream = mediaStream;
  trace('Received local stream.');
  callButton.disabled = false;  // Enable call button.
}
localPeerConnection.addStream(localStream);
trace('Added local stream to localPeerConnection.');
  1. नेटवर्क के उम्मीदवार उपलब्ध होने पर, पहले चरण का onicecandidate हैंडलर कॉल किया जाता है.
  2. ऐलिस, बॉब को क्रम से लगाया गया उम्मीदवार का डेटा भेजती है. असल ऐप्लिकेशन में, यह प्रोसेस (जिसे सिग्नलिंग कहा जाता है) मैसेजिंग सेवा के ज़रिए होती है. इसके बारे में आपको बाद के चरण में पता चलेगा. इस चरण में, दोनों RTCPeerConnection ऑब्जेक्ट एक ही पेज पर होते हैं और सीधे तौर पर एक-दूसरे से कम्यूनिकेट कर सकते हैं. इसके लिए, बाहरी मैसेजिंग की ज़रूरत नहीं होती.
  3. जब बॉब को एलिस से उम्मीदवार का मैसेज मिलता है, तो वह addIceCandidate() को कॉल करता है, ताकि उम्मीदवार को रिमोट पीयर के ब्यौरे में जोड़ा जा सके:
function handleConnection(event) {
  const peerConnection = event.target;
  const iceCandidate = event.candidate;

  if (iceCandidate) {
    const newIceCandidate = new RTCIceCandidate(iceCandidate);
    const otherPeer = getOtherPeer(peerConnection);

    otherPeer.addIceCandidate(newIceCandidate)
      .then(() => {
        handleConnectionSuccess(peerConnection);
      }).catch((error) => {
        handleConnectionFailure(peerConnection, error);
      });

    trace(`${getPeerName(peerConnection)} ICE candidate:\n` +
          `${event.candidate.candidate}.`);
  }
}

WebRTC पियर को, लोकल और रिमोट ऑडियो और वीडियो मीडिया की जानकारी का पता लगाना और उसे शेयर करना होता है. जैसे, रिज़ॉल्यूशन और कोडेक की क्षमताएं. मीडिया कॉन्फ़िगरेशन की जानकारी को शेयर करने के लिए, मेटाडेटा के ब्लॉब शेयर किए जाते हैं. इन्हें ऑफ़र और जवाब कहा जाता है. इसके लिए, सेशन डिस्क्रिप्शन प्रोटोकॉल फ़ॉर्मैट का इस्तेमाल किया जाता है. इसे एसडीपी कहा जाता है:

  1. ऐलिस, RTCPeerConnection createOffer() तरीके का इस्तेमाल करती है. वापस किया गया प्रॉमिस, RTCSessionDescription देता है: ऐलिस के लोकल सेशन का ब्यौरा:
trace('localPeerConnection createOffer start.');
localPeerConnection.createOffer(offerOptions)
  .then(createdOffer).catch(setSessionDescriptionError);
  1. अगर ऐसा हो जाता है, तो एलिस setLocalDescription() का इस्तेमाल करके स्थानीय ब्यौरा सेट करती है. इसके बाद, वह इस सेशन का ब्यौरा, बॉब को उसके सिग्नलिंग चैनल के ज़रिए भेजती है.
  2. ऋतिक, मयंक से मिली जानकारी को setRemoteDescription() का इस्तेमाल करके रिमोट जानकारी के तौर पर सेट करता है.
  3. बॉब, RTCPeerConnection createAnswer() तरीके को चलाता है. इसमें वह एलिस से मिली रिमोट जानकारी को पास करता है, ताकि एक ऐसा लोकल सेशन जनरेट किया जा सके जो एलिस के सेशन के साथ काम कर सके. createAnswer() प्रॉमिस, RTCSessionDescription को पास करता है: राघव इसे लोकल डिस्क्रिप्शन के तौर पर सेट करता है और इसे मयंक को भेजता है.
  4. जब ऐलिस को बॉब के सेशन का ब्यौरा मिलता है, तो वह उसे setRemoteDescription() के साथ रिमोट ब्यौरे के तौर पर सेट करती है.
// Logs offer creation and sets peer connection session descriptions.
function createdOffer(description) {
  trace(`Offer from localPeerConnection:\n${description.sdp}`);

  trace('localPeerConnection setLocalDescription start.');
  localPeerConnection.setLocalDescription(description)
    .then(() => {
      setLocalDescriptionSuccess(localPeerConnection);
    }).catch(setSessionDescriptionError);

  trace('remotePeerConnection setRemoteDescription start.');
  remotePeerConnection.setRemoteDescription(description)
    .then(() => {
      setRemoteDescriptionSuccess(remotePeerConnection);
    }).catch(setSessionDescriptionError);

  trace('remotePeerConnection createAnswer start.');
  remotePeerConnection.createAnswer()
    .then(createdAnswer)
    .catch(setSessionDescriptionError);
}

// Logs answer to offer creation and sets peer connection session descriptions.
function createdAnswer(description) {
  trace(`Answer from remotePeerConnection:\n${description.sdp}.`);

  trace('remotePeerConnection setLocalDescription start.');
  remotePeerConnection.setLocalDescription(description)
    .then(() => {
      setLocalDescriptionSuccess(remotePeerConnection);
    }).catch(setSessionDescriptionError);

  trace('localPeerConnection setRemoteDescription start.');
  localPeerConnection.setRemoteDescription(description)
    .then(() => {
      setRemoteDescriptionSuccess(localPeerConnection);
    }).catch(setSessionDescriptionError);
}
  1. पिंग!

बोनस पॉइंट

  1. chrome://webrtc-internals पर जाएं. इससे WebRTC के आंकड़े और डीबग करने से जुड़ा डेटा मिलता है. (Chrome के यूआरएल की पूरी सूची chrome://about पर उपलब्ध है.)
  2. सीएसएस की मदद से पेज को स्टाइल करें:
  • वीडियो को अगल-बगल में रखें.
  • बटन की चौड़ाई एक जैसी रखें और टेक्स्ट को बड़ा करें.
  • पक्का करें कि लेआउट, फ़ोन या टैबलेट पर काम करता हो.
  1. Chrome DevTools कंसोल में, localStream, localPeerConnection, और remotePeerConnection देखें.
  2. कंसोल में, localPeerConnectionpc1.localDescription देखें. एसडीपी फ़ॉर्मैट कैसा दिखता है?

आपको क्या सीखने को मिला

इस चरण में, आपने इनके बारे में जाना:

  • WebRTC शिम, adapter.js की मदद से, ब्राउज़र के बीच के अंतर को कम करें.
  • वीडियो स्ट्रीम करने के लिए, RTCPeerConnection API का इस्तेमाल करें.
  • मीडिया कैप्चर और स्ट्रीमिंग को कंट्रोल करना.
  • WebRTC कॉल की सुविधा चालू करने के लिए, पीयर के बीच मीडिया और नेटवर्क की जानकारी शेयर करें.

इस चरण का पूरा वर्शन, step-2 फ़ोल्डर में है.

सलाह

  • इस चरण में सीखने के लिए बहुत कुछ है! RTCPeerConnection के बारे में ज़्यादा जानकारी देने वाले अन्य संसाधन ढूंढने के लिए, webrtc.org पर जाएं. इस पेज पर, JavaScript फ़्रेमवर्क के सुझाव दिए गए हैं. अगर आपको WebRTC का इस्तेमाल करना है, लेकिन एपीआई को मैनेज नहीं करना है, तो इन सुझावों को आज़माएं.
  • adapter.js GitHub रिपॉज़िटरी में जाकर, adapter.js शिम के बारे में ज़्यादा जानें.
  • क्या आपको दुनिया के सबसे बेहतरीन वीडियो चैट ऐप्लिकेशन की झलक देखनी है? WebRTC कॉल के लिए, WebRTC प्रोजेक्ट के कैननिकल ऐप्लिकेशन AppRTC को देखें: ऐप्लिकेशन, कोड. कॉल सेटअप होने में 500 मि॰से॰ से कम समय लगता है.

सबसे सही तरीका

  • अपने कोड को आने वाले समय के लिए तैयार करने के लिए, Promise पर आधारित नए एपीआई का इस्तेमाल करें. साथ ही, adapter.js का इस्तेमाल करके, उन ब्राउज़र के साथ काम करने की सुविधा चालू करें जिन पर ये एपीआई काम नहीं करते.

अगला

इस चरण में, WebRTC का इस्तेमाल करके पीयर के बीच वीडियो स्ट्रीम करने का तरीका बताया गया है. हालांकि, यह कोडलैब डेटा के बारे में भी है!

अगले चरण में, RTCDataChannel का इस्तेमाल करके किसी भी तरह का डेटा स्ट्रीम करने का तरीका जानें.

6. डेटा का आदान-प्रदान करने के लिए, RTCDataChannel का इस्तेमाल करना

आपको क्या सीखने को मिलेगा

  • WebRTC एंडपॉइंट (पीयर) के बीच डेटा का आदान-प्रदान कैसे किया जाता है.

इस चरण का पूरा वर्शन, step-03 फ़ोल्डर में है.

अपने एचटीएमएल कोड को अपडेट करना

इस चरण में, WebRTC डेटा चैनलों का इस्तेमाल करके, एक ही पेज पर मौजूद दो textarea एलिमेंट के बीच टेक्स्ट भेजा जाएगा. यह बहुत काम का नहीं है. हालांकि, इससे यह पता चलता है कि WebRTC का इस्तेमाल, डेटा शेयर करने के साथ-साथ वीडियो स्ट्रीम करने के लिए भी किया जा सकता है.

index.html से वीडियो और बटन एलिमेंट हटाएं. इसके बाद, उनकी जगह यह एचटीएमएल डालें:

<textarea id="dataChannelSend" disabled
    placeholder="Press Start, enter some text, then press Send."></textarea>
<textarea id="dataChannelReceive" disabled></textarea>

<div id="buttons">
  <button id="startButton">Start</button>
  <button id="sendButton">Send</button>
  <button id="closeButton">Stop</button>
</div>

एक टेक्स्ट एरिया में टेक्स्ट डाला जाएगा. वहीं, दूसरे टेक्स्ट एरिया में, पीयर के बीच स्ट्रीम किया गया टेक्स्ट दिखेगा.

index.html अब ऐसा दिखना चाहिए:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <textarea id="dataChannelSend" disabled
    placeholder="Press Start, enter some text, then press Send."></textarea>
  <textarea id="dataChannelReceive" disabled></textarea>

  <div id="buttons">
    <button id="startButton">Start</button>
    <button id="sendButton">Send</button>
    <button id="closeButton">Stop</button>
  </div>

  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>

</body>

</html>

JavaScript को अपडेट करना

main.js को step-03/js/main.js के कॉन्टेंट से बदलें.

साथी उपयोगकर्ताओं के बीच डेटा स्ट्रीम करने की सुविधा आज़माएं: index.html खोलें. इसके बाद, पीयर कनेक्शन सेट अप करने के लिए Start दबाएं. बाईं ओर मौजूद textarea में कुछ टेक्स्ट डालें. इसके बाद, WebRTC डेटा चैनलों का इस्तेमाल करके टेक्स्ट ट्रांसफ़र करने के लिए, Send पर क्लिक करें.

यह कैसे काम करता है

यह कोड, टेक्स्ट मैसेज भेजने की सुविधा चालू करने के लिए RTCPeerConnection और RTCDataChannel का इस्तेमाल करता है.

इस चरण में ज़्यादातर कोड, RTCPeerConnection के उदाहरण के जैसा ही है.

sendData() और createConnection() फ़ंक्शन में ज़्यादातर नया कोड है:

function createConnection() {
  dataChannelSend.placeholder = '';
  var servers = null;
  pcConstraint = null;
  dataConstraint = null;
  trace('Using SCTP based data channels');
  // For SCTP, reliable and ordered delivery is true by default.
  // Add localConnection to global scope to make it visible
  // from the browser console.
  window.localConnection = localConnection =
      new RTCPeerConnection(servers, pcConstraint);
  trace('Created local peer connection object localConnection');

  sendChannel = localConnection.createDataChannel('sendDataChannel',
      dataConstraint);
  trace('Created send data channel');

  localConnection.onicecandidate = iceCallback1;
  sendChannel.onopen = onSendChannelStateChange;
  sendChannel.onclose = onSendChannelStateChange;

  // Add remoteConnection to global scope to make it visible
  // from the browser console.
  window.remoteConnection = remoteConnection =
      new RTCPeerConnection(servers, pcConstraint);
  trace('Created remote peer connection object remoteConnection');

  remoteConnection.onicecandidate = iceCallback2;
  remoteConnection.ondatachannel = receiveChannelCallback;

  localConnection.createOffer().then(
    gotDescription1,
    onCreateSessionDescriptionError
  );
  startButton.disabled = true;
  closeButton.disabled = false;
}

function sendData() {
  var data = dataChannelSend.value;
  sendChannel.send(data);
  trace('Sent Data: ' + data);
}

RTCDataChannel का सिंटैक्स, जान-बूझकर WebSocket के जैसा रखा गया है. इसमें send() तरीका और message इवेंट शामिल है.

dataConstraint के इस्तेमाल पर ध्यान दें. डेटा चैनल को कॉन्फ़िगर करके, अलग-अलग तरह से डेटा शेयर किया जा सकता है. उदाहरण के लिए, परफ़ॉर्मेंस के बजाय भरोसेमंद डिलीवरी को प्राथमिकता देना. आपको विकल्पों के बारे में ज़्यादा जानकारी, Mozilla Developer Network पर मिल सकती है.

बोनस पॉइंट

  1. WebRTC डेटा चैनल इस्तेमाल करने वाले प्रोटोकॉल SCTP में, डेटा को भरोसेमंद तरीके से और क्रम से डिलीवर करने की सुविधा डिफ़ॉल्ट रूप से चालू होती है. RTCDataChannel को कब डेटा को भरोसेमंद तरीके से डिलीवर करने की ज़रूरत पड़ सकती है और कब परफ़ॉर्मेंस ज़्यादा ज़रूरी हो सकती है, भले ही इसका मतलब कुछ डेटा खोना हो?
  2. पेज लेआउट को बेहतर बनाने के लिए, सीएसएस का इस्तेमाल करें. साथ ही, "dataChannelReceive" टेक्स्ट एरिया में प्लेसहोल्डर एट्रिब्यूट जोड़ें.
  3. मोबाइल डिवाइस पर पेज की जांच करें.

आपको क्या सीखने को मिला

इस चरण में, आपने इनके बारे में जाना:

  • दो WebRTC पियर के बीच कनेक्शन बनाना.
  • पीयर के बीच टेक्स्ट डेटा का आदान-प्रदान करना.

इस चरण का पूरा वर्शन, step-03 फ़ोल्डर में है.

ज़्यादा जानें

अगला

आपने एक ही पेज पर मौजूद साथियों के बीच डेटा शेयर करने का तरीका जान लिया है. हालांकि, अलग-अलग मशीनों के बीच डेटा शेयर कैसे किया जाता है? मेटाडेटा मैसेज का आदान-प्रदान करने के लिए, आपको सबसे पहले एक सिग्नलिंग चैनल सेट अप करना होगा. अगले चरण में जानें कि ऐसा कैसे किया जाता है!

7. मैसेज एक्सचेंज करने के लिए, सिग्नलिंग सेवा सेट अप करना

आपको क्या सीखने को मिलेगा

इस चरण में, आपको इनके बारे में जानकारी मिलेगी:

  • package.json में बताई गई प्रोजेक्ट की डिपेंडेंसी इंस्टॉल करने के लिए, npm का इस्तेमाल करें
  • Node.js सर्वर चलाएं और स्टैटिक फ़ाइलें उपलब्ध कराने के लिए, node-static का इस्तेमाल करें.
  • Socket.IO का इस्तेमाल करके, Node.js पर मैसेज सेवा सेट अप करें.
  • इसका इस्तेमाल करके, ‘रूम' बनाए जा सकते हैं और मैसेज भेजे जा सकते हैं.

इस चरण का पूरा वर्शन, step-04 फ़ोल्डर में है.

कॉन्सेप्ट

WebRTC कॉल सेट अप करने और उसे चालू रखने के लिए, WebRTC क्लाइंट (पीयर) को मेटाडेटा का आदान-प्रदान करना होता है:

  • उम्मीदवार (नेटवर्क) की जानकारी.
  • मीडिया के बारे में जानकारी देने वाले मैसेज भेजें और जवाब दें. जैसे, रिज़ॉल्यूशन और कोडेक.

दूसरे शब्दों में कहें, तो ऑडियो, वीडियो या डेटा की पीयर-टू-पीयर स्ट्रीमिंग शुरू करने से पहले, मेटाडेटा का आदान-प्रदान करना ज़रूरी है. इस प्रोसेस को सिग्नलिंग कहा जाता है.

पिछले चरणों में, भेजने और पाने वाले के RTCPeerConnection ऑब्जेक्ट एक ही पेज पर होते हैं. इसलिए, ‘सिग्नलिंग' का मतलब सिर्फ़ ऑब्जेक्ट के बीच मेटाडेटा पास करना होता है.

असल दुनिया में, भेजने वाले और पाने वाले के RTCPeerConnections, अलग-अलग डिवाइसों पर वेब पेजों में चलते हैं. इसलिए, आपको उनके बीच मेटाडेटा को कम्यूनिकेट करने का तरीका चाहिए.

इसके लिए, सिग्नलिंग सर्वर का इस्तेमाल किया जाता है. यह एक ऐसा सर्वर होता है जो WebRTC क्लाइंट (पीयर) के बीच मैसेज भेज सकता है. असल मैसेज, सामान्य टेक्स्ट होते हैं: स्ट्रिंगिफ़ाइड JavaScript ऑब्जेक्ट.

ज़रूरी शर्तें: Node.js इंस्टॉल करना

इस कोडलैब के अगले चरणों (फ़ोल्डर step-04 से step-06 तक) को पूरा करने के लिए, आपको Node.js का इस्तेमाल करके लोकल होस्ट पर सर्वर चलाना होगा.

Node.js को इस लिंक से डाउनलोड और इंस्टॉल किया जा सकता है. इसके अलावा, इसे अपने पसंदीदा पैकेज मैनेजर से भी डाउनलोड और इंस्टॉल किया जा सकता है.

इंस्टॉल हो जाने के बाद, अगले चरणों (npm install चलाना) के लिए ज़रूरी डिपेंडेंसी इंपोर्ट की जा सकेंगी. साथ ही, कोडलैब को चलाने के लिए एक छोटा लोकलहोस्ट सर्वर (node index.js चलाना) भी चलाया जा सकेगा. इन कमांड के बारे में बाद में बताया जाएगा, जब इनकी ज़रूरत होगी.

ऐप्लिकेशन के बारे में जानकारी

WebRTC, क्लाइंट-साइड JavaScript API का इस्तेमाल करता है. हालांकि, असल दुनिया में इसका इस्तेमाल करने के लिए, सिग्नलिंग (मैसेजिंग) सर्वर के साथ-साथ STUN और TURN सर्वर की भी ज़रूरत होती है. ज़्यादा जानकारी के लिए यहां जाएं.

इस चरण में, आपको एक सामान्य Node.js सिग्नलिंग सर्वर बनाना होगा. इसके लिए, Socket.IO Node.js मॉड्यूल और मैसेज भेजने के लिए JavaScript लाइब्रेरी का इस्तेमाल करें. Node.js और Socket.IO का अनुभव होना फ़ायदेमंद होगा, लेकिन यह ज़रूरी नहीं है. मैसेजिंग कॉम्पोनेंट बहुत आसान हैं.

इस उदाहरण में, सर्वर (Node.js ऐप्लिकेशन) को index.js में लागू किया गया है. साथ ही, इस पर चलने वाले क्लाइंट (वेब ऐप्लिकेशन) को index.html में लागू किया गया है.

इस चरण में Node.js ऐप्लिकेशन के दो टास्क हैं.

सबसे पहले, यह मैसेज रिले के तौर पर काम करता है:

socket.on('message', function (message) {
  log('Got message: ', message);
  socket.broadcast.emit('message', message);
});

दूसरा, यह WebRTC वीडियो चैट ‘रूम' मैनेज करता है:

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

हमारे WebRTC ऐप्लिकेशन में, ज़्यादा से ज़्यादा दो लोगों को एक रूम शेयर करने की अनुमति होगी.

एचटीएमएल और JavaScript

index.html को इस तरह अपडेट करें:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <script src="/socket.io/socket.io.js"></script>
  <script src="js/main.js"></script>
  
</body>

</html>

इस चरण में, आपको पेज पर कुछ भी नहीं दिखेगा: सभी लॉगिंग, ब्राउज़र कंसोल में की जाती है. (Chrome में कंसोल देखने के लिए, Ctrl-Shift-J दबाएं. अगर Mac का इस्तेमाल किया जा रहा है, तो Command-Option-J दबाएं.)

js/main.js की जगह यह कोड डालें:

'use strict';

var isInitiator;

window.room = prompt("Enter room name:");

var socket = io.connect();

if (room !== "") {
  console.log('Message from client: Asking to join room ' + room);
  socket.emit('create or join', room);
}

socket.on('created', function(room, clientId) {
  isInitiator = true;
});

socket.on('full', function(room) {
  console.log('Message from client: Room ' + room + ' is full :^(');
});

socket.on('ipaddr', function(ipaddr) {
  console.log('Message from client: Server IP address is ' + ipaddr);
});

socket.on('joined', function(room, clientId) {
  isInitiator = false;
});

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

Node.js पर Socket.IO को चलाने के लिए सेट अप करना

एचटीएमएल फ़ाइल में, आपको Socket.IO फ़ाइल का इस्तेमाल करने का विकल्प दिख सकता है:

<script src="/socket.io/socket.io.js"></script>

अपनी work डायरेक्ट्री के टॉप लेवल पर, package.json नाम की फ़ाइल बनाएं. साथ ही, इसमें यह कॉन्टेंट शामिल करें:

{
  "name": "webrtc-codelab",
  "version": "0.0.1",
  "description": "WebRTC codelab",
  "dependencies": {
    "node-static": "^0.7.10",
    "socket.io": "^1.2.0"
  }
}

यह एक ऐप्लिकेशन मेनिफ़ेस्ट है. इससे Node Package Manager (npm) को पता चलता है कि किन प्रोजेक्ट डिपेंडेंसी को इंस्टॉल करना है.

/socket.io/socket.io.js जैसे ज़रूरी सॉफ़्टवेयर इंस्टॉल करने के लिए, कमांड लाइन टर्मिनल में जाकर अपनी work डायरेक्ट्री में यह कमांड चलाएं:

npm install

आपको एक इंस्टॉलेशन लॉग दिखेगा. यह कुछ इस तरह से खत्म होगा:

3ab06b7bcc7664b9.png

जैसा कि आप देख सकते हैं, npm ने package.json में तय की गई डिपेंडेंसी इंस्टॉल कर दी हैं.

अपनी work डायरेक्ट्री के टॉप लेवल पर, index.js नाम की नई फ़ाइल बनाएं. इसे js डायरेक्ट्री में न बनाएं. इसके बाद, यह कोड जोड़ें:

'use strict';

var os = require('os');
var nodeStatic = require('node-static');
var http = require('http');
var socketIO = require('socket.io');

var fileServer = new(nodeStatic.Server)();
var app = http.createServer(function(req, res) {
  fileServer.serve(req, res);
}).listen(8080);

var io = socketIO.listen(app);
io.sockets.on('connection', function(socket) {

  // convenience function to log server messages on the client
  function log() {
    var array = ['Message from server:'];
    array.push.apply(array, arguments);
    socket.emit('log', array);
  }

  socket.on('message', function(message) {
    log('Client said: ', message);
    // for a real app, would be room-only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', function(room) {
    log('Received request to create or join room ' + room);

    var clientsInRoom = io.sockets.adapter.rooms[room];
    var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;

    log('Room ' + room + ' now has ' + numClients + ' client(s)');

    if (numClients === 0) {
      socket.join(room);
      log('Client ID ' + socket.id + ' created room ' + room);
      socket.emit('created', room, socket.id);

    } else if (numClients === 1) {
      log('Client ID ' + socket.id + ' joined room ' + room);
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room, socket.id);
      io.sockets.in(room).emit('ready');
    } else { // max two clients
      socket.emit('full', room);
    }
  });

  socket.on('ipaddr', function() {
    var ifaces = os.networkInterfaces();
    for (var dev in ifaces) {
      ifaces[dev].forEach(function(details) {
        if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
          socket.emit('ipaddr', details.address);
        }
      });
    }
  });

});

कमांड लाइन टर्मिनल में, work डायरेक्ट्री में यह कमांड चलाएं:

node index.js

अपने ब्राउज़र में, localhost:8080 खोलें.

इस यूआरएल को हर बार खोलने पर, आपसे चैट रूम का नाम डालने के लिए कहा जाएगा. एक ही रूम में शामिल होने के लिए, हर बार एक ही नाम वाला रूम चुनें. जैसे, ‘foo'.

नया टैब पेज खोलें और localhost:8080 को फिर से खोलें. चैट रूम का वही नाम चुनें.

तीसरे टैब या विंडो में localhost:8080 खोलें. रूम का वही नाम फिर से चुनें.

हर टैब में कंसोल देखें: आपको ऊपर दिए गए JavaScript से लॉगिंग दिखनी चाहिए.

बोनस पॉइंट

  1. मैसेज भेजने के अन्य कौनसे तरीके इस्तेमाल किए जा सकते हैं? ‘प्योर' WebSocket का इस्तेमाल करते समय, आपको कौनसी समस्याएं आ सकती हैं?
  2. इस ऐप्लिकेशन को स्केल करने में कौनसी समस्याएं आ सकती हैं? क्या एक ही समय में हज़ारों या लाखों कमरों के अनुरोधों की जांच करने का कोई तरीका बनाया जा सकता है?
  3. यह ऐप्लिकेशन, चैट रूम का नाम पाने के लिए JavaScript प्रॉम्प्ट का इस्तेमाल करता है. यूआरएल से चैट रूम का नाम पाने का तरीका ढूंढें. उदाहरण के लिए, localhost:8080/foo से रूम का नाम foo मिलेगा.

आपको क्या सीखने को मिला

इस चरण में, आपने इनके बारे में जाना:

  • package.json में बताई गई प्रोजेक्ट डिपेंडेंसी इंस्टॉल करने के लिए, npm का इस्तेमाल करें
  • स्टैटिक फ़ाइलों को सर्वर पर भेजने के लिए, Node.js सर्वर चलाएं.
  • socket.io का इस्तेमाल करके, Node.js पर मैसेज भेजने की सेवा सेट अप करें.
  • इसका इस्तेमाल करके, ‘रूम' बनाए जा सकते हैं और मैसेज भेजे जा सकते हैं.

इस चरण का पूरा वर्शन, step-04 फ़ोल्डर में है.

ज़्यादा जानें

अगला

जानें कि दो उपयोगकर्ताओं को पीयर कनेक्शन बनाने की सुविधा देने के लिए, सिग्नलिंग का इस्तेमाल कैसे किया जाता है.

8. पीयर कनेक्शन और सिग्नलिंग को एक साथ इस्तेमाल करना

आपको क्या सीखने को मिलेगा

इस चरण में, आपको इनके बारे में जानकारी मिलेगी:

  • Node.js पर चलने वाले Socket.IO का इस्तेमाल करके, WebRTC सिग्नलिंग सेवा चलाएं
  • इस सेवा का इस्तेमाल, पीयर के बीच WebRTC मेटाडेटा को शेयर करने के लिए करें.

इस चरण का पूरा वर्शन, step-05 फ़ोल्डर में है.

एचटीएमएल और JavaScript को बदलना

index.html के कॉन्टेंट को इससे बदलें:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="/css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <div id="videos">
    <video id="localVideo" autoplay muted></video>
    <video id="remoteVideo" autoplay></video>
  </div>

  <script src="/socket.io/socket.io.js"></script>
  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>
  
</body>

</html>

js/main.js को step-05/js/main.js के कॉन्टेंट से बदलें.

Node.js सर्वर चलाना

अगर इस कोडलैब को अपनी वर्क डायरेक्ट्री से फ़ॉलो नहीं किया जा रहा है, तो आपको step-05 फ़ोल्डर या अपने मौजूदा वर्किंग फ़ोल्डर के लिए डिपेंडेंसी इंस्टॉल करनी पड़ सकती हैं. अपनी वर्किंग डायरेक्ट्री से यह कमांड चलाएं:

npm install

अगर इंस्टॉल करने के बाद आपका Node.js सर्वर नहीं चल रहा है, तो work डायरेक्ट्री में जाकर, नीचे दी गई कमांड को कॉल करके इसे शुरू करें:

node index.js

पक्का करें कि पिछले चरण में इस्तेमाल किए गए index.js के उस वर्शन का इस्तेमाल किया जा रहा हो जिसमें Socket.IO लागू किया गया है. Node और Socket IO के बारे में ज़्यादा जानने के लिए, "संदेशों का आदान-प्रदान करने के लिए, सिग्नलिंग सेवा सेट अप करना" सेक्शन देखें.

अपने ब्राउज़र में, localhost:8080 खोलें.

localhost:8080 को नए टैब या विंडो में फिर से खोलें. एक वीडियो एलिमेंट में getUserMedia()से लोकल स्ट्रीम दिखेगी. वहीं, दूसरे वीडियो एलिमेंट में RTCPeerconnection के ज़रिए स्ट्रीम किया गया ‘रिमोट' वीडियो दिखेगा.

ब्राउज़र कंसोल में लॉगिंग देखें.

बोनस पॉइंट

  1. यह ऐप्लिकेशन, सिर्फ़ एक-दूसरे से वीडियो चैट करने की सुविधा देता है. एक से ज़्यादा लोगों को एक ही वीडियो चैट रूम शेयर करने की सुविधा देने के लिए, डिज़ाइन में क्या बदलाव किया जा सकता है?
  2. इस उदाहरण में, रूम का नाम foo हार्ड कोड किया गया है. कमरे के अन्य नामों को चालू करने का सबसे सही तरीका क्या होगा?
  3. उपयोगकर्ता, रूम का नाम कैसे शेयर करेंगे? कमरे के नाम शेयर करने के लिए, कोई दूसरा तरीका आज़माएं.
  4. ऐप्लिकेशन में बदलाव कैसे किया जा सकता है

आपको क्या सीखने को मिला

इस चरण में, आपने इनके बारे में जाना:

  • Node.js पर चल रहे Socket.IO का इस्तेमाल करके, WebRTC सिग्नलिंग सेवा चलाएं.
  • इस सेवा का इस्तेमाल, पीयर के बीच WebRTC मेटाडेटा को शेयर करने के लिए करें.

इस चरण का पूरा वर्शन, step-05 फ़ोल्डर में है.

सलाह

  • WebRTC के आंकड़े और डीबग डेटा, chrome://webrtc-internals पर उपलब्ध हैं.
  • test.webrtc.org का इस्तेमाल, अपने लोकल एनवायरमेंट की जांच करने के लिए किया जा सकता है. साथ ही, इससे अपने कैमरे और माइक्रोफ़ोन की जांच भी की जा सकती है.
  • अगर आपको कैश मेमोरी से जुड़ी कोई समस्या आ रही है, तो यह तरीका आज़माएं:
  • ctrl को दबाकर रखें और फिर से लोड करें बटन पर क्लिक करके, हार्ड रीफ़्रेश करें
  • ब्राउज़र को रीस्टार्ट करना
  • कमांड लाइन से npm cache clean चलाएं.

अगला

फ़ोटो लेने, इमेज का डेटा पाने, और उसे रिमोट पीयर के बीच शेयर करने का तरीका जानें.

9. फ़ोटो खींचें और उसे डेटा चैनल के ज़रिए शेयर करें

आपको क्या सीखने को मिलेगा

इस चरण में, आपको इनके बारे में जानकारी मिलेगी:

  • फ़ोटो लें और कैनवस एलिमेंट का इस्तेमाल करके उससे डेटा पाएं.
  • किसी दूसरे व्यक्ति के साथ इमेज डेटा शेयर करना.

इस चरण का पूरा वर्शन, step-06 फ़ोल्डर में है.

यह कैसे काम करता है

आपने पहले RTCDataChannel का इस्तेमाल करके, टेक्स्ट मैसेज भेजने और पाने का तरीका सीखा था.

इस चरण से, पूरी फ़ाइलें शेयर की जा सकती हैं. इस उदाहरण में, getUserMedia() से कैप्चर की गई फ़ोटो शेयर की जा रही हैं.

इस चरण के मुख्य हिस्से यहां दिए गए हैं:

  1. डेटा चैनल सेट अप करें. ध्यान दें कि इस चरण में, आपको पीयर कनेक्शन में कोई मीडिया स्ट्रीम नहीं जोड़नी है.
  2. getUserMedia() की मदद से, उपयोगकर्ता के वेबकैम की वीडियो स्ट्रीम कैप्चर करें:
var video = document.getElementById('video');

function grabWebCamVideo() {
  console.log('Getting user media (video) ...');
  navigator.mediaDevices.getUserMedia({
    video: true
  })
  .then(gotStream)
  .catch(function(e) {
    alert('getUserMedia() error: ' + e.name);
  });
}
  1. जब उपयोगकर्ता स्नैप बटन पर क्लिक करता है, तो वीडियो स्ट्रीम से एक स्नैपशॉट (वीडियो फ़्रेम) लें और उसे canvas एलिमेंट में दिखाएं:
var photo = document.getElementById('photo');
var photoContext = photo.getContext('2d');

function snapPhoto() {
  photoContext.drawImage(video, 0, 0, photo.width, photo.height);
  show(photo, sendBtn);
}
  1. जब उपयोगकर्ता भेजें बटन पर क्लिक करता है, तो इमेज को बाइट में बदलें और उन्हें डेटा चैनल के ज़रिए भेजें:
function sendPhoto() {
  // Split data channel message in chunks of this byte length.
  var CHUNK_LEN = 64000;
  var img = photoContext.getImageData(0, 0, photoContextW, photoContextH),
    len = img.data.byteLength,
    n = len / CHUNK_LEN | 0;

  console.log('Sending a total of ' + len + ' byte(s)');
  dataChannel.send(len);

  // split the photo and send in chunks of about 64KB
  for (var i = 0; i < n; i++) {
    var start = i * CHUNK_LEN,
      end = (i + 1) * CHUNK_LEN;
    console.log(start + ' - ' + (end - 1));
    dataChannel.send(img.data.subarray(start, end));
  }

  // send the reminder, if any
  if (len % CHUNK_LEN) {
    console.log('last ' + len % CHUNK_LEN + ' byte(s)');
    dataChannel.send(img.data.subarray(n * CHUNK_LEN));
  }
}
  1. डेटा पाने वाला पक्ष, डेटा चैनल के मैसेज बाइट को वापस इमेज में बदलता है और उपयोगकर्ता को इमेज दिखाता है:
function receiveDataChromeFactory() {
  var buf, count;

  return function onmessage(event) {
    if (typeof event.data === 'string') {
      buf = window.buf = new Uint8ClampedArray(parseInt(event.data));
      count = 0;
      console.log('Expecting a total of ' + buf.byteLength + ' bytes');
      return;
    }

    var data = new Uint8ClampedArray(event.data);
    buf.set(data, count);

    count += data.byteLength;
    console.log('count: ' + count);

    if (count === buf.byteLength) {
      // we're done: all data chunks have been received
      console.log('Done. Rendering photo.');
      renderPhoto(buf);
    }
  };
}

function renderPhoto(data) {
  var canvas = document.createElement('canvas');
  canvas.width = photoContextW;
  canvas.height = photoContextH;
  canvas.classList.add('incomingPhoto');
  // trail is the element holding the incoming images
  trail.insertBefore(canvas, trail.firstChild);

  var context = canvas.getContext('2d');
  var img = context.createImageData(photoContextW, photoContextH);
  img.data.set(data);
  context.putImageData(img, 0, 0);
}

कोड प्राप्त करें

अपने work फ़ोल्डर के कॉन्टेंट को step-06 के कॉन्टेंट से बदलें. work फ़ोल्डर में मौजूद आपकी index.html फ़ाइल अब ऐसी दिखनी चाहिए**:**

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="/css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <h2>
    <span>Room URL: </span><span id="url">...</span>
  </h2>

  <div id="videoCanvas">
    <video id="camera" autoplay></video>
    <canvas id="photo"></canvas>
  </div>

  <div id="buttons">
    <button id="snap">Snap</button><span> then </span><button id="send">Send</button>
    <span> or </span>
    <button id="snapAndSend">Snap &amp; Send</button>
  </div>

  <div id="incoming">
    <h2>Incoming photos</h2>
    <div id="trail"></div>
  </div>

  <script src="/socket.io/socket.io.js"></script>
  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>

</body>

</html>

अगर आपने इस कोडलैब को अपनी वर्क डायरेक्ट्री से फ़ॉलो नहीं किया है, तो आपको step-06 फ़ोल्डर या अपने मौजूदा वर्किंग फ़ोल्डर के लिए डिपेंडेंसी इंस्टॉल करनी पड़ सकती हैं. इसके लिए, अपनी वर्किंग डायरेक्ट्री से यह कमांड चलाएं:

npm install

अगर इंस्टॉल करने के बाद आपका Node.js सर्वर नहीं चल रहा है, तो इसे शुरू करने के लिए, अपनी work डायरेक्ट्री से यह कमांड कॉल करें:

node index.js

पक्का करें कि Socket.IO को लागू करने वाले index.js के वर्शन का इस्तेमाल किया जा रहा हो. साथ ही, बदलाव करने पर अपने Node.js सर्वर को रीस्टार्ट करना न भूलें. Node और Socket IO के बारे में ज़्यादा जानने के लिए, "संदेशों का आदान-प्रदान करने के लिए, सिग्नलिंग सेवा सेट अप करना" सेक्शन देखें.

अगर ज़रूरी हो, तो अनुमति दें बटन पर क्लिक करके, ऐप्लिकेशन को वेबकैम इस्तेमाल करने की अनुमति दें.

ऐप्लिकेशन, एक रैंडम रूम आईडी बनाएगा और उसे यूआरएल में जोड़ देगा. पता बार में मौजूद यूआरएल को नए ब्राउज़र टैब या विंडो में खोलें.

स्नैप और भेजें बटन पर क्लिक करें. इसके बाद, पेज में सबसे नीचे मौजूद दूसरी टैब में, इनकमिंग एरिया देखें. यह ऐप्लिकेशन, फ़ोटो को एक टैब से दूसरे टैब में ट्रांसफ़र करता है.

आपको कुछ ऐसा दिखेगा:

911b40f36ba6ba8.png

बोनस पॉइंट

  1. किसी भी तरह की फ़ाइल को शेयर करने के लिए, कोड में कैसे बदलाव किया जा सकता है?

ज़्यादा जानें

  • MediaStream Image Capture API: यह फ़ोटो लेने और कैमरे कंट्रोल करने के लिए एक एपीआई है. यह जल्द ही आपके ब्राउज़र में उपलब्ध होगा!
  • ऑडियो और वीडियो रिकॉर्ड करने के लिए, MediaRecorder API: डेमो, दस्तावेज़.

आपको क्या सीखने को मिला

  • कैनवस एलिमेंट का इस्तेमाल करके, फ़ोटो लेने और उससे डेटा पाने का तरीका.
  • उस डेटा को किसी रिमोट उपयोगकर्ता के साथ कैसे शेयर करें.

इस चरण का पूरा वर्शन, step-06 फ़ोल्डर में है.

10. बधाई हो

आपने रीयलटाइम में वीडियो स्ट्रीम करने और डेटा ट्रांसफ़र करने के लिए एक ऐप्लिकेशन बनाया है!

आपको क्या सीखने को मिला

इस कोडलैब में, आपने ये सीखा:

  • अपने वेबकैम से वीडियो पाना.
  • RTCPeerConnection की मदद से वीडियो स्ट्रीम करें.
  • RTCDataChannel की मदद से डेटा स्ट्रीम करना.
  • मैसेज भेजने और पाने के लिए, सिग्नलिंग सेवा सेट अप करें.
  • पीयर कनेक्शन और सिग्नलिंग को एक साथ इस्तेमाल करें.
  • फ़ोटो लें और उसे डेटा चैनल के ज़रिए शेयर करें.

अगले चरण

  • AppRTC, WebRTC का एक स्टैंडर्ड चैट ऐप्लिकेशन है. इसके कोड और आर्किटेक्चर को देखें: app, code.
  • github.com/webrtc/samples पर जाकर, लाइव डेमो आज़माएं.

ज़्यादा जानें

  • WebRTC का इस्तेमाल शुरू करने के लिए, कई तरह के संसाधन webrtc.org पर उपलब्ध हैं.