WebRTC এর সাথে রিয়েল টাইম যোগাযোগ

1. ভূমিকা

WebRTC হল একটি ওপেন সোর্স প্রকল্প যা ওয়েব এবং নেটিভ অ্যাপগুলিতে অডিও, ভিডিও এবং ডেটার রিয়েলটাইম যোগাযোগ সক্ষম করে।

WebRTC-তে বেশ কিছু JavaScript API আছে — ডেমো দেখতে লিঙ্কগুলিতে ক্লিক করুন।

  • getUserMedia() : অডিও এবং ভিডিও ক্যাপচার।
  • MediaRecorder : অডিও এবং ভিডিও রেকর্ড করুন।
  • RTCPeerConnection : ব্যবহারকারীদের মধ্যে অডিও এবং ভিডিও স্ট্রিম করুন।
  • RTCDataChannel : ব্যবহারকারীদের মধ্যে ডেটা স্ট্রিম করে।

আমি কোথায় WebRTC ব্যবহার করতে পারি?

ফায়ারফক্স, অপেরা এবং ডেস্কটপ এবং অ্যান্ড্রয়েডে ক্রোমে। ওয়েবআরটিসি আইওএস এবং অ্যান্ড্রয়েডের নেটিভ অ্যাপগুলির জন্যও উপলব্ধ।

সিগন্যালিং কি?

WebRTC ব্রাউজারগুলির মধ্যে স্ট্রিমিং ডেটা যোগাযোগের জন্য RTCPeerConnection ব্যবহার করে, তবে যোগাযোগের সমন্বয় সাধন এবং নিয়ন্ত্রণ বার্তা প্রেরণের জন্য একটি প্রক্রিয়ারও প্রয়োজন, যা সিগন্যালিং নামে পরিচিত। WebRTC দ্বারা সিগন্যালিং পদ্ধতি এবং প্রোটোকল নির্দিষ্ট করা হয় না। এই কোডল্যাবে আপনি বার্তা প্রেরণের জন্য Socket.IO ব্যবহার করবেন, তবে অনেক বিকল্প রয়েছে।

STUN এবং TURN কি?

WebRTC পিয়ার-টু-পিয়ারের মাধ্যমে কাজ করার জন্য ডিজাইন করা হয়েছে, যাতে ব্যবহারকারীরা যতটা সম্ভব সরাসরি রুট ব্যবহার করে সংযোগ করতে পারেন। তবে, WebRTC বাস্তব-বিশ্বের নেটওয়ার্কিং মোকাবেলা করার জন্য তৈরি করা হয়েছে: ক্লায়েন্ট অ্যাপ্লিকেশনগুলিকে NAT গেটওয়ে এবং ফায়ারওয়াল অতিক্রম করতে হয় এবং সরাসরি সংযোগ ব্যর্থ হলে পিয়ার-টু-পিয়ার নেটওয়ার্কিংকে ফলব্যাকের প্রয়োজন হয়। এই প্রক্রিয়ার অংশ হিসাবে, WebRTC API গুলি আপনার কম্পিউটারের IP ঠিকানা পেতে STUN সার্ভার ব্যবহার করে এবং পিয়ার-টু-পিয়ার যোগাযোগ ব্যর্থ হলে TURN সার্ভারগুলি রিলে সার্ভার হিসাবে কাজ করে। ( বাস্তব জগতে WebRTC আরও বিস্তারিতভাবে ব্যাখ্যা করে।)

WebRTC কি নিরাপদ?

সমস্ত WebRTC উপাদানের জন্য এনক্রিপশন বাধ্যতামূলক, এবং এর JavaScript API গুলি শুধুমাত্র নিরাপদ উৎস (HTTPS বা localhost) থেকে ব্যবহার করা যেতে পারে। সিগন্যালিং প্রক্রিয়াগুলি WebRTC মান দ্বারা সংজ্ঞায়িত করা হয় না, তাই নিরাপদ প্রোটোকল ব্যবহার নিশ্চিত করা আপনার উপর নির্ভর করে।

2. সংক্ষিপ্ত বিবরণ

আপনার ওয়েবক্যাম দিয়ে ভিডিও পেতে এবং স্ন্যাপশট নিতে এবং WebRTC এর মাধ্যমে পিয়ার-টু-পিয়ারে শেয়ার করার জন্য একটি অ্যাপ তৈরি করুন। পথে আপনি শিখবেন কিভাবে মূল WebRTC API গুলি ব্যবহার করতে হয় এবং Node.js ব্যবহার করে একটি মেসেজিং সার্ভার সেট আপ করতে হয়।

তুমি কি শিখবে

  • আপনার ওয়েবক্যাম থেকে ভিডিও পান
  • RTCPeerConnection দিয়ে ভিডিও স্ট্রিম করুন
  • RTCDataChannel দিয়ে ডেটা স্ট্রিম করুন
  • বার্তা আদান-প্রদানের জন্য একটি সিগন্যালিং পরিষেবা সেট আপ করুন
  • পিয়ার সংযোগ এবং সিগন্যালিং একত্রিত করুন
  • একটি ছবি তুলুন এবং একটি ডেটা চ্যানেলের মাধ্যমে শেয়ার করুন

তোমার যা লাগবে

  • Chrome 47 বা তার উপরে
  • ক্রোমের জন্য ওয়েব সার্ভার , অথবা আপনার পছন্দের ওয়েব সার্ভার ব্যবহার করুন।
  • নমুনা কোড
  • একটি টেক্সট এডিটর
  • HTML, CSS এবং JavaScript এর প্রাথমিক জ্ঞান

৩. নমুনা কোডটি পান

কোডটি ডাউনলোড করুন

আপনি যদি গিটের সাথে পরিচিত হন, তাহলে আপনি এই কোডল্যাবের কোডটি ক্লোন করে গিটহাব থেকে ডাউনলোড করতে পারেন:

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

অথবা, কোডের একটি .zip ফাইল ডাউনলোড করতে নিম্নলিখিত বোতামে ক্লিক করুন:

ডাউনলোড করা জিপ ফাইলটি খুলুন। এটি একটি প্রজেক্ট ফোল্ডার ( adaptive-web-media ) আনপ্যাক করবে যাতে এই কোডল্যাবের প্রতিটি ধাপের জন্য একটি করে ফোল্ডার থাকবে, সাথে আপনার প্রয়োজনীয় সমস্ত রিসোর্সও থাকবে।

তুমি তোমার সমস্ত কোডিং কাজ work নামক ডিরেক্টরিতে করবে।

step-nn ফোল্ডারগুলিতে এই কোডল্যাবের প্রতিটি ধাপের জন্য একটি সমাপ্ত সংস্করণ রয়েছে। সেগুলি রেফারেন্সের জন্য রয়েছে।

ওয়েব সার্ভার ইনস্টল এবং যাচাই করুন

আপনি নিজের ওয়েব সার্ভার ব্যবহার করতে পারবেন, তবে এই কোডল্যাবটি Chrome ওয়েব সার্ভারের সাথে ভালোভাবে কাজ করার জন্য ডিজাইন করা হয়েছে। যদি আপনার কাছে এখনও সেই অ্যাপটি ইনস্টল না থাকে, তাহলে আপনি Chrome ওয়েব স্টোর থেকে এটি ইনস্টল করতে পারেন।

6ddeb4aee53c0f0e.png সম্পর্কে

Chrome অ্যাপের জন্য ওয়েব সার্ভার ইনস্টল করার পরে, বুকমার্ক বার, একটি নতুন ট্যাব পৃষ্ঠা, অথবা অ্যাপ লঞ্চার থেকে Chrome অ্যাপস শর্টকাটে ক্লিক করুন:

1d2b4aa977ab7e24.png সম্পর্কে

ওয়েব সার্ভার আইকনে ক্লিক করুন:

27fce4494f641883.png সম্পর্কে

এরপর, আপনি এই ডায়ালগটি দেখতে পাবেন, যা আপনাকে আপনার স্থানীয় ওয়েব সার্ভার কনফিগার করতে দেয়:

স্ক্রিন শট ২০১৬-০২-১৮ সকাল ১১.৪৮.১৪.png

"ফোল্ডার নির্বাচন করুন" বোতামে ক্লিক করুন এবং আপনার তৈরি করা কাজের ফোল্ডারটি নির্বাচন করুন। এটি আপনাকে ওয়েব সার্ভার URL(গুলি) বিভাগে ওয়েব সার্ভার ডায়ালগে হাইলাইট করা URL এর মাধ্যমে Chrome-এ আপনার চলমান কাজ দেখতে সক্ষম করবে।

Options এর অধীনে, Automatically show index.html এর পাশের বাক্সটি চেক করুন, যেমনটি নিচে দেখানো হয়েছে:

স্ক্রিন শট ২০১৬-০২-১৮ সকাল ১১.৫৬.৩০ টায়.png

তারপর "Web Server: STARTED" লেবেলযুক্ত টগলটি বাম দিকে এবং তারপর ডানদিকে স্লাইড করে সার্ভারটি থামান এবং পুনরায় চালু করুন।

স্ক্রিন শট ২০১৬-০২-১৮ দুপুর ১২.২২.১৮.png

এবার আপনার ওয়েব ব্রাউজারে হাইলাইট করা ওয়েব সার্ভার URL-এ ক্লিক করে আপনার কাজের সাইটে যান। আপনি এইরকম একটি পৃষ্ঠা দেখতে পাবেন, যা work/index.html এর সাথে সম্পর্কিত:

18a705cb6ccc5181.png সম্পর্কে

স্পষ্টতই, এই অ্যাপটি এখনও আকর্ষণীয় কিছু করছে না — এখন পর্যন্ত, এটি কেবলমাত্র একটি ন্যূনতম কঙ্কাল যা আমরা আপনার ওয়েব সার্ভার সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করার জন্য ব্যবহার করছি। পরবর্তী ধাপগুলিতে আপনি কার্যকারিতা এবং লেআউট বৈশিষ্ট্যগুলি যুক্ত করবেন।

৪. আপনার ওয়েবক্যাম থেকে ভিডিও স্ট্রিম করুন

তুমি কি শিখবে

এই ধাপে আপনি শিখবেন কিভাবে:

  • আপনার ওয়েবক্যাম থেকে একটি ভিডিও স্ট্রিম পান।
  • স্ট্রিম প্লেব্যাক পরিচালনা করুন।
  • ভিডিও পরিচালনা করতে CSS এবং SVG ব্যবহার করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০১ ফোল্ডারে রয়েছে।

একটু 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>

...এবং এক চিমটি জাভাস্ক্রিপ্ট

আপনার 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} তে পরিবর্তন করেন তখন কী হয়?
  • ভিডিও এলিমেন্টের আকার কত? জাভাস্ক্রিপ্ট থেকে ভিডিওর স্বাভাবিক আকার কীভাবে বের করা যায়, ডিসপ্লে সাইজের বিপরীতে? Chrome Dev Tools ব্যবহার করে পরীক্ষা করুন।
  • ভিডিও এলিমেন্টে CSS ফিল্টার যোগ করার চেষ্টা করুন। উদাহরণস্বরূপ:
video {
  filter: blur(4px) invert(1) opacity(0.5);
}
  • SVG ফিল্টার যোগ করার চেষ্টা করুন। উদাহরণস্বরূপ:
video {
   filter: hue-rotate(180deg) saturate(200%);
 }

তুমি যা শিখেছো

এই ধাপে আপনি শিখেছেন কিভাবে:

  • আপনার ওয়েবক্যাম থেকে ভিডিও পান।
  • মিডিয়া সীমাবদ্ধতা সেট করুন।
  • ভিডিও এলিমেন্টের সাথে গোলমাল।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০১ ফোল্ডারে রয়েছে।

পরামর্শ

  • video এলিমেন্টের autoplay অ্যাট্রিবিউটটি ভুলবেন না। এটি ছাড়া, আপনি কেবল একটি ফ্রেম দেখতে পাবেন!
  • getUserMedia() সীমাবদ্ধতার জন্য আরও অনেক বিকল্প রয়েছে। webrtc.github.io/samples/src/content/peerconnection/constraints এ ডেমোটি দেখুন। আপনি দেখতে পাবেন, সেই সাইটে প্রচুর আকর্ষণীয় WebRTC নমুনা রয়েছে।

সর্বোত্তম অনুশীলন

  • আপনার ভিডিও এলিমেন্টটি যেন তার কন্টেইনারে বেশি ভরে না যায় তা নিশ্চিত করুন। ভিডিওর জন্য পছন্দসই আকার এবং সর্বোচ্চ আকার নির্ধারণ করতে আমরা width এবং max-width যোগ করেছি। ব্রাউজার স্বয়ংক্রিয়ভাবে উচ্চতা গণনা করবে:
video {
  max-width: 100%;
  width: 320px;
}

পরবর্তী

তোমার কাছে ভিডিও আছে, কিন্তু তুমি কীভাবে এটি স্ট্রিম করবে? পরবর্তী ধাপে জেনে নাও!

৫. RTCPeerConnection দিয়ে ভিডিও স্ট্রিম করুন

তুমি কি শিখবে

এই ধাপে আপনি শিখবেন কিভাবে:

  • WebRTC shim, adapter.js ব্যবহার করে ব্রাউজারের পার্থক্যগুলি দূর করুন।
  • ভিডিও স্ট্রিম করতে RTCPeerConnection API ব্যবহার করুন।
  • মিডিয়া ক্যাপচার এবং স্ট্রিমিং নিয়ন্ত্রণ করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-২ ফোল্ডারে রয়েছে।

RTCPeerConnection কি?

RTCPeerConnection হল ভিডিও এবং অডিও স্ট্রিম করার জন্য WebRTC কল করার এবং ডেটা বিনিময় করার জন্য একটি API।

এই উদাহরণটি একই পৃষ্ঠায় দুটি 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 কোডটি ইনস্টল করুন

step-02 ফোল্ডারে main.js এর পরিবর্তে version দিন।

ফোন করো।

index.html খুলুন, আপনার ওয়েবক্যাম থেকে ভিডিও পেতে স্টার্ট বোতামে ক্লিক করুন এবং পিয়ার সংযোগ তৈরি করতে কল করুন এ ক্লিক করুন। উভয় ভিডিও উপাদানেই আপনার একই ভিডিও (আপনার ওয়েবক্যাম থেকে) দেখতে হবে। WebRTC লগিং দেখতে ব্রাউজার কনসোলটি দেখুন।

কিভাবে এটা কাজ করে

এই ধাপটি অনেক কিছু করে...

WebRTC RTCPeerConnection API ব্যবহার করে WebRTC ক্লায়েন্টদের মধ্যে ভিডিও স্ট্রিম করার জন্য একটি সংযোগ স্থাপন করে, যা পিয়ার্স নামে পরিচিত।

এই উদাহরণে, দুটি RTCPeerConnection অবজেক্ট একই পৃষ্ঠায় রয়েছে: pc1 এবং pc2 । খুব বেশি ব্যবহারিক ব্যবহার নেই, তবে API গুলি কীভাবে কাজ করে তা প্রদর্শনের জন্য ভালো।

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-র সহযোগীদের স্থানীয় এবং দূরবর্তী অডিও এবং ভিডিও মিডিয়া তথ্য, যেমন রেজোলিউশন এবং কোডেক ক্ষমতা, খুঁজে বের করতে এবং বিনিময় করতে হবে। মিডিয়া কনফিগারেশন তথ্য বিনিময়ের জন্য সংকেত প্রদানের জন্য সেশন বর্ণনা প্রোটোকল ফর্ম্যাট, যা SDP নামে পরিচিত, ব্যবহার করে অফার এবং উত্তর নামে পরিচিত মেটাডেটার ব্লব বিনিময় করা হয়:

  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 URL গুলির একটি সম্পূর্ণ তালিকা chrome://about এ রয়েছে।)
  2. CSS ব্যবহার করে পৃষ্ঠাটি স্টাইল করুন:
  • ভিডিওগুলো পাশাপাশি রাখুন।
  • বোতামগুলো একই প্রস্থের করুন, বড় লেখা সহ।
  • লেআউটটি মোবাইলে কাজ করছে কিনা তা নিশ্চিত করুন।
  1. Chrome Dev Tools কনসোল থেকে, localStream , localPeerConnection এবং remotePeerConnection দেখুন।
  2. কনসোল থেকে, localPeerConnectionpc1.localDescription দেখুন। SDP ফর্ম্যাটটি কেমন দেখাচ্ছে?

তুমি যা শিখেছো

এই ধাপে আপনি শিখেছেন কিভাবে:

  • WebRTC shim, adapter.js ব্যবহার করে ব্রাউজারের পার্থক্যগুলি দূর করুন।
  • ভিডিও স্ট্রিম করতে RTCPeerConnection API ব্যবহার করুন।
  • মিডিয়া ক্যাপচার এবং স্ট্রিমিং নিয়ন্ত্রণ করুন।
  • WebRTC কল সক্ষম করতে সহকর্মীদের মধ্যে মিডিয়া এবং নেটওয়ার্ক তথ্য ভাগ করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-২ ফোল্ডারে রয়েছে।

পরামর্শ

  • এই ধাপে শেখার অনেক কিছু আছে! RTCPeerConnection সম্পর্কে আরও বিস্তারিতভাবে ব্যাখ্যা করে এমন অন্যান্য রিসোর্স খুঁজে পেতে, webrtc.org দেখুন। এই পৃষ্ঠায় জাভাস্ক্রিপ্ট ফ্রেমওয়ার্কের জন্য পরামর্শ রয়েছে — যদি আপনি WebRTC ব্যবহার করতে চান, কিন্তু API গুলি নিয়ে ঝামেলা করতে চান না।
  • adapter.js shim সম্পর্কে আরও জানুন adapter.js GitHub রেপো থেকে।
  • বিশ্বের সেরা ভিডিও চ্যাট অ্যাপটি দেখতে কেমন তা দেখতে চান? WebRTC প্রকল্পের WebRTC কলের জন্য ক্যানোনিকাল অ্যাপ, AppRTC দেখুন: app , code । কল সেটআপ সময় 500 ms এর কম।

সর্বোত্তম অনুশীলন

  • আপনার কোডকে ভবিষ্যতের জন্য সুরক্ষিত করতে, নতুন Promise-ভিত্তিক API গুলি ব্যবহার করুন এবং adapter.js ব্যবহার করে যে ব্রাউজারগুলি সমর্থন করে না তাদের সাথে সামঞ্জস্যতা সক্ষম করুন।

পরবর্তী

এই ধাপে দেখানো হয়েছে কিভাবে WebRTC ব্যবহার করে সমবয়সীদের মধ্যে ভিডিও স্ট্রিম করতে হয় — কিন্তু এই কোডল্যাবটিও ডেটা সম্পর্কে!

পরবর্তী ধাপে RTCDataChannel ব্যবহার করে কীভাবে নির্বিচারে ডেটা স্ট্রিম করতে হয় তা শিখুন।

৬. তথ্য আদান-প্রদানের জন্য RTCDataChannel ব্যবহার করুন

তুমি কি শিখবে

  • WebRTC এন্ডপয়েন্ট (পিয়ার) এর মধ্যে ডেটা কীভাবে বিনিময় করবেন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৩ ফোল্ডারে রয়েছে।

আপনার HTML আপডেট করুন

এই ধাপের জন্য, আপনি একই পৃষ্ঠায় দুটি textarea উপাদানের মধ্যে টেক্সট পাঠানোর জন্য WebRTC ডেটা চ্যানেল ব্যবহার করবেন। এটি খুব একটা কার্যকর নয়, তবে এটি দেখায় যে কীভাবে WebRTC ডেটা শেয়ার করার পাশাপাশি ভিডিও স্ট্রিমিং করতে ব্যবহার করা যেতে পারে।

index.html থেকে ভিডিও এবং বোতাম উপাদানগুলি সরান এবং নিম্নলিখিত 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>

আপনার জাভাস্ক্রিপ্ট আপডেট করুন

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. SCTP এর সাথে, WebRTC ডেটা চ্যানেল দ্বারা ব্যবহৃত প্রোটোকল, নির্ভরযোগ্য এবং সুশৃঙ্খল ডেটা ডেলিভারি ডিফল্টরূপে চালু থাকে। কখন RTCDataChannel-কে নির্ভরযোগ্য ডেটা ডেলিভারি প্রদানের প্রয়োজন হতে পারে এবং কখন কর্মক্ষমতা আরও গুরুত্বপূর্ণ হতে পারে — এমনকি যদি এর অর্থ কিছু ডেটা হারানো হয়?
  2. পৃষ্ঠার লেআউট উন্নত করতে CSS ব্যবহার করুন এবং "dataChannelReceive" টেক্সট এরিয়ায় একটি প্লেসহোল্ডার অ্যাট্রিবিউট যোগ করুন।
  3. একটি মোবাইল ডিভাইসে পৃষ্ঠাটি পরীক্ষা করুন।

তুমি যা শিখেছো

এই ধাপে আপনি শিখেছেন কিভাবে:

  • দুটি WebRTC পিয়ারের মধ্যে একটি সংযোগ স্থাপন করুন।
  • সমবয়সীদের মধ্যে টেক্সট ডেটা বিনিময় করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৩ ফোল্ডারে রয়েছে।

আরও জানুন

পরবর্তী

তুমি একই পৃষ্ঠায় থাকা সহকর্মীদের মধ্যে ডেটা আদান-প্রদান শিখেছো, কিন্তু বিভিন্ন মেশিনের মধ্যে এটা কিভাবে করবে? প্রথমে, মেটাডেটা বার্তা আদান-প্রদানের জন্য তোমাকে একটি সিগন্যালিং চ্যানেল সেট আপ করতে হবে। পরবর্তী ধাপে কীভাবে তা জেনে নাও!

৭. বার্তা আদান-প্রদানের জন্য একটি সিগন্যালিং পরিষেবা স্থাপন করুন

তুমি কি শিখবে

এই ধাপে, আপনি শিখবেন কিভাবে:

  • package.json- এ উল্লেখিত প্রকল্প নির্ভরতা ইনস্টল করতে npm ব্যবহার করুন।
  • একটি Node.js সার্ভার চালান এবং স্ট্যাটিক ফাইল পরিবেশন করতে node-static ব্যবহার করুন।
  • Socket.IO ব্যবহার করে Node.js-এ একটি মেসেজিং পরিষেবা সেট আপ করুন।
  • 'রুম' তৈরি করতে এবং বার্তা বিনিময় করতে এটি ব্যবহার করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৪ ফোল্ডারে রয়েছে।

ধারণা

একটি WebRTC কল সেট আপ এবং রক্ষণাবেক্ষণ করার জন্য, WebRTC ক্লায়েন্টদের (পিয়ারদের) মেটাডেটা বিনিময় করতে হবে:

  • প্রার্থী (নেটওয়ার্ক) তথ্য।
  • রেজোলিউশন এবং কোডেকের মতো মিডিয়া সম্পর্কে তথ্য প্রদানকারী বার্তাগুলি অফার করুন এবং উত্তর দিন

অন্য কথায়, অডিও, ভিডিও বা ডেটার পিয়ার-টু-পিয়ার স্ট্রিমিং করার আগে মেটাডেটার আদান-প্রদান প্রয়োজন। এই প্রক্রিয়াটিকে সিগন্যালিং বলা হয়।

পূর্ববর্তী ধাপগুলিতে, প্রেরক এবং প্রাপক RTCPeerConnection অবজেক্ট একই পৃষ্ঠায় থাকে, তাই 'সিগন্যালিং' কেবল অবজেক্টের মধ্যে মেটাডেটা প্রেরণের বিষয়।

বাস্তব জগতের অ্যাপ্লিকেশনে, প্রেরক এবং গ্রহণকারী RTCPeerConnections বিভিন্ন ডিভাইসের ওয়েব পৃষ্ঠাগুলিতে চলে এবং তাদের মেটাডেটা যোগাযোগের জন্য আপনার একটি উপায়ের প্রয়োজন হয়।

এর জন্য, আপনি একটি সিগন্যালিং সার্ভার ব্যবহার করেন: একটি সার্ভার যা WebRTC ক্লায়েন্টদের (পিয়ার) মধ্যে বার্তা প্রেরণ করতে পারে। প্রকৃত বার্তাগুলি হল প্লেইন টেক্সট: স্ট্রিংফাইড জাভাস্ক্রিপ্ট অবজেক্ট।

পূর্বশর্ত: Node.js ইনস্টল করুন

এই কোডল্যাবের পরবর্তী ধাপগুলি (ফোল্ডারগুলি ধাপ-০৪ থেকে ধাপ-০৬ ) চালানোর জন্য আপনাকে Node.js ব্যবহার করে লোকালহোস্টে একটি সার্ভার চালাতে হবে।

আপনি এই লিঙ্ক থেকে অথবা আপনার পছন্দের প্যাকেজ ম্যানেজারের মাধ্যমে Node.js ডাউনলোড এবং ইনস্টল করতে পারেন।

একবার ইনস্টল হয়ে গেলে, আপনি পরবর্তী ধাপগুলির জন্য প্রয়োজনীয় নির্ভরতাগুলি আমদানি করতে সক্ষম হবেন ( npm install চালানো), পাশাপাশি কোডল্যাব চালানোর জন্য একটি ছোট লোকালহোস্ট সার্ভার চালানো ( node index.js চালানো)। এই কমান্ডগুলি পরে নির্দেশিত হবে, যখন সেগুলি প্রয়োজন হবে।

অ্যাপ সম্পর্কে

WebRTC একটি ক্লায়েন্ট-সাইড জাভাস্ক্রিপ্ট API ব্যবহার করে, কিন্তু বাস্তব-বিশ্ব ব্যবহারের জন্য একটি সিগন্যালিং (মেসেজিং) সার্ভারের পাশাপাশি STUN এবং TURN সার্ভারেরও প্রয়োজন। আপনি এখানে আরও জানতে পারেন।

এই ধাপে আপনি Socket.IO Node.js মডিউল এবং মেসেজিংয়ের জন্য জাভাস্ক্রিপ্ট লাইব্রেরি ব্যবহার করে একটি সহজ 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 অ্যাপ্লিকেশনটি সর্বোচ্চ দুইজন সহকর্মীকে একটি রুম ভাগ করে নেওয়ার অনুমতি দেবে।

এইচটিএমএল এবং জাভাস্ক্রিপ্ট

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>

এই ধাপে আপনি পৃষ্ঠায় কিছুই দেখতে পাবেন না: সমস্ত লগিং ব্রাউজার কনসোলে সম্পন্ন হয়। (ক্রোমে কনসোলটি দেখতে, 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 সেট আপ করুন

HTML ফাইলে, আপনি হয়তো দেখেছেন যে আপনি একটি 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 এ সংজ্ঞায়িত নির্ভরতা ইনস্টল করেছে।

আপনার কাজের ডিরেক্টরির উপরের স্তরে ( js ডিরেক্টরিতে নয়) একটি নতুন ফাইল index.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);
        }
      });
    }
  });

});

কমান্ড লাইন টার্মিনাল থেকে, ওয়ার্ক ডিরেক্টরিতে নিম্নলিখিত কমান্ডটি চালান:

node index.js

আপনার ব্রাউজার থেকে, localhost:8080 খুলুন।

প্রতিবার এই URL টি খুললে, আপনাকে একটি রুমের নাম লিখতে বলা হবে। একই রুমে যোগদানের জন্য, প্রতিবার একই রুমের নাম নির্বাচন করুন, যেমন 'foo'।

একটি নতুন ট্যাব পৃষ্ঠা খুলুন, এবং আবার localhost:8080 খুলুন। একই রুমের নাম নির্বাচন করুন।

তৃতীয় ট্যাব বা উইন্ডোতে localhost:8080 খুলুন। আবার একই রুমের নাম নির্বাচন করুন।

প্রতিটি ট্যাবে কনসোলটি পরীক্ষা করুন: আপনি উপরের জাভাস্ক্রিপ্ট থেকে লগিং দেখতে পাবেন।

বোনাস পয়েন্ট

  1. বিকল্প বার্তা প্রেরণের কোন পদ্ধতিগুলি সম্ভব হতে পারে? 'বিশুদ্ধ' ওয়েবসকেট ব্যবহার করে আপনি কোন সমস্যার সম্মুখীন হতে পারেন?
  2. এই অ্যাপ্লিকেশনটি স্কেল করার ক্ষেত্রে কী কী সমস্যা হতে পারে? আপনি কি হাজার হাজার বা লক্ষ লক্ষ রুম অনুরোধ পরীক্ষা করার জন্য একটি পদ্ধতি তৈরি করতে পারেন?
  3. এই অ্যাপটি একটি জাভাস্ক্রিপ্ট প্রম্পট ব্যবহার করে একটি রুমের নাম বের করে। URL থেকে রুমের নাম বের করার একটি উপায় বের করুন। উদাহরণস্বরূপ, localhost:8080/foo রুমের নাম foo দেবে।

তুমি যা শিখেছো

এই ধাপে, আপনি শিখেছেন কিভাবে:

  • package.json-এ উল্লেখিত প্রকল্প নির্ভরতা ইনস্টল করতে npm ব্যবহার করুন।
  • স্ট্যাটিক ফাইল সার্ভারে একটি Node.js সার্ভার চালান।
  • socket.io ব্যবহার করে Node.js-এ একটি মেসেজিং পরিষেবা সেট আপ করুন।
  • 'রুম' তৈরি করতে এবং বার্তা বিনিময় করতে এটি ব্যবহার করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৪ ফোল্ডারে রয়েছে।

আরও জানুন

পরবর্তী

দুজন ব্যবহারকারীকে পিয়ার সংযোগ স্থাপনে সক্ষম করার জন্য সিগন্যালিং কীভাবে ব্যবহার করবেন তা জানুন।

৮. পিয়ার সংযোগ এবং সিগন্যালিং একত্রিত করুন

তুমি কি শিখবে

এই ধাপে আপনি শিখবেন কিভাবে:

  • Node.js-এ চলমান Socket.IO ব্যবহার করে একটি WebRTC সিগন্যালিং পরিষেবা চালান।
  • সমবয়সীদের মধ্যে WebRTC মেটাডেটা বিনিময় করতে সেই পরিষেবাটি ব্যবহার করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৫ ফোল্ডারে রয়েছে।

HTML এবং 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 সার্ভারটি চালু না থাকে, তাহলে ওয়ার্ক ডিরেক্টরিতে নিম্নলিখিত কমান্ডটি কল করে এটি শুরু করুন:

node index.js

নিশ্চিত করুন যে আপনি পূর্ববর্তী ধাপের index.js সংস্করণটি ব্যবহার করছেন যা Socket.IO প্রয়োগ করে। নোড এবং সকেট IO সম্পর্কে আরও তথ্যের জন্য, "বার্তা বিনিময়ের জন্য একটি সিগন্যালিং পরিষেবা সেট আপ করুন" বিভাগটি পর্যালোচনা করুন।

আপনার ব্রাউজার থেকে, localhost:8080 খুলুন।

নতুন ট্যাব বা উইন্ডোতে আবার localhost:8080 খুলুন। একটি ভিডিও উপাদান getUserMedia() থেকে স্থানীয় স্ট্রিম প্রদর্শন করবে এবং অন্যটি RTCPeerconnection এর মাধ্যমে স্ট্রিম করা 'রিমোট' ভিডিও প্রদর্শন করবে।

ব্রাউজার কনসোলে লগিং দেখুন।

বোনাস পয়েন্ট

  1. এই অ্যাপ্লিকেশনটি শুধুমাত্র এক-এক ভিডিও চ্যাট সমর্থন করে। একই ভিডিও চ্যাট রুমে একাধিক ব্যক্তিকে ভাগ করে নেওয়ার জন্য আপনি কীভাবে নকশা পরিবর্তন করতে পারেন?
  2. উদাহরণে রুমের নাম foo হার্ড কোডেড আছে। অন্যান্য রুমের নাম সক্রিয় করার সেরা উপায় কী হবে?
  3. ব্যবহারকারীরা কীভাবে রুমের নাম শেয়ার করবেন? রুমের নাম শেয়ার করার বিকল্প তৈরি করার চেষ্টা করুন।
  4. আপনি কিভাবে অ্যাপটি পরিবর্তন করতে পারেন?

তুমি যা শিখেছো

এই ধাপে আপনি শিখেছেন কিভাবে:

  • Node.js-এ চলমান Socket.IO ব্যবহার করে একটি WebRTC সিগন্যালিং পরিষেবা চালান।
  • সমবয়সীদের মধ্যে WebRTC মেটাডেটা বিনিময় করতে সেই পরিষেবাটি ব্যবহার করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৫ ফোল্ডারে রয়েছে।

পরামর্শ

  • WebRTC পরিসংখ্যান এবং ডিবাগ ডেটা chrome://webrtc-internals থেকে পাওয়া যায়।
  • test.webrtc.org আপনার স্থানীয় পরিবেশ পরীক্ষা করতে এবং আপনার ক্যামেরা এবং মাইক্রোফোন পরীক্ষা করতে ব্যবহার করা যেতে পারে।
  • ক্যাশিং নিয়ে যদি আপনার কোন অদ্ভুত সমস্যা হয়, তাহলে নিম্নলিখিতগুলি চেষ্টা করে দেখুন:
  • ctrl চেপে ধরে এবং Reload বোতামে ক্লিক করে একটি হার্ড রিফ্রেশ করুন।
  • ব্রাউজারটি পুনরায় চালু করুন
  • কমান্ড লাইন থেকে npm cache clean চালান।

পরবর্তী

কীভাবে ছবি তুলতে হয়, ছবির তথ্য পেতে হয় এবং দূরবর্তী সমবয়সীদের সাথে শেয়ার করতে হয় তা জানুন।

৯. একটি ছবি তুলুন এবং একটি ডেটা চ্যানেলের মাধ্যমে শেয়ার করুন

তুমি কি শিখবে

এই ধাপে আপনি শিখবেন কিভাবে:

  • ক্যানভাস এলিমেন্ট ব্যবহার করে একটি ছবি তুলুন এবং সেখান থেকে তথ্য সংগ্রহ করুন।
  • দূরবর্তী ব্যবহারকারীর সাথে ছবির ডেটা বিনিময় করুন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৬ ফোল্ডারে রয়েছে।

কিভাবে এটা কাজ করে

আগে আপনি 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. যখন ব্যবহারকারী Send বোতামে ক্লিক করেন, তখন ছবিটিকে বাইটে রূপান্তর করুন এবং একটি ডেটা চ্যানেলের মাধ্যমে পাঠান:
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);
}

কোডটি পান

আপনার কাজের ফোল্ডারের বিষয়বস্তু ধাপ-০৬ এর বিষয়বস্তু দিয়ে প্রতিস্থাপন করুন। কাজের ক্ষেত্রে আপনার 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 সার্ভারটি পুনরায় চালু করতে ভুলবেন না। Node এবং Socket IO সম্পর্কে আরও তথ্যের জন্য, "বার্তা বিনিময়ের জন্য একটি সিগন্যালিং পরিষেবা সেট আপ করুন" বিভাগটি পর্যালোচনা করুন।

প্রয়োজনে, অ্যাপটিকে আপনার ওয়েবক্যাম ব্যবহার করার অনুমতি দিতে Allow বাটনে ক্লিক করুন।

অ্যাপটি একটি র‍্যান্ডম রুম আইডি তৈরি করবে এবং সেই আইডিটি URL-এ যোগ করবে। একটি নতুন ব্রাউজার ট্যাব বা উইন্ডোতে ঠিকানা বার থেকে URLটি খুলুন।

"স্ন্যাপ অ্যান্ড সেন্ড " বোতামে ক্লিক করুন এবং তারপর পৃষ্ঠার নীচের অন্য ট্যাবে "ইনকামিং" অংশটি দেখুন। অ্যাপটি ট্যাবগুলির মধ্যে ছবি স্থানান্তর করে।

তোমার এরকম কিছু দেখা উচিত:

911b40f36ba6ba8.png সম্পর্কে

বোনাস পয়েন্ট

  1. যেকোনো ধরণের ফাইল শেয়ার করা সম্ভব করার জন্য আপনি কীভাবে কোড পরিবর্তন করতে পারেন?

আরও জানুন

তুমি যা শিখেছো

  • ক্যানভাস এলিমেন্ট ব্যবহার করে কীভাবে একটি ছবি তুলবেন এবং সেখান থেকে ডেটা পাবেন।
  • দূরবর্তী ব্যবহারকারীর সাথে সেই ডেটা কীভাবে বিনিময় করবেন।

এই ধাপের একটি সম্পূর্ণ সংস্করণ ধাপ-০৬ ফোল্ডারে রয়েছে।

১০. অভিনন্দন

তুমি রিয়েলটাইম ভিডিও স্ট্রিমিং এবং ডেটা আদান-প্রদানের জন্য একটি অ্যাপ তৈরি করেছ!

তুমি যা শিখেছো

এই কোডল্যাবে আপনি শিখেছেন কিভাবে:

  • আপনার ওয়েবক্যাম থেকে ভিডিও পান।
  • RTCPeerConnection দিয়ে ভিডিও স্ট্রিম করুন।
  • RTCDataChannel দিয়ে ডেটা স্ট্রিম করুন।
  • বার্তা আদান-প্রদানের জন্য একটি সিগন্যালিং পরিষেবা স্থাপন করুন।
  • পিয়ার সংযোগ এবং সিগন্যালিং একত্রিত করুন।
  • একটি ছবি তুলুন এবং একটি ডেটা চ্যানেলের মাধ্যমে শেয়ার করুন।

পরবর্তী পদক্ষেপ

আরও জানুন

  • WebRTC শুরু করার জন্য বিভিন্ন ধরণের রিসোর্স webrtc.org থেকে পাওয়া যাবে।