ارتباط بلادرنگ با WebRTC

1. مقدمه

WebRTC یک پروژه منبع باز برای فعال کردن ارتباط بیدرنگ صدا، تصویر و داده در وب و برنامه های بومی است.

WebRTC چندین API جاوا اسکریپت دارد — برای دیدن دموها روی پیوندها کلیک کنید.

کجا می توانم از WebRTC استفاده کنم؟

در فایرفاکس، اپرا و کروم روی دسکتاپ و اندروید. WebRTC همچنین برای برنامه های بومی در iOS و Android در دسترس است.

سیگنالینگ چیست؟

WebRTC از RTCPeerConnection برای برقراری ارتباط جریان داده بین مرورگرها استفاده می کند، اما همچنین به مکانیزمی برای هماهنگ کردن ارتباطات و ارسال پیام های کنترلی نیاز دارد، فرآیندی که به عنوان سیگنالینگ شناخته می شود. روش ها و پروتکل های سیگنالینگ توسط WebRTC مشخص نشده اند. در این کد لبه از Socket.IO برای پیام‌رسانی استفاده خواهید کرد، اما جایگزین‌های زیادی وجود دارد.

STUN و TURN چیست؟

WebRTC طوری طراحی شده است که به صورت همتا به همتا کار می کند، بنابراین کاربران می توانند از مستقیم ترین مسیر ممکن متصل شوند. با این حال، WebRTC برای مقابله با شبکه های دنیای واقعی ساخته شده است: برنامه های کاربردی کلاینت باید از دروازه ها و فایروال های NAT عبور کنند، و شبکه های همتا به همتا در صورت عدم موفقیت اتصال مستقیم نیاز به بازگشت به عقب دارند. به عنوان بخشی از این فرآیند، APIهای WebRTC از سرورهای STUN برای دریافت آدرس IP رایانه شما استفاده می کنند و سرورها را به عنوان سرورهای رله در صورتی که ارتباط همتا به همتا از کار بیفتد، تبدیل می کنند. ( WebRTC در دنیای واقعی با جزئیات بیشتری توضیح می دهد.)

آیا WebRTC امن است؟

رمزگذاری برای همه مؤلفه‌های WebRTC اجباری است و APIهای جاوا اسکریپت آن فقط از منابع امن (HTTPS یا میزبان محلی) قابل استفاده است. مکانیسم های سیگنالینگ با استانداردهای WebRTC تعریف نشده اند، بنابراین این به شما بستگی دارد که از پروتکل های امن استفاده کنید.

2. بررسی اجمالی

برنامه ای بسازید تا با وب کم خود ویدیو بگیرید و عکس های فوری بگیرید و آنها را به صورت همتا از طریق WebRTC به اشتراک بگذارید. در طول مسیر، نحوه استفاده از WebRTC APIهای اصلی و راه اندازی یک سرور پیام رسانی با استفاده از Node.js را یاد خواهید گرفت.

چیزی که یاد خواهید گرفت

  • ویدیو را از وب کم خود دریافت کنید
  • پخش ویدئو با RTCPeerConnection
  • پخش جریانی داده ها با RTCDataChannel
  • یک سرویس سیگنالینگ برای تبادل پیام راه اندازی کنید
  • اتصال همتا و سیگنالینگ را ترکیب کنید
  • یک عکس بگیرید و آن را از طریق یک کانال داده به اشتراک بگذارید

آنچه شما نیاز دارید

  • Chrome 47 یا بالاتر
  • وب سرور برای Chrome ، یا از وب سرور دلخواه خود استفاده کنید.
  • کد نمونه
  • یک ویرایشگر متن
  • دانش اولیه HTML، CSS و جاوا اسکریپت

3. کد نمونه را دریافت کنید

کد را دانلود کنید

اگر با git آشنایی دارید، می توانید کد این کد لبه را از GitHub با شبیه سازی آن دانلود کنید:

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

همچنین، روی دکمه زیر کلیک کنید تا فایل زیپ کد را دانلود کنید:

فایل فشرده دانلود شده را باز کنید. با این کار یک پوشه پروژه ( تطبیقی-وب-رسانه ) که حاوی یک پوشه برای هر مرحله از این کد لبه است، به همراه تمام منابعی که نیاز دارید باز می شود.

شما تمام کارهای کدنویسی خود را در دایرکتوری به نام work انجام خواهید داد.

پوشه های step-nn حاوی یک نسخه تمام شده برای هر مرحله از این کد لبه هستند. آنها برای مرجع وجود دارد.

وب سرور را نصب و تأیید کنید

در حالی که شما آزاد هستید که از وب سرور خود استفاده کنید، این کد لبه برای کار با وب سرور کروم طراحی شده است. اگر هنوز آن برنامه را نصب نکرده‌اید، می‌توانید آن را از فروشگاه وب Chrome نصب کنید.

6ddeb4aee53c0f0e.png

پس از نصب وب سرور برای برنامه Chrome ، روی میانبر Chrome Apps از نوار نشانک‌ها، یک صفحه برگه جدید یا از راه‌انداز برنامه کلیک کنید:

1d2b4aa977ab7e24.png

روی نماد وب سرور کلیک کنید:

27fce4494f641883.png

در مرحله بعد، این گفتگو را مشاهده خواهید کرد که به شما امکان می دهد وب سرور محلی خود را پیکربندی کنید:

اسکرین شات 18/02/2016 در ساعت 11.48.14.png

روی دکمه CHOOSE FOLDER کلیک کنید و پوشه کاری را که ایجاد کردید انتخاب کنید. این به شما امکان می‌دهد کارهای در حال انجام خود را در Chrome از طریق URL مشخص شده در گفتگوی وب سرور در بخش URL(های) وب سرور مشاهده کنید.

در زیر گزینه ها ، کادر کنار نشان دادن خودکار index.html را علامت بزنید، همانطور که در زیر نشان داده شده است:

اسکرین شات 18/02/2016 در ساعت 11.56.30.png

سپس سرور را با لغزاندن کلید ضامن برچسب Web Server: STARTED به سمت چپ و سپس بازگشت به راست، متوقف کرده و مجددا راه اندازی کنید.

اسکرین شات 18/02/2016 در ساعت 12.22.18 بعد از ظهر.png

اکنون با کلیک بر روی نشانی اینترنتی وب سرور برجسته شده، از سایت کاری خود در مرورگر وب خود دیدن کنید. شما باید صفحه‌ای را ببینید که شبیه به work/index.html است:

18a705cb6ccc5181.png

بدیهی است که این برنامه هنوز کار جالبی انجام نمی دهد - تا کنون، این فقط یک اسکلت کوچک است که ما برای اطمینان از اینکه سرور وب شما به درستی کار می کند استفاده می کنیم. در مراحل بعدی ویژگی های عملکرد و چیدمان را اضافه خواهید کرد.

4. ویدئو را از وب کم خود پخش کنید

چیزی که یاد خواهید گرفت

در این مرحله خواهید فهمید که چگونه:

  • یک جریان ویدیویی از وب کم خود دریافت کنید.
  • پخش جریانی را دستکاری کنید.
  • از CSS و SVG برای دستکاری ویدیو استفاده کنید.

نسخه کامل این مرحله در پوشه step-01 قرار دارد.

یک خط HTML ...

یک عنصر video و یک عنصر 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 autoplay playsinline></video>

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

</body>

</html>

... و کمی جاوا اسکریپت

موارد زیر را به main.js در پوشه 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 ارسال شده به getUserMedia() در محدوده جهانی است، بنابراین می توانید آن را از کنسول مرورگر بررسی کنید: کنسول را باز کنید، stream را تایپ کنید و Return را فشار دهید. (برای مشاهده کنسول در Chrome، Ctrl-Shift-J یا Command-Option-J را فشار دهید، اگر از Mac استفاده می کنید.)
  • 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%);
 }

چیزی که یاد گرفتی

در این مرحله یاد گرفتید که چگونه:

  • ویدیو را از وب کم خود دریافت کنید.
  • محدودیت های رسانه را تنظیم کنید.
  • با عنصر ویدیو قاطی کنید.

نسخه کامل این مرحله در پوشه step-01 قرار دارد.

نکات

  • ویژگی autoplay در عنصر video را فراموش نکنید. بدون آن، شما فقط یک فریم را خواهید دید!
  • گزینه های بیشتری برای محدودیت های getUserMedia() وجود دارد. به نسخه ی نمایشی در webrtc.github.io/samples/src/content/peerconnection/constraints نگاهی بیندازید. همانطور که خواهید دید، نمونه های WebRTC جالب زیادی در آن سایت وجود دارد.

بهترین تمرین

  • مطمئن شوید که عنصر ویدیوی شما از محفظه خود سرریز نمی‌شود. ما width و max-width را برای تنظیم اندازه دلخواه و حداکثر اندازه برای ویدیو اضافه کرده‌ایم. مرورگر به طور خودکار ارتفاع را محاسبه می کند:
video {
  max-width: 100%;
  width: 320px;
}

بعدی

شما ویدیو دارید، اما چگونه آن را پخش می کنید؟ در مرحله بعد متوجه شوید!

5. ویدئو را با RTCPeerConnection پخش کنید

چیزی که یاد خواهید گرفت

در این مرحله خواهید فهمید که چگونه:

  • تفاوت های مرورگر را با WebRTC shim، adapter.js حذف کنید.
  • از RTCPeerConnection API برای پخش ویدیو استفاده کنید.
  • ضبط و پخش رسانه را کنترل کنید.

نسخه کامل این مرحله در پوشه step-2 قرار دارد.

RTCPeerConnection چیست؟

RTCPeerConnection یک API برای برقراری تماس‌های WebRTC برای پخش ویدیو و صدا و تبادل داده است.

این مثال یک ارتباط بین دو شی RTCPeerConnection (معروف به peer) در یک صفحه ایجاد می کند.

کاربرد عملی چندانی ندارد، اما برای درک نحوه عملکرد 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 shim را اضافه کنید

یک پیوند به نسخه فعلی adapter.js در بالای پیوند به main.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 را باز کنید، روی دکمه Start کلیک کنید تا ویدیو را از وب کم خود دریافت کنید و برای برقراری اتصال همتا روی Call کلیک کنید. شما باید همان ویدیو (از وب کم خود) را در هر دو عنصر ویدیو ببینید. برای مشاهده گزارش WebRTC، کنسول مرورگر را مشاهده کنید.

چگونه کار می کند

این مرحله کارهای زیادی انجام می دهد ...

WebRTC از RTCPeerConnection API برای راه‌اندازی اتصالی برای پخش جریانی ویدیو بین مشتریان WebRTC استفاده می‌کند که به عنوان همتا شناخته می‌شوند.

در این مثال، دو شیء RTCPeerConnection در یک صفحه قرار دارند: pc1 و pc2 . کاربرد عملی زیادی ندارد، اما برای نشان دادن نحوه عملکرد APIها خوب است.

برقراری تماس بین همتایان WebRTC شامل سه کار است:

  • برای هر انتهای تماس یک RTCPeerConnection ایجاد کنید و در هر پایان، جریان محلی را از getUserMedia() اضافه کنید.
  • اطلاعات شبکه را دریافت و به اشتراک بگذارید: نقاط پایانی اتصال بالقوه به عنوان نامزدهای ICE شناخته می شوند.
  • توضیحات محلی و راه دور را دریافت و به اشتراک بگذارید: ابرداده درباره رسانه های محلی در قالب SDP .

تصور کنید که آلیس و باب می خواهند از RTCPeerConnection برای راه اندازی یک چت تصویری استفاده کنند.

ابتدا آلیس و باب اطلاعات شبکه را تبادل می کنند. عبارت «پیدا کردن نامزدها» به فرآیند یافتن رابط‌ها و پورت‌های شبکه با استفاده از چارچوب ICE اشاره دارد.

  1. آلیس یک شی RTCPeerConnection با یک کنترل کننده onicecandidate (addEventListener('icecandidate')) ایجاد می کند. این مربوط به کد زیر از 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 از مرحله 1 زمانی فراخوانی می شود که نامزدهای شبکه در دسترس قرار گیرند.
  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. آلیس متد createOffer() RTCPeerConnection را اجرا می کند. وعده بازگشتی یک RTCSessionDescription را ارائه می دهد: شرح جلسه محلی Alice:
trace('localPeerConnection createOffer start.');
localPeerConnection.createOffer(offerOptions)
  .then(createdOffer).catch(setSessionDescriptionError);
  1. در صورت موفقیت آمیز بودن، Alice توضیحات محلی را با استفاده از setLocalDescription() تنظیم می کند و سپس این توضیحات جلسه را از طریق کانال سیگنالینگ آنها برای Bob ارسال می کند.
  2. باب توصیفی را که آلیس برای او فرستاده بود با استفاده از setRemoteDescription() به عنوان توضیحات راه دور تنظیم می کند.
  3. Bob متد RTCPeerConnection createAnswer() اجرا می‌کند و توضیحات راه دوری را که از آلیس دریافت کرده است، به آن می‌فرستد، بنابراین می‌توان یک جلسه محلی ایجاد کرد که با جلسه او سازگار باشد. وعده createAnswer() یک RTCSessionDescription را منتقل می کند: Bob آن را به عنوان توضیحات محلی تنظیم می کند و برای Alice می فرستد.
  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 و داده های اشکال زدایی را فراهم می کند. (لیست کامل URL های کروم در chrome://about است.)
  2. صفحه را با CSS استایل کنید:
  • ویدیوها را کنار هم قرار دهید.
  • دکمه ها را با عرض یکسان، با متن بزرگتر بسازید.
  • مطمئن شوید که چیدمان روی موبایل کار می کند.
  1. از کنسول Chrome Dev Tools، به localStream ، localPeerConnection و remotePeerConnection نگاه کنید.
  2. از کنسول، به localPeerConnectionpc1.localDescription نگاه کنید. فرمت SDP چگونه به نظر می رسد؟

چیزی که یاد گرفتی

در این مرحله یاد گرفتید که چگونه:

  • تفاوت های مرورگر را با WebRTC shim، adapter.js حذف کنید.
  • از RTCPeerConnection API برای پخش ویدیو استفاده کنید.
  • ضبط و پخش رسانه را کنترل کنید.
  • برای فعال کردن تماس WebRTC، اطلاعات رسانه و شبکه را بین همتایان به اشتراک بگذارید.

نسخه کامل این مرحله در پوشه step-2 قرار دارد.

نکات

  • در این مرحله چیزهای زیادی برای یادگیری وجود دارد! برای یافتن منابع دیگری که RTCPeerConnection را با جزئیات بیشتر توضیح می دهند، به webrtc.org نگاهی بیندازید. این صفحه شامل پیشنهادهایی برای چارچوب‌های جاوا اسکریپت است - اگر می‌خواهید از WebRTC استفاده کنید، اما نمی‌خواهید بین APIها بحث کنید.
  • در مورد adapter.js shim از مخزن adapter.js GitHub اطلاعات بیشتری کسب کنید.
  • آیا می خواهید ببینید بهترین برنامه چت تصویری جهان چگونه است؟ به AppRTC، برنامه متعارف پروژه WebRTC برای تماس‌های WebRTC نگاهی بیندازید: برنامه ، کد . زمان تنظیم تماس کمتر از 500 میلی ثانیه است.

بهترین تمرین

  • برای اثبات آتی کد خود، از APIهای مبتنی بر Promise جدید استفاده کنید و با استفاده از adapter.js سازگاری با مرورگرهایی را که از آنها پشتیبانی نمی‌کنند فعال کنید.

بعدی

این مرحله نحوه استفاده از WebRTC را برای پخش جریانی ویدیو بین همتایان نشان می‌دهد - اما این کد لبه درباره داده‌ها نیز هست!

در مرحله بعدی نحوه استریم داده های دلخواه با استفاده از RTCDataChannel را بیاموزید.

6. از RTCDataChannel برای تبادل داده استفاده کنید

چیزی که یاد خواهید گرفت

  • نحوه تبادل داده بین نقاط پایانی WebRTC (همتایان).

نسخه کامل این مرحله در پوشه step-03 قرار دارد.

HTML خود را به روز کنید

برای این مرحله، از کانال های داده WebRTC برای ارسال متن بین دو عنصر textarea در یک صفحه استفاده خواهید کرد. این خیلی مفید نیست، اما نشان می دهد که چگونه می توان از 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 را باز کنید، برای راه اندازی اتصال همتا، استارت را فشار دهید، متنی را در 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 ارتباط برقرار کنید.
  • تبادل داده های متنی بین همتایان

نسخه کامل این مرحله در پوشه step-03 قرار دارد.

بیشتر بدانید

بعدی

شما یاد گرفته اید که چگونه داده ها را بین همتایان در همان صفحه مبادله کنید، اما چگونه این کار را بین ماشین های مختلف انجام می دهید؟ ابتدا باید یک کانال سیگنالینگ برای تبادل پیام های ابرداده راه اندازی کنید. در مرحله بعدی نحوه کار را بیابید!

7. یک سرویس سیگنالینگ برای تبادل پیام راه اندازی کنید

چیزی که یاد خواهید گرفت

در این مرحله خواهید فهمید که چگونه:

  • از npm برای نصب وابستگی های پروژه همانطور که در package.json مشخص شده است استفاده کنید
  • یک سرور Node.js را اجرا کنید و از node-static برای ارائه فایل های استاتیک استفاده کنید.
  • با استفاده از Socket.IO یک سرویس پیام رسانی در Node.js راه اندازی کنید.
  • از آن برای ایجاد "اتاق" و تبادل پیام استفاده کنید.

نسخه کامل این مرحله در پوشه step-04 قرار دارد.

مفاهیم

برای راه اندازی و حفظ تماس WebRTC، مشتریان WebRTC (همتایان) باید ابرداده را مبادله کنند:

  • اطلاعات نامزد (شبکه).
  • پیام‌هایی را ارائه دهید و به آن‌ها پاسخ دهید که اطلاعاتی درباره رسانه‌ها، مانند وضوح و کدک‌ها ارائه می‌کنند.

به عبارت دیگر، قبل از انجام پخش همتا به همتای صدا، ویدئو یا داده، تبادل ابرداده مورد نیاز است. این فرآیند سیگنالینگ نامیده می شود.

در مراحل قبلی، اشیاء RTCPeerConnection فرستنده و گیرنده در یک صفحه قرار دارند، بنابراین «سیگنال‌سازی» صرفاً مربوط به ارسال ابرداده بین اشیا است.

در یک برنامه دنیای واقعی، RTCPeerConnections فرستنده و گیرنده در صفحات وب روی دستگاه های مختلف اجرا می شود و شما به راهی برای ارتباط متادیتا توسط آنها نیاز دارید.

برای این کار، از سرور سیگنالینگ استفاده می‌کنید: سروری که می‌تواند پیام‌ها را بین مشتریان WebRTC (همتایان) ارسال کند. پیام های واقعی متن ساده هستند: اشیاء جاوا اسکریپت رشته ای.

پیش نیاز: Node.js را نصب کنید

برای اجرای مراحل بعدی این کد لبه (پوشه‌های step-04 تا step-06 ) باید با استفاده از Node.js یک سرور روی لوکال هاست اجرا کنید.

می توانید Node.js را از این لینک یا از طریق مدیریت بسته دلخواه خود دانلود و نصب کنید.

پس از نصب، می‌توانید وابستگی‌های مورد نیاز برای مراحل بعدی را وارد کنید (اجرای npm install )، و همچنین یک سرور لوکال هاست کوچک برای اجرای codelab اجرا کنید (در حال اجرا 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 ما به حداکثر دو همتا اجازه می دهد تا یک اتاق را به اشتراک بگذارند.

HTML و جاوا اسکریپت

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 یا Command-Option-J را فشار دهید، اگر از Mac استفاده می کنید.)

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);
});

Socket.IO را برای اجرا در Node.js راه اندازی کنید

در فایل 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"
  }
}

این یک مانیفست برنامه است که به Node Package Manager ( 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);
        }
      });
    }
  });

});

از ترمینال خط فرمان، دستور زیر را در پوشه کاری اجرا کنید:

node index.js

از مرورگر خود، localhost:8080 را باز کنید.

هر بار که این URL را باز می کنید، از شما خواسته می شود نام اتاق را وارد کنید. برای پیوستن به همان اتاق، هر بار نام اتاق یکسانی مانند «فو» را انتخاب کنید.

یک صفحه برگه جدید باز کنید و localhost:8080 را دوباره باز کنید. همان نام اتاق را انتخاب کنید.

localhost:8080 را در برگه یا پنجره سوم باز کنید. دوباره همان نام اتاق را انتخاب کنید.

کنسول را در هر یک از تب‌ها بررسی کنید: باید ثبت‌نام را از جاوا اسکریپت بالا ببینید.

امتیازات جایزه

  1. چه مکانیسم های جایگزینی برای پیام رسانی ممکن است امکان پذیر باشد؟ با استفاده از WebSocket "خالص" با چه مشکلاتی ممکن است مواجه شوید؟
  2. چه مسائلی ممکن است در مقیاس این برنامه درگیر باشد؟ آیا می توانید روشی برای آزمایش هزاران یا میلیون ها درخواست اتاق همزمان ایجاد کنید؟
  3. این برنامه از یک درخواست جاوا اسکریپت برای دریافت نام اتاق استفاده می کند. راهی برای دریافت نام اتاق از URL پیدا کنید. برای مثال localhost:8080/foo نام اتاق را foo می‌دهد.

چیزی که یاد گرفتی

در این مرحله یاد گرفتید که چگونه:

  • از npm برای نصب وابستگی های پروژه همانطور که در package.json مشخص شده است استفاده کنید
  • سرور Node.js را روی فایل های استاتیک سرور اجرا کنید.
  • با استفاده از socket.io یک سرویس پیام رسانی در Node.js راه اندازی کنید.
  • از آن برای ایجاد "اتاق" و تبادل پیام استفاده کنید.

نسخه کامل این مرحله در پوشه step-04 قرار دارد.

بیشتر بدانید

بعدی

نحوه استفاده از سیگنالینگ را برای فعال کردن دو کاربر برای ایجاد یک اتصال همتا بیابید.

8. اتصال همتا و سیگنالینگ را ترکیب کنید

چیزی که یاد خواهید گرفت

در این مرحله خواهید فهمید که چگونه:

  • یک سرویس سیگنالینگ WebRTC را با استفاده از Socket.IO اجرا کنید که روی Node.js اجرا می شود
  • از آن سرویس برای تبادل ابرداده WebRTC بین همتایان استفاده کنید.

نسخه کامل این مرحله در پوشه step-05 قرار دارد.

HTML و جاوا اسکریپت را جایگزین کنید

محتوای 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 را پیاده سازی می کند، استفاده می کنید. برای اطلاعات بیشتر در مورد Node and Socket IO، بخش «تنظیم یک سرویس سیگنالینگ برای تبادل پیام» را مرور کنید.

از مرورگر خود، localhost:8080 را باز کنید.

localhost:8080 را دوباره در یک برگه یا پنجره جدید باز کنید. یکی از عناصر ویدیویی جریان محلی را از getUserMedia() نمایش می‌دهد و دیگری ویدیوی «راه‌دور» پخش‌شده از طریق RTCPeerconnection را نشان می‌دهد.

مشاهده ورود به سیستم در کنسول مرورگر.

امتیازات جایزه

  1. این برنامه فقط از چت تصویری یک به یک پشتیبانی می کند. چگونه می‌توانید طراحی را تغییر دهید تا بیش از یک نفر بتوانند یک اتاق چت ویدیویی را به اشتراک بگذارند؟
  2. در مثال نام اتاق foo سخت کدگذاری شده است. بهترین راه برای فعال کردن نام اتاق های دیگر چیست؟
  3. کاربران چگونه نام اتاق را به اشتراک می گذارند؟ سعی کنید جایگزینی برای به اشتراک گذاری نام اتاق بسازید.
  4. چگونه می توانید برنامه را تغییر دهید

چیزی که یاد گرفتی

در این مرحله یاد گرفتید که چگونه:

  • یک سرویس سیگنالینگ WebRTC را با استفاده از Socket.IO اجرا کنید که روی Node.js اجرا می شود.
  • از آن سرویس برای تبادل ابرداده WebRTC بین همتایان استفاده کنید.

نسخه کامل این مرحله در پوشه step-05 قرار دارد.

نکات

  • آمار WebRTC و داده‌های اشکال‌زدایی از chrome://webrtc-internals در دسترس هستند.
  • از test.webrtc.org می توان برای بررسی محیط محلی و تست دوربین و میکروفون خود استفاده کرد.
  • اگر مشکلات عجیبی در کش دارید، موارد زیر را امتحان کنید:
  • با نگه داشتن ctrl و کلیک روی دکمه Reload، یک رفرش سخت انجام دهید
  • مرورگر را مجددا راه اندازی کنید
  • 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);
}

کد را دریافت کنید

محتویات پوشه کاری خود را با محتویات مرحله 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 خود را مجددا راه‌اندازی کنید. برای اطلاعات بیشتر در مورد Node and Socket IO، بخش «تنظیم یک سرویس سیگنالینگ برای تبادل پیام» را مرور کنید.

در صورت لزوم، روی دکمه Allow کلیک کنید تا به برنامه اجازه دهید از وب کم شما استفاده کند.

برنامه یک شناسه اتاق تصادفی ایجاد می کند و آن شناسه را به URL اضافه می کند. URL را از نوار آدرس در یک برگه یا پنجره مرورگر جدید باز کنید.

روی دکمه Snap & Send کلیک کنید و سپس به قسمت Incoming در برگه دیگر در پایین صفحه نگاه کنید. این برنامه عکس ها را بین برگه ها منتقل می کند.

شما باید چیزی شبیه به این را ببینید:

911b40f36ba6ba8.png

امتیازات جایزه

  1. چگونه می توانید کد را تغییر دهید تا امکان اشتراک گذاری هر نوع فایلی وجود داشته باشد؟

بیشتر بدانید

چیزی که یاد گرفتی

  • چگونه با استفاده از عنصر canvas یک عکس بگیرید و از آن اطلاعات دریافت کنید.
  • نحوه تبادل آن داده ها با یک کاربر راه دور

نسخه کامل این مرحله در پوشه step-06 قرار دارد.

10. تبریک می گویم

شما یک برنامه برای انجام پخش بیدرنگ ویدیو و تبادل داده ساخته اید!

چیزی که یاد گرفتی

در این کد لبه یاد گرفتید که چگونه:

  • ویدیو را از وب کم خود دریافت کنید.
  • پخش ویدئو با RTCPeerConnection.
  • پخش جریانی داده ها با RTCDataChannel.
  • یک سرویس سیگنالینگ برای تبادل پیام راه اندازی کنید.
  • اتصال همتا و سیگنالینگ را ترکیب کنید.
  • عکس بگیرید و آن را از طریق یک کانال داده به اشتراک بگذارید.

مراحل بعدی

بیشتر بدانید

  • طیف وسیعی از منابع برای شروع با WebRTC از webrtc.org در دسترس است.