پخش یک برنامه وب را فعال کنید

۱. مرور کلی

لوگوی گوگل کست

این آزمایشگاه کد به شما آموزش می‌دهد که چگونه یک برنامه ویدیویی وب موجود را برای پخش محتوا در دستگاهی که از Google Cast پشتیبانی می‌کند، تغییر دهید.

گوگل کست چیست؟

گوگل کست به کاربران اجازه می‌دهد محتوا را از دستگاه تلفن همراه خود به تلویزیون منتقل کنند. سپس کاربران می‌توانند از دستگاه تلفن همراه خود به عنوان کنترل از راه دور برای پخش رسانه در تلویزیون استفاده کنند.

کیت توسعه نرم‌افزار (SDK) گوگل کست (Google Cast) به شما امکان می‌دهد برنامه خود را برای کنترل تلویزیون یا سیستم صوتی گسترش دهید. کیت توسعه نرم‌افزار کست (Cast SDK) به شما امکان می‌دهد اجزای رابط کاربری لازم را بر اساس چک‌لیست طراحی گوگل کست (Google Cast Design Checklist) اضافه کنید.

چک لیست طراحی گوگل کست (Google Cast) ارائه شده است تا تجربه کاربری کست (Cast) را در تمام پلتفرم‌های پشتیبانی‌شده ساده و قابل پیش‌بینی کند.

قرار است چه چیزی بسازیم؟

وقتی این آزمایشگاه کدنویسی را تکمیل کردید، یک برنامه ویدیوی وب کروم خواهید داشت که قادر است ویدیوها را به دستگاه Google Cast منتقل کند.

آنچه یاد خواهید گرفت

  • نحوه اضافه کردن SDK گوگل کست به یک برنامه ویدیویی نمونه.
  • نحوه اضافه کردن دکمه Cast برای انتخاب دستگاه Google Cast.
  • نحوه اتصال به دستگاه Cast و راه‌اندازی گیرنده رسانه.
  • نحوه ارسال ویدیو.
  • نحوه ادغام Cast Connect

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

  • جدیدترین مرورگر گوگل کروم .
  • سرویس میزبانی HTTPS مانند Firebase Hosting یا ngrok .
  • یک دستگاه گوگل کست مانند کروم کست یا تلویزیون اندروید که به اینترنت دسترسی داشته باشد.
  • تلویزیون یا مانیتوری که ورودی HDMI داشته باشد.
  • برای آزمایش ادغام Cast Connect، یک Chromecast با Google TV مورد نیاز است، اما برای بقیه Codelab اختیاری است. اگر Chromecast ندارید، می‌توانید از مرحله افزودن پشتیبانی Cast Connect که در انتهای این آموزش آمده است، صرف نظر کنید.

تجربه

  • شما باید دانش قبلی در زمینه توسعه وب داشته باشید.
  • همچنین به دانش قبلی در مورد تماشای تلویزیون نیاز خواهید داشت :)

چگونه از این آموزش استفاده خواهید کرد؟

فقط تا انتها بخوانید آن را بخوانید و تمرین‌ها را انجام دهید

تجربه خود را در ساخت برنامه‌های وب چگونه ارزیابی می‌کنید؟

تازه کار متوسط ماهر

تجربه خود را با تماشای تلویزیون چگونه ارزیابی می‌کنید؟

تازه کار متوسط ماهر

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

شما می‌توانید تمام کدهای نمونه را روی کامپیوتر خود دانلود کنید...

و فایل زیپ دانلود شده را از حالت فشرده خارج کنید.

۳. برنامه نمونه را اجرا کنید

لوگوی گوگل کروم

ابتدا، بیایید ببینیم برنامه نمونه تکمیل‌شده چگونه است. این برنامه یک پخش‌کننده ویدیوی ساده است. کاربر می‌تواند یک ویدیو را از یک لیست انتخاب کند و سپس آن را به‌صورت محلی روی دستگاه پخش کند یا آن را به یک دستگاه Google Cast منتقل کند.

برای اینکه بتوانید از فایل تکمیل‌شده استفاده کنید، باید آن را میزبانی کنید.

اگر سروری برای استفاده در دسترس ندارید، می‌توانید از Firebase Hosting یا ngrok استفاده کنید.

سرور را اجرا کنید

پس از تنظیم سرویس مورد نظر خود، به app-done بروید و سرور خود را شروع کنید.

در مرورگر خود، به آدرس https مربوط به نمونه‌ای که میزبانی کرده‌اید، مراجعه کنید.

  1. باید ببینید که برنامه‌ی ویدیو ظاهر می‌شود.
  2. روی دکمه‌ی Cast کلیک کنید و دستگاه Google Cast خود را انتخاب کنید.
  3. یک ویدیو را انتخاب کنید، روی دکمه پخش کلیک کنید.
  4. پخش ویدیو در دستگاه Google Cast شما شروع خواهد شد.

تصویر پخش ویدیو در دستگاه Cast

برای مکث ویدیو در گیرنده، روی دکمه مکث در عنصر ویدیو کلیک کنید. برای ادامه پخش مجدد ویدیو، روی دکمه پخش در عنصر ویدیو کلیک کنید.

برای متوقف کردن ارسال به دستگاه Google Cast، روی دکمه‌ی Cast کلیک کنید.

قبل از اینکه ادامه دهیم، سرور را متوقف کنید.

۴. پروژه شروع را آماده کنید

تصویر پخش ویدیو در دستگاه Cast

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

  • یک برنامه فرستنده روی دستگاه تلفن همراه یا لپ‌تاپ اجرا می‌شود،
  • یک برنامه گیرنده روی دستگاه Google Cast اجرا می‌شود.

اکنون آماده‌اید تا با استفاده از ویرایشگر متن مورد علاقه‌تان، پروژه‌ی اولیه را توسعه دهید:

  1. انتخاب کنید آیکون پوشه پوشه app-start از کد نمونه‌ای که دانلود کرده‌اید.
  2. برنامه را با استفاده از سرور خود اجرا کنید و رابط کاربری (UI) را بررسی کنید.

توجه داشته باشید، از آنجایی که شما در حال کار بر روی این آزمایشگاه کد هستید، بسته به سرویس، باید نمونه را روی سرور خود مجدداً میزبانی کنید.

طراحی اپلیکیشن

این برنامه لیستی از ویدیوها را از یک وب سرور راه دور دریافت می‌کند و لیستی را برای مرور در اختیار کاربر قرار می‌دهد. کاربران می‌توانند یک ویدیو را برای مشاهده جزئیات انتخاب کنند یا ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کنند.

این برنامه شامل یک نمای اصلی است که در index.html تعریف شده و کنترل‌کننده اصلی، CastVideos.js.

فهرست.html

این فایل html تقریباً تمام رابط کاربری (UI) برنامه وب را تعریف می‌کند.

چند بخش از نماها وجود دارد، ما div#main_video خود را داریم که شامل عنصر ویدئو است. مرتبط با div ویدئو، div#media_control داریم که تمام کنترل‌ها را برای عنصر ویدئو تعریف می‌کند. در زیر آن، media_info قرار دارد که جزئیات ویدئو را در نما نمایش می‌دهد. در نهایت، div carousel لیستی از ویدئوها را در یک div نمایش می‌دهد.

فایل index.html همچنین Cast SDK را بوت‌استرپ می‌کند و به تابع CastVideos دستور بارگذاری می‌دهد.

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

CastVideos.js

این اسکریپت تمام منطق برنامه وب Cast Videos را مدیریت می‌کند. لیست ویدیوها و ابرداده‌های مرتبط با آنها که در CastVideos.js تعریف شده‌اند، در شیء‌ای به نام mediaJSON قرار دارند.

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

CastPlayer کلاس اصلی است که کل برنامه را مدیریت می‌کند، پخش‌کننده را تنظیم می‌کند، رسانه را انتخاب می‌کند و رویدادها را برای پخش رسانه به PlayerHandler متصل می‌کند. CastPlayer.prototype.initializeCastPlayer متدی است که تمام قابلیت‌های Cast را تنظیم می‌کند. CastPlayer.prototype.switchPlayer وضعیت را بین پخش‌کننده‌های محلی و راه دور تغییر می‌دهد. CastPlayer.prototype.setupLocalPlayer و CastPlayer.prototype.setupRemotePlayer پخش‌کننده‌های محلی و راه دور را مقداردهی اولیه می‌کنند.

PlayerHandler کلاسی است که مسئول مدیریت پخش رسانه است. تعدادی متد دیگر نیز وجود دارند که مسئول جزئیات مدیریت رسانه و پخش هستند.

سوالات متداول

۵. اضافه کردن دکمه‌ی Cast

تصویر یک برنامه با قابلیت Cast

یک برنامه‌ی دارای قابلیت Cast، دکمه‌ی Cast را در عنصر ویدیو نمایش می‌دهد. کلیک بر روی دکمه‌ی Cast، فهرستی از دستگاه‌های Cast را نمایش می‌دهد که کاربر می‌تواند آن‌ها را انتخاب کند. اگر کاربر در حال پخش محتوا به صورت محلی در دستگاه فرستنده بوده باشد، انتخاب یک دستگاه Cast، پخش را در آن دستگاه Cast شروع یا از سر می‌گیرد. در هر زمانی در طول یک جلسه‌ی Cast، کاربر می‌تواند بر روی دکمه‌ی Cast کلیک کند و ارسال برنامه‌ی خود به دستگاه Cast را متوقف کند. کاربر باید بتواند در هر صفحه‌ای از برنامه‌ی شما، همانطور که در چک لیست طراحی Google Cast توضیح داده شده است، به دستگاه Cast متصل شود یا از آن جدا شود.

پیکربندی

پروژه‌ی شروع به همان وابستگی‌ها و تنظیماتی نیاز دارد که برای برنامه‌ی نمونه‌ی تکمیل‌شده انجام دادید، اما این بار محتویات app-start را میزبانی کنید.

در مرورگر خود، به آدرس https مربوط به نمونه‌ای که میزبانی کرده‌اید، مراجعه کنید.

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

مقداردهی اولیه

چارچوب Cast یک شیء سینگلتون سراسری به CastContext دارد که تمام فعالیت‌های چارچوب را هماهنگ می‌کند. این شیء باید در اوایل چرخه حیات برنامه مقداردهی اولیه شود، که معمولاً از یک فراخوانی برگشتی اختصاص داده شده به window['__onGCastApiAvailable'] فراخوانی می‌شود، که پس از بارگذاری Cast SDK فراخوانی می‌شود و برای استفاده در دسترس است. در این حالت، CastContext در CastPlayer.prototype.initializeCastPlayer فراخوانی می‌شود، که از فراخوانی برگشتی فوق‌الذکر فراخوانی می‌شود.

هنگام مقداردهی اولیه CastContext ، باید یک شیء JSON options ارائه شود. این کلاس شامل گزینه‌هایی است که بر رفتار چارچوب تأثیر می‌گذارند. مهم‌ترین آنها شناسه برنامه گیرنده است که برای فیلتر کردن لیست دستگاه‌های Cast موجود استفاده می‌شود تا فقط دستگاه‌هایی که قادر به اجرای برنامه مشخص شده هستند نشان داده شوند و برنامه گیرنده هنگام شروع جلسه Cast اجرا شود.

وقتی برنامه‌ی خود را که قابلیت Cast دارد توسعه می‌دهید، باید به عنوان توسعه‌دهنده‌ی Cast ثبت‌نام کنید و سپس یک شناسه‌ی برنامه برای برنامه‌ی خود دریافت کنید. برای این آزمایشگاه کد، ما از یک شناسه‌ی برنامه‌ی نمونه استفاده خواهیم کرد.

کد زیر را در انتهای بخش body به index.html اضافه کنید:

<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

کد زیر را به index.html اضافه کنید تا برنامه CastVideos و همچنین CastContext مقداردهی اولیه شوند:

<script src="CastVideos.js"></script>
<script type="text/javascript">
var castPlayer = new CastPlayer();
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    castPlayer.initializeCastPlayer();
  }
};
</script>

حالا، باید یک متد جدید در CastVideos.js اضافه کنیم که مربوط به متدی باشد که در index.html فراخوانی کردیم. بیایید یک متد جدید به نام initializeCastPlayer اضافه کنیم که گزینه‌های CastContext را تنظیم می‌کند و RemotePlayer و RemotePlayerControllers جدید را مقداردهی اولیه می‌کند:

/**
 * This method sets up the CastContext, and a few other members
 * that are necessary to play and control videos on a Cast
 * device.
 */
CastPlayer.prototype.initializeCastPlayer = function() {

    var options = {};

    // Set the receiver application ID to your own (created in
    // the Google Cast Developer Console), or optionally
    // use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
    options.receiverApplicationId = 'C0868879';

    // Auto join policy can be one of the following three:
    // ORIGIN_SCOPED - Auto connect from same appId and page origin
    // TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab
    // PAGE_SCOPED - No auto connect
    options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED;

    cast.framework.CastContext.getInstance().setOptions(options);

    this.remotePlayer = new cast.framework.RemotePlayer();
    this.remotePlayerController = new cast.framework.RemotePlayerController(this.remotePlayer);
    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
        this.switchPlayer.bind(this)
    );
};

در نهایت، باید متغیرهایی برای RemotePlayer و RemotePlayerController ایجاد کنیم:

var CastPlayer = function() {
  //...
  /* Cast player variables */
  /** @type {cast.framework.RemotePlayer} */
  this.remotePlayer = null;
  /** @type {cast.framework.RemotePlayerController} */
  this.remotePlayerController = null;
  //...
};

دکمه‌ی ارسال

حالا که CastContext مقداردهی اولیه شده است، باید دکمه Cast را اضافه کنیم تا کاربر بتواند دستگاه Cast را انتخاب کند. Cast SDK یک کامپوننت دکمه Cast به نام google-cast-launcher با شناسه " castbutton" ارائه می‌دهد. می‌توان آن را به عنصر ویدیوی برنامه با اضافه کردن یک button در بخش media_control اضافه کرد.

این همان چیزی است که عنصر دکمه به نظر می‌رسد:

<google-cast-launcher id="castbutton"></google-cast-launcher>

کد زیر را به index.html در بخش media_control اضافه کنید:

<div id="media_control">
  <div id="play"></div>
  <div id="pause"></div>
  <div id="progress_bg"></div>
  <div id="progress"></div>
  <div id="progress_indicator"></div>
  <div id="fullscreen_expand"></div>
  <div id="fullscreen_collapse"></div>
  <google-cast-launcher id="castbutton"></google-cast-launcher>
  <div id="audio_bg"></div>
  <div id="audio_bg_track"></div>
  <div id="audio_indicator"></div>
  <div id="audio_bg_level"></div>
  <div id="audio_on"></div>
  <div id="audio_off"></div>
  <div id="duration">00:00:00</div>
</div>

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

ما هنوز هیچ پشتیبانی برای پخش رسانه ارائه نکرده‌ایم، بنابراین هنوز نمی‌توانید ویدیوها را در دستگاه Cast پخش کنید. برای توقف پخش، روی دکمه Cast کلیک کنید.

۶. پخش محتوای ویدیویی

تصویر برنامه‌ی دارای قابلیت Cast با منوی انتخاب دستگاه Cast

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

رسانه‌های ریخته‌گری

در سطح بالا، اگر می‌خواهید یک رسانه را در دستگاه Cast پخش کنید، موارد زیر باید اتفاق بیفتد:

  1. یک شیء MediaInfo JSON از Cast SDK ایجاد کنید که یک آیتم رسانه‌ای را مدل‌سازی کند.
  2. کاربر برای اجرای برنامه گیرنده شما به دستگاه Cast متصل می‌شود.
  3. شیء MediaInfo را در گیرنده خود بارگذاری کنید و محتوا را پخش کنید.
  4. وضعیت رسانه را پیگیری کنید.
  5. ارسال دستورات پخش به گیرنده بر اساس تعاملات کاربر.

مرحله ۱ به نگاشت یک شیء به شیء دیگر مربوط می‌شود؛ MediaInfo چیزی است که Cast SDK آن را درک می‌کند و mediaJSON کپسوله‌سازی برنامه ما برای یک آیتم رسانه‌ای است؛ می‌توانیم به راحتی یک mediaJSON به MediaInfo نگاشت کنیم. ما قبلاً مرحله ۲ را در بخش قبلی انجام داده‌ایم. انجام مرحله ۳ با Cast SDK آسان است.

برنامه نمونه CastPlayer از قبل بین پخش محلی و پخش از راه دور در متد switchPlayer تمایز قائل می‌شود:

if (cast && cast.framework) {
  if (this.remotePlayer.isConnected) {
    //...

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

در حال حاضر، پخش‌کننده محلی همیشه در حالت پخش محلی است، زیرا هنوز چیزی در مورد حالت‌های Casting نمی‌داند. ما باید رابط کاربری را بر اساس انتقال حالت‌هایی که در چارچوب Cast اتفاق می‌افتد، به‌روزرسانی کنیم. برای مثال، اگر شروع به Cast کردن کنیم، باید پخش محلی را متوقف کنیم و برخی از کنترل‌ها را غیرفعال کنیم. به طور مشابه، اگر Cast کردن را در حالی که در این کنترلر نما هستیم متوقف کنیم، باید به پخش محلی منتقل شویم. برای مدیریت این موضوع، باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.

مدیریت جلسه بازیگران

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

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

جلسات Cast توسط CastSession مدیریت می‌شوند که از طریق cast.framework.CastContext.getInstance().getCurrentSession() قابل دسترسی است. فراخوانی‌های EventListener می‌توانند برای نظارت بر رویدادهای جلسه، مانند ایجاد، تعلیق، از سرگیری و خاتمه، استفاده شوند.

در برنامه فعلی ما، تمام مدیریت session و state در متد setupRemotePlayer برای ما انجام می‌شود. بیایید با اضافه کردن کد زیر به CastVideos.js ، پیکربندی آن را در برنامه خود شروع کنیم:

/**
 * Set the PlayerHandler target to use the remote player
 */
CastPlayer.prototype.setupRemotePlayer = function () {
    var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

    this.playerHandler.setTarget(playerTarget);

    // Setup remote player volume right on setup
    // The remote player may have had a volume set from previous playback
    if (this.remotePlayer.isMuted) {
        this.playerHandler.mute();
    }
    var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
    var p = document.getElementById('audio_bg_level');
    p.style.height = currentVolume + 'px';
    p.style.marginTop = -currentVolume + 'px';

    this.hideFullscreenButton();

    this.playerHandler.play();
};

ما هنوز باید تمام رویدادهای مربوط به فراخوانی‌های برگشتی را مقید کنیم و تمام رویدادهایی را که وارد می‌شوند، مدیریت کنیم. این کار نسبتاً ساده‌ای است، پس بیایید اکنون به آن بپردازیم:

/**
 * Set the PlayerHandler target to use the remote player
 */
CastPlayer.prototype.setupRemotePlayer = function () {
    var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

    // Add event listeners for player changes which may occur outside sender app
    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
        function() {
            if (this.remotePlayer.isPaused) {
                this.playerHandler.pause();
            } else {
                this.playerHandler.play();
            }
        }.bind(this)
    );

    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,
        function() {
            if (this.remotePlayer.isMuted) {
                this.playerHandler.mute();
            } else {
                this.playerHandler.unMute();
            }
        }.bind(this)
    );

    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.VOLUME_LEVEL_CHANGED,
        function() {
            var newVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
            var p = document.getElementById('audio_bg_level');
            p.style.height = newVolume + 'px';
            p.style.marginTop = -newVolume + 'px';
        }.bind(this)
    );

    // This object will implement PlayerHandler callbacks with
    // remotePlayerController, and makes necessary UI updates specific
    // to remote playback
    var playerTarget = {};

    playerTarget.play = function () {
        if (this.remotePlayer.isPaused) {
            this.remotePlayerController.playOrPause();
        }

        var vi = document.getElementById('video_image');
        vi.style.display = 'block';
        var localPlayer = document.getElementById('video_element');
        localPlayer.style.display = 'none';
    }.bind(this);

    playerTarget.pause = function () {
        if (!this.remotePlayer.isPaused) {
            this.remotePlayerController.playOrPause();
        }
    }.bind(this);

    playerTarget.stop = function () {
         this.remotePlayerController.stop();
    }.bind(this);

    playerTarget.getCurrentMediaTime = function() {
        return this.remotePlayer.currentTime;
    }.bind(this);

    playerTarget.getMediaDuration = function() {
        return this.remotePlayer.duration;
    }.bind(this);

    playerTarget.updateDisplayMessage = function () {
        document.getElementById('playerstate').style.display = 'block';
        document.getElementById('playerstatebg').style.display = 'block';
        document.getElementById('video_image_overlay').style.display = 'block';
        document.getElementById('playerstate').innerHTML =
            this.mediaContents[ this.currentMediaIndex]['title'] + ' ' +
            this.playerState + ' on ' + castSession.getCastDevice().friendlyName;
    }.bind(this);

    playerTarget.setVolume = function (volumeSliderPosition) {
        // Add resistance to avoid loud volume
        var currentVolume = this.remotePlayer.volumeLevel;
        var p = document.getElementById('audio_bg_level');
        if (volumeSliderPosition < FULL_VOLUME_HEIGHT) {
            var vScale =  this.currentVolume * FULL_VOLUME_HEIGHT;
            if (volumeSliderPosition > vScale) {
                volumeSliderPosition = vScale + (pos - vScale) / 2;
            }
            p.style.height = volumeSliderPosition + 'px';
            p.style.marginTop = -volumeSliderPosition + 'px';
            currentVolume = volumeSliderPosition / FULL_VOLUME_HEIGHT;
        } else {
            currentVolume = 1;
        }
        this.remotePlayer.volumeLevel = currentVolume;
        this.remotePlayerController.setVolumeLevel();
    }.bind(this);

    playerTarget.mute = function () {
        if (!this.remotePlayer.isMuted) {
            this.remotePlayerController.muteOrUnmute();
        }
    }.bind(this);

    playerTarget.unMute = function () {
        if (this.remotePlayer.isMuted) {
            this.remotePlayerController.muteOrUnmute();
        }
    }.bind(this);

    playerTarget.isMuted = function() {
        return this.remotePlayer.isMuted;
    }.bind(this);

    playerTarget.seekTo = function (time) {
        this.remotePlayer.currentTime = time;
        this.remotePlayerController.seek();
    }.bind(this);

    this.playerHandler.setTarget(playerTarget);

    // Setup remote player volume right on setup
    // The remote player may have had a volume set from previous playback
    if (this.remotePlayer.isMuted) {
        this.playerHandler.mute();
    }
    var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
    var p = document.getElementById('audio_bg_level');
    p.style.height = currentVolume + 'px';
    p.style.marginTop = -currentVolume + 'px';

    this.hideFullscreenButton();

    this.playerHandler.play();
};

بارگیری رسانه

در Cast SDK، RemotePlayer و RemotePlayerController مجموعه‌ای از APIهای مناسب را برای مدیریت پخش رسانه از راه دور در گیرنده ارائه می‌دهند. برای CastSession که از پخش رسانه پشتیبانی می‌کند، نمونه‌های RemotePlayer و RemotePlayerController به طور خودکار توسط SDK ایجاد می‌شوند. همانطور که قبلاً در codelab نشان داده شده است، می‌توان با ایجاد نمونه‌هایی از cast.framework.RemotePlayer و cast.framework.RemotePlayerController به ترتیب به آنها دسترسی داشت.

در مرحله بعد، باید ویدیوی انتخاب شده فعلی را با ساخت یک شیء MediaInfo برای SDK جهت پردازش و ارسال درخواست، روی گیرنده بارگذاری کنیم. برای انجام این کار، کد زیر را به setupRemotePlayer اضافه کنید:

/**
 * Set the PlayerHandler target to use the remote player
 */
CastPlayer.prototype.setupRemotePlayer = function () {
    //...

    playerTarget.load = function (mediaIndex) {
        console.log('Loading...' + this.mediaContents[mediaIndex]['title']);
        var mediaInfo = new chrome.cast.media.MediaInfo(
            this.mediaContents[mediaIndex]['sources'][0], 'video/mp4');

        mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();
        mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;
        mediaInfo.metadata.title = this.mediaContents[mediaIndex]['title'];
        mediaInfo.metadata.images = [
            {'url': MEDIA_SOURCE_ROOT + this.mediaContents[mediaIndex]['thumb']}];

        var request = new chrome.cast.media.LoadRequest(mediaInfo);
        castSession.loadMedia(request).then(
            this.playerHandler.loaded.bind(this.playerHandler),
            function (errorCode) {
                this.playerState = PLAYER_STATE.ERROR;
                console.log('Remote media load error: ' +
                    CastPlayer.getErrorMessage(errorCode));
            }.bind(this));
    }.bind(this);

    //...
};

اکنون روشی برای جابجایی بین پخش محلی و از راه دور اضافه کنید:

/**
 * This is a method for switching between the local and remote
 * players. If the local player is selected, setupLocalPlayer()
 * is run. If there is a cast device connected we run
 * setupRemotePlayer().
 */
CastPlayer.prototype.switchPlayer = function() {
    this.stopProgressTimer();
    this.resetVolumeSlider();
    this.playerHandler.stop();
    this.playerState = PLAYER_STATE.IDLE;
    if (cast && cast.framework) {
        if (this.remotePlayer.isConnected) {
            this.setupRemotePlayer();
            return;
        }
    }
    this.setupLocalPlayer();
};

در نهایت، یک متد برای مدیریت هرگونه پیام خطای تبدیل نوع (Cast) اضافه کنید:

/**
 * Makes human-readable message from chrome.cast.Error
 * @param {chrome.cast.Error} error
 * @return {string} error message
 */
CastPlayer.getErrorMessage = function(error) {
  switch (error.code) {
    case chrome.cast.ErrorCode.API_NOT_INITIALIZED:
      return 'The API is not initialized.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.CANCEL:
      return 'The operation was canceled by the user' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.CHANNEL_ERROR:
      return 'A channel to the receiver is not available.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.EXTENSION_MISSING:
      return 'The Cast extension is not available.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.INVALID_PARAMETER:
      return 'The parameters to the operation were not valid.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE:
      return 'No receiver was compatible with the session request.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.SESSION_ERROR:
      return 'A session could not be created, or a session was invalid.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.TIMEOUT:
      return 'The operation timed out.' +
        (error.description ? ' :' + error.description : '');
  }
};

حالا برنامه را اجرا کنید. به دستگاه Cast خود متصل شوید و پخش ویدیو را شروع کنید. باید پخش ویدیو را روی گیرنده ببینید.

۷. اضافه کردن پشتیبانی از اتصال بازیگران

کتابخانه Cast Connect به برنامه‌های فرستنده موجود اجازه می‌دهد تا از طریق پروتکل Cast با برنامه‌های Android TV ارتباط برقرار کنند. Cast Connect بر روی زیرساخت Cast ساخته می‌شود و برنامه Android TV شما به عنوان گیرنده عمل می‌کند.

وابستگی‌ها

  • مرورگر کروم نسخه M87 یا بالاتر

تنظیم سازگاری گیرنده اندروید

برای اجرای برنامه Android TV که به آن Android Receiver نیز گفته می‌شود، باید پرچم androidReceiverCompatible را در شیء CastOptions روی true تنظیم کنیم.

کد زیر را به تابع initializeCastPlayer در فایل CastVideos.js خود اضافه کنید:

var options = {};
...
options.androidReceiverCompatible = true;

cast.framework.CastContext.getInstance().setOptions(options);

اعتبارنامه‌های راه‌اندازی را تنظیم کنید

در سمت فرستنده، می‌توانید CredentialsData برای نشان دادن اینکه چه کسی به جلسه می‌پیوندد، مشخص کنید. credentials رشته‌ای هستند که می‌توانند توسط کاربر تعریف شوند، تا زمانی که برنامه ATV شما بتواند آن را بفهمد. CredentialsData فقط در زمان راه‌اندازی یا اتصال به برنامه Android TV شما منتقل می‌شود. اگر آن را دوباره در حین اتصال تنظیم کنید، به برنامه Android TV شما منتقل نمی‌شود.

برای تنظیم اعتبارنامه‌های راه‌اندازی، CredentialsData باید هر زمان پس از تنظیم گزینه‌های راه‌اندازی تعریف شود.

کد زیر را به کلاس CastVideos.js خود، زیر تابع initializeCastPlayer اضافه کنید:

cast.framework.CastContext.getInstance().setOptions(options);
...
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
...

تنظیم اعتبارنامه‌ها در صورت درخواست بارگذاری

در صورتی که برنامه گیرنده وب و برنامه تلویزیون اندروید شما credentials به طور متفاوتی مدیریت می‌کنند، ممکن است لازم باشد برای هر کدام اعتبارنامه‌های جداگانه‌ای تعریف کنید. برای انجام این کار، کد زیر را در CastVideos.js خود در زیر playerTarget.load در تابع setupRemotePlayer اضافه کنید:

...
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...

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

تست اتصال کست

مراحل نصب APK اندروید تی‌وی روی کروم‌کست با گوگل تی‌وی:

  1. آدرس IP دستگاه Android TV خود را پیدا کنید. معمولاً این آدرس در قسمت تنظیمات > شبکه و اینترنت > (نام شبکه‌ای که دستگاه شما به آن متصل است) موجود است. در سمت راست، جزئیات و IP دستگاه شما در شبکه نشان داده می‌شود.
  2. از آدرس IP دستگاه خود برای اتصال به آن از طریق ADB با استفاده از ترمینال استفاده کنید:
$ adb connect <device_ip_address>:5555
  1. از پنجره ترمینال خود، به پوشه سطح بالا برای نمونه‌های codelab که در ابتدای این codelab دانلود کرده‌اید، بروید. برای مثال:
$ cd Desktop/chrome_codelab_src
  1. فایل .apk موجود در این پوشه را با اجرای دستور زیر روی تلویزیون اندروید خود نصب کنید:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. اکنون باید بتوانید برنامه‌ای با نام Cast Videos را در منوی برنامه‌های خود در دستگاه Android TV خود مشاهده کنید.
  2. کد ارسال‌کننده وب به‌روزرسانی‌شده را اجرا کنید و با استفاده از آیکون ارسال یا انتخاب Cast.. از منوی کشویی مرورگر کروم خود، یک جلسه ارسال با دستگاه تلویزیون اندروید خود برقرار کنید. اکنون باید برنامه تلویزیون اندروید روی گیرنده اندروید شما اجرا شود و به شما امکان دهد پخش را با استفاده از ریموت تلویزیون اندروید خود کنترل کنید.

۸. تبریک

اکنون می‌دانید که چگونه با استفاده از ویجت‌های Cast SDK در یک برنامه وب کروم، قابلیت پخش ویدیو را در یک برنامه ویدیویی فعال کنید.

برای جزئیات بیشتر، به راهنمای توسعه‌دهنده‌ی Web Sender مراجعه کنید.