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

1. परिचय

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

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

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

मैं WebRTC का उपयोग कहां कर सकता/सकती हूं?

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

सिग्नल की सुविधा क्या है?

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

STUN और टर्न क्या हैं?

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

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

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

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

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

आप इन चीज़ों के बारे में जानेंगे

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

आपको इनकी ज़रूरत होगी

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

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

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

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

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

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

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

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

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

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

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

6ddeb4aee53c0f0e.png

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

1d2b4aa977ab7e24.png

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

27fce4494f641883.png

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

Screen Shot 2016-02-18 को 11.48.14 AM.png पर

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

Options में नीचे दिखाए गए तरीके से index.html अपने-आप दिखाएं के बगल में मौजूद बॉक्स चुनें:

18-02-2016 को सुबह 11.56.30 बजे स्क्रीन शॉट लिया गया

इसके बाद, वेब सर्वर: शुरू किया गया लेबल वाले टॉगल को बाईं ओर और फिर वापस दाईं ओर स्लाइड करके, सर्वर को बंद करें और रीस्टार्ट करें.

18-02-2016 को 12.22.18 PM.png पर स्क्रीन शॉट लिया गया

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

18a705cb6FCC5181.png

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

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

आप इन चीज़ों के बारे में जानेंगे

इस चरण में आपको पता चलेगा कि कैसे:

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

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

HTML का एक डैश...

अपनी काम डायरेक्ट्री में, 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;
}

बोनस पॉइंट

  • getUserMedia() को पास किया गया localStream ऑब्जेक्ट, ग्लोबल स्कोप में है. इसलिए, ब्राउज़र कंसोल से इसकी जांच की जा सकती है: कंसोल खोलें, stream टाइप करें, और Return दबाएं. (Chrome में कंसोल देखने के लिए, Ctrl-Shift-J दबाएं या अगर आप Mac पर हैं, तो Command-Option-J दबाएं.)
  • localStream.getVideoTracks() से क्या नतीजे मिलते हैं?
  • localStream.getVideoTracks()[0].stop() को कॉल करने की कोशिश करें.
  • कंस्ट्रेंट ऑब्जेक्ट को देखें: इसे {audio: true, video: true} में बदलने पर क्या होता है?
  • वीडियो एलिमेंट का साइज़ क्या है? डिसप्ले साइज़ के बजाय JavaScript से वीडियो का नैचुरल साइज़ कैसे पता लगाया जा सकता है? जांच करने के लिए, Chrome Dev टूल का इस्तेमाल करें.
  • वीडियो एलिमेंट में सीएसएस फ़िल्टर जोड़कर देखें. उदाहरण के लिए:
video {
  filter: blur(4px) invert(1) opacity(0.5);
}
  • SVG फ़िल्टर जोड़कर देखें. उदाहरण के लिए:
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() से स्ट्रीम दिखाएगा. साथ ही, दूसरा एलिमेंट, RTCPeerकनेक्शन के ज़रिए स्ट्रीम किए गए वीडियो को दिखाएगा. (असल दुनिया के ऐप्लिकेशन में, एक वीडियो एलिमेंट लोकल स्ट्रीम दिखाएगा और दूसरा रिमोट स्ट्रीम.)

अडैप्टर.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 का इस्तेमाल करता है.

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

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

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

मान लें कि ऐलिस और बॉब, एक वीडियो चैट सेट अप करने के लिए, 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() तरीके का इस्तेमाल करती हैं. रिस्पॉन्स में दिख रहे प्रॉमिस से RTCसेशनDescription: ऐलिस के लोकल सेशन की जानकारी मिलती है:
trace('localPeerConnection createOffer start.');
localPeerConnection.createOffer(offerOptions)
  .then(createdOffer).catch(setSessionDescriptionError);
  1. कामयाब होने पर, ऐलिस setLocalDescription() का इस्तेमाल करके स्थानीय जानकारी सेट करती हैं. इसके बाद, वह अपने सिग्नल वाले चैनल के ज़रिए बॉब को सेशन का यह ब्यौरा भेजती हैं.
  2. बॉब ने setRemoteDescription() का इस्तेमाल करके, उस ब्यौरे को सेट किया जिसे ऐलिस ने रिमोट ब्यौरे के तौर पर भेजा था.
  3. बॉब, RTCPeerConnection createAnswer() तरीके का इस्तेमाल करता है. इस तरीके को वह ऐलिस से मिले रिमोट के तौर पर पास करता है. इससे ऐसा लोकल सेशन जनरेट किया जा सकता है जो उनके नेटवर्क के साथ काम कर सके. createAnswer() प्रॉमिस, RTCसेशनDescription में पास होता है: बॉब उसे लोकल ब्यौरे के तौर पर सेट करता है और उसे ऐलिस को भेजता है.
  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 Dev टूल कंसोल से, localStream, localPeerConnection, और remotePeerConnection को देखें.
  2. कंसोल में, localPeerConnectionpc1.localDescription को देखें. एसडीपी फ़ॉर्मैट कैसा दिखता है?

आपने क्या सीखा

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

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

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

सलाह

  • इस चरण में सीखने के लिए बहुत कुछ है! RTCPeerConnection के बारे में ज़्यादा जानकारी देने वाले अन्य संसाधनों के बारे में जानने के लिए, webrtc.org पर जाएं. इस पेज पर JavaScript फ़्रेमवर्क के सुझाव दिए गए हैं — अगर आपको WebRTC का इस्तेमाल करना है, लेकिन इसके साथ एपीआई का इस्तेमाल नहीं करना है.
  • अडैप्टर.js शिम के बारे में ज़्यादा जानने के लिए, adapter.js GitHub रेपो पर जाएं.
  • देखना चाहते हैं कि विश्व का सर्वश्रेष्ठ वीडियो चैट ऐप्लिकेशन कैसा दिखता है? 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 डेटा चैनलों का इस्तेमाल करके टेक्स्ट ट्रांसफ़र करने के लिए, भेजें पर क्लिक करें.

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

यह कोड, मैसेज भेजने और पाने की सुविधा चालू करने के लिए, 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. SCTP में, WebRTC डेटा चैनलों के ज़रिए इस्तेमाल किया जाने वाला प्रोटोकॉल, भरोसेमंद और ऑर्डर किए गए डेटा की डिलीवरी डिफ़ॉल्ट रूप से चालू होता है. RTCDataChannel को डेटा की भरोसेमंद डिलीवरी कब करनी चाहिए और कब परफ़ॉर्मेंस ज़्यादा अहम हो सकती है — भले ही, ऐसा करने पर कुछ डेटा का नुकसान हो?
  2. पेज लेआउट को बेहतर बनाने के लिए सीएसएस का इस्तेमाल करें और "dataChannelReceive" में प्लेसहोल्डर एट्रिब्यूट जोड़ें टेक्स्ट एरिया.
  3. मोबाइल डिवाइस पर पेज की जांच करें.

आपने क्या सीखा

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

  • दो WebRTC पीयर के बीच कनेक्शन बनाएं.
  • मिलते-जुलते ऐप्लिकेशन के बीच टेक्स्ट डेटा का लेन-देन करें.

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

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

अगला अवॉर्ड

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

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

आप इन चीज़ों के बारे में जानेंगे

इस चरण में आपको पता चलेगा कि कैसे:

  • package.json में बताई गई प्रोजेक्ट डिपेंडेंसी इंस्टॉल करने के लिए, npm का इस्तेमाल करें
  • Node.js सर्वर चलाएं और स्टैटिक फ़ाइलें दिखाने के लिए नोड-स्टैटिक इस्तेमाल करें.
  • 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 और टर्न सर्वर की भी ज़रूरत होती है. आपको ज़्यादा जानकारी यहां मिल सकती है.

इस चरण में, मैसेज सेवा के लिए Socket.IO Node.js मॉड्यूल और JavaScript लाइब्रेरी का इस्तेमाल करके, एक आसान Node.js सिग्नलिंग सर्वर बनाया जाएगा. 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>

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

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

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

डिपेंडेंसी (जैसे कि /socket.io/socket.io.js) इंस्टॉल करने के लिए, अपनी काम डायरेक्ट्री में कमांड-लाइन टर्मिनल से, यहां दिया गया कोड चलाएं:

npm install

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

3ab06b7bcc7664b9.png

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

अपनी वर्क डायरेक्ट्री के टॉप लेवल पर एक नई फ़ाइल 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 में बताई गई प्रोजेक्ट डिपेंडेंसी इंस्टॉल करने के लिए, एनपीएम का इस्तेमाल करें
  • सर्वर की स्टैटिक फ़ाइलों पर Node.js सर्वर चलाएं.
  • सॉकेट.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

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

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

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

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

बोनस पॉइंट

  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. जब उपयोगकर्ता Snap बटन पर क्लिक करता है, तब वीडियो स्ट्रीम से एक स्नैपशॉट (वीडियो फ़्रेम) मिलता है और उसे 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 के कॉन्टेंट से बदलें. काम में मौजूद आपकी 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 सर्वर नहीं चल रहा है, तो अपनी वर्क डायरेक्ट्री से नीचे दिए गए कमांड को कॉल करके इसे शुरू करें:

node index.js

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

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

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

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

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

911b40f36ba6ba8.png

बोनस पॉइंट

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

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

  • MediaStream का इमेज कैप्चर एपीआई: फ़ोटो खींचने और कैमरे कंट्रोल करने के लिए एक एपीआई — यह सुविधा जल्द ही आपके आस-पास मौजूद ब्राउज़र पर भी उपलब्ध होगी!
  • ऑडियो और वीडियो रिकॉर्ड करने के लिए MediaRecorder API: डेमो, दस्तावेज़.

आपने क्या सीखा

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

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

10. बधाई हो

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

आपने क्या सीखा

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

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

अगले चरण

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

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