הטמעת CameraStream עם WebRTC

1. לפני שמתחילים

התכונה CameraStream שייכת למכשירים שיכולים להפעיל סטרימינג של פידים של וידאו למסכים חכמים, למכשירי Chromecast ולטלפונים חכמים. פרוטוקול WebRTC נתמך עכשיו בתכונה CameraStream, מה שאומר שאפשר לצמצם באופן משמעותי את זמן ההשהיה של ההפעלה והסטרימינג ממצלמה למסך Google Nest.

מכשירי מצלמה שמשדרים בסטרימינג למסך Google Nest

דרישות מוקדמות

מה תלמדו

  • איך פורסים שירות ענן לבית חכם.
  • איך לחבר את השירות ל-Google Assistant.
  • איך להפעיל סטרימינג למסך Google Nest באמצעות פרוטוקול WebRTC.

הדרישות

  • דפדפן אינטרנט, כמו Google Chrome.
  • מכשיר iOS או Android עם אפליקציית Google Home.
  • Node.js בגרסה 10.16 ואילך.
  • תוכנית Blaze (תשלום לפי שימוש) ל-Firebase.
  • מצלמת אינטרנט מובנית או חיצונית שתומכת ברזולוציית Full HD.
  • מסך Google Nest.

2. שנתחיל?

התקנת Firebase CLI

בעזרת Firebase CLI אפשר להפעיל את אפליקציות האינטרנט באופן מקומי ולפרוס אותן ב-Firebase Hosting.

כדי להתקין את Firebase CLI, מבצעים את השלבים הבאים:

  1. במסוף, מורידים ומתקינים את Firebase CLI:
$ npm install -g firebase-tools
  1. בודקים שה-CLI הותקן בצורה תקינה:
$ firebase --version
  1. נותנים הרשאה ל-Firebase CLI באמצעות חשבון Google:
$ firebase login

יצירת פרויקט

  1. עוברים אל Google Home Developer Console.
  2. לוחצים על Create Project, מזינים שם לפרויקט ולוחצים על Create Project.

שם הפרויקט

הפעלת אפליקציית הלקוח CameraStream

קוד המקור של ה-codelab הזה כולל לקוח WebRTC שמקים, מנהל ומתנהל מול סשן WebRTC בין מצלמת האינטרנט לבין מסך חכם של Google לבית חכם.

כדי להפעיל את אפליקציית הלקוח CameraStream WebRTC, מבצעים אחת מהפעולות הבאות:

  • כדי להוריד את קוד המקור למחשב הפיתוח, לוחצים על הלחצן הבא:

  • משכפלים את המאגר הזה ב-GitHub:
    $ git clone https://github.com/google-home/smarthome-camerastream-webrtc.git
    

הקוד מכיל את הספריות הבאות:

  • הספרייה camerastream-start, שמכילה את קוד לתחילת הדרך שעליו אתם בונים.
  • הספרייה camerastream-done, שמכילה את קוד הפתרון ל-Codelab שהושלם.

הספרייה camerastream-start מכילה את ספריות המשנה הבאות:

  • ספריית המשנה public, שמכילה ממשק משתמש של קצה קדמי כדי לשלוט בקלות במצב של מכשיר המצלמה ולעקוב אחריו.
  • ספריית המשנה functions, שמכילה שירות ענן מיושם במלואו שמנהל את המצלמה באמצעות Cloud Functions for Firebase ומסד נתונים בזמן אמת.

קוד לתחילת הדרך מכיל הערות TODO שמציינות איפה צריך להוסיף או לשנות קוד, כמו בדוגמה הבאה:

// TODO: Implement full SYNC response.

הוספת Firebase לפרויקט ב-Google Home Developer Console

שיטה 1: דרך מסוף Firebase

  1. עוברים אל Firebase.
  2. לוחצים על יצירת פרויקט Firebase.
    יצירת פרויקט Firebase
  3. במסך Create a project (יצירת פרויקט), לוחצים על Add Firebase to Google Cloud project (הוספת Firebase לפרויקט Google Cloud).
    הוספת Firebase לפרויקט ב-Google Cloud
  4. במסך Get started (תחילת העבודה), בוחרים את פרויקט הענן ב-Google Cloud שיצרתם זה עתה במסוף הפיתוח של Google Home ולוחצים על Continue (המשך).
    בחירת פרויקט בענן של Google

שיטה 2: דרך Firebase CLI

firebase projects:addfirebase

בוחרים את הפרויקט ב-Google Home Developer Console שנוצר זה עתה כדי להוסיף את Firebase.

כשמוסיפים את Firebase לפרויקט ב-Google Home Developer Console, הוא מופיע במסוף Firebase. מזהה הפרויקט ב-Firebase יהיה זהה למזהה הפרויקט ב-Google Home Developer Console.

פרויקט בענן נוסף

התחברות אל Firebase

  1. עוברים לספרייה camerastream-start ומגדירים את Firebase CLI באמצעות פרויקט Actions:
$ cd camerastream-start
$ firebase use <project-id>
  1. בספרייה camerastream-start, עוברים לתיקייה functions ומתקינים את כל הרכיבים התלויים שנדרשים:
$ cd functions
$ npm install
  1. אם ההודעה הבאה מופיעה, אפשר להתעלם ממנה. האזהרה הזו מופיעה בגלל תלות ישנות יותר. מידע נוסף זמין בבעיה הזו ב-GitHub.
found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details
  1. מאתחלים פרויקט Firebase:
$ firebase init
  1. בוחרים באפשרות פונקציות ואז באפשרות אירוח. הפעולה הזו מאתחלת את ממשקי ה-API והתכונות הנדרשים לפרויקט.
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter
 to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to
 proceed)
>( ) Data Connect: Set up a Firebase Data Connect service
 ( ) Firestore: Configure security rules and indexes files for Firestore
 ( ) Genkit: Setup a new Genkit project with Firebase
 (*) Functions: Configure a Cloud Functions directory and its files
 ( ) App Hosting: Configure an apphosting.yaml file for App Hosting
 (*) Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ( ) Storage: Configure a security rules file for Cloud Storage
 ( ) Emulators: Set up local emulators for Firebase products
 ( ) Remote Config: Configure a template file for Remote Config
 ( ) Extensions: Set up an empty Extensions manifest
 (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision
default instance
 ( ) Data Connect: Set up a Firebase Data Connect service
 ( ) Firestore: Configure security rules and indexes files for Firestore
  1. מגדירים את Cloud Functions עם קובצי ברירת המחדל, ומוודאים שלא דורסים את הקבצים הקיימים index.js ו-package.json בדוגמה של הפרויקט:
? Would you like to initialize a new codebase, or overwrite an existing one?
Overwrite

? What language would you like to use to write Cloud Functions?
JavaScript

? File functions/package.json already exists. Overwrite?
No

? File functions/index.js already exists. Overwrite?
No

? Do you want to install dependencies with npm now?
Yes
  1. מגדירים את Hosting באמצעות הספרייה public בקוד הפרויקט ומשתמשים בקובץ index.html הקיים:
? What do you want to use as your public directory?
public

? Configure as a single-page app (rewrite all urls to /index.html)?
Yes

? Set up automatic builds and deploys with GitHub?
No

? File public/index.html already exists. Overwrite?
 No

3. החלפת הודעות Session Description Protocol ‏ (SDP)

החלפת הודעות SDP היא שלב חשוב ביצירת סטרימינג של WebRTC. פרוטוקול SDP הוא פרוטוקול מבוסס-טקסט שמתאר את המאפיינים של סשן מולטימדיה. נעשה בו שימוש ב-WebRTC כדי לנהל משא ומתן על הפרמטרים של חיבור ישיר בין עמיתים, כמו קודקים שנעשה בהם שימוש, כתובות ה-IP של המשתתפים והיציאות שמשמשות להעברת מדיה.

כדי להשתמש ב-Realtime Database כמארח להחלפת הודעות SDP בין מצלמת האינטרנט לבין אפליקציית הלקוח CameraStream של הבית החכם, פועלים לפי השלבים הבאים:

  1. במסוף Firebase, לוחצים על Build > Realtime Database > Create database (פיתוח > מסד נתונים בזמן אמת > יצירת מסד נתונים).

הדף Realtime Database (מסד נתונים בזמן אמת) במסוף Firebase

  1. בתפריט הנפתח מיקום של מסד נתונים בזמן אמת, בוחרים מיקום מתאים לאירוח מסד הנתונים.

התפריט הנפתח של מיקום מסד נתונים בזמן אמת בתיבת הדו-שיח Set up database (הגדרת מסד נתונים)

  1. בוחרים באפשרות התחלה במצב בדיקה ולוחצים על הפעלה. אם מפעילים את מסד נתונים בזמן אמת, צריך להיות אפשר להפנות אליו מאפליקציית הלקוח CameraStream.
  1. במסוף Firebase, בוחרים באפשרות 513f2be95dcd7896.png Project settings (הגדרות הפרויקט) > Project settings (הגדרות הפרויקט) > e584a9026e2b407f.pngAdd Firebase to your Web App (הוספת Firebase לאפליקציית האינטרנט) כדי להפעיל את תהליך ההגדרה.
  2. אם כבר הוספתם אפליקציה לפרויקט Firebase, לוחצים על הוספת אפליקציה כדי להציג את אפשרויות הפלטפורמה.
  3. מזינים כינוי לאפליקציה, כמו My web app, ולוחצים על רישום האפליקציה.
  4. בקטע Add Firebase SDK (הוספת Firebase SDK), בוחרים באפשרות Use <script> tag (שימוש בתג <script>).
  5. מעתיקים את הערכים מהאובייקט firebasebaseConfig ומדביקים אותם בקובץ camaerastream-start/public/webrtc_generator.js.
const firebaseConfig = {
  apiKey: "XXXXX",
  authDomain: "XXXXX",
  projectId: "XXXXX",
  storageBucket: "XXXXX",
  messagingSenderId: "XXXXX",
  appId: "XXXXX",
  measurementId: "XXXXX"
};
  1. לוחצים על Continue to console (המשך אל מסוף) כדי להשלים את התהליך. אפליקציית האינטרנט החדשה שנוצרה מופיעה בדף Project settings (הגדרות הפרויקט).

4. יצירת מצלמת WebRTC

אחרי שמגדירים את הפעולה, שירות הענן צריך לטפל בכוונות הבאות:

  • SYNC כוונה שמתרחשת כש-Assistant רוצה לדעת אילו מכשירים מחוברים למשתמש. הפרטים האלה נשלחים לשירות כשמשתמש מקשר חשבון. עליכם להשיב עם מטען ייעודי (payload) של JSON שמכיל את המכשירים של המשתמש ואת היכולות שלהם.
  • EXECUTE/QUERY Intent שמתרחש כש-Assistant רוצה לשלוט במכשיר בשם משתמש. צריך להגיב עם מטען ייעודי (payload) של JSON עם סטטוס הביצוע של כל מכשיר שהתבקש.

בקטע הזה מעדכנים את הפונקציות שפרסתם קודם כדי לטפל בכוונה הזו.

עדכון התשובה להזמנה SYNC

  1. עוברים לקובץ functions/index.js. הוא מכיל את הקוד לתגובה לבקשות מ-Assistant.
  2. עורכים את הכוונה SYNC כדי להחזיר את המטא-נתונים והיכולות של המכשיר:

index.js

app.onSync((body) => {
return {
  requestId: body.requestId,
  payload: {
    agentUserId: USER_ID,
    devices: [{
      id: 'camera',
      type: 'action.devices.types.CAMERA',
      traits: [
        'action.devices.traits.OnOff',
        'action.devices.traits.CameraStream',
      ],
      name: {
        defaultNames: ['My WebRTC Camera'],
        name: 'Camera',
        nicknames: ['Camera'],
      },
      deviceInfo: {
        manufacturer: 'Acme Co',
        model: 'acme-camera',
        hwVersion: '1.0',
        swVersion: '1.0.1',
      },
      willReportState: false,
      attributes: {
        cameraStreamSupportedProtocols:['webrtc'],
        cameraStreamNeedAuthToken: true, 
        cameraStreamSupportsPreview: true
      },
    }],
  },
};
});
  1. USER_ID לא מוגדר בקוד. מוסיפים את הטקסט הבא לקטע const _ = require('underscore');:
// Hardcoded user ID
const USER_ID = '123';

טיפול בכוונת החיפוש EXECUTE

ה-intent‏ EXECUTE מטפל בפקודות לעדכון מצב המכשיר. בתגובה מופיע הסטטוס של כל פקודה – לדוגמה, SUCCESS,‏ ERROR או PENDING – ומצב המכשיר החדש.

כדי לטפל ב-intent‏ EXECUTE, עורכים את ה-intent‏ EXECUTE כדי להחזיר את נקודת הקצה signaling של פרויקט Firebase בקובץ functions/index.js:

index.js

app.onExecute(async (body,headers) => {
  var array = headers.authorization.split(' ');
  var snapshot = await firebaseRef.ref('/userId/'+array[1]).once('value');
  var offerGenLocation = snapshot.val().type;
  const {requestId} = body;

  var result = {
    status: 'SUCCESS',
    states: {
      cameraStreamProtocol: 'webrtc',
      cameraStreamSignalingUrl:'https://us-central1-<project-id>.cloudfunctions.net/signaling?token='+array[1], // TODO: Add Firebase hosting URL
      cameraStreamIceServers: '',
      cameraStreamOffer:'',
      cameraStreamAuthToken:'',
    },
    ids: [ 
      'camera'
    ],
  };
  
  return {
    requestId: requestId,
    payload: {
      commands: [result],
    },
  };
});

טיפול בשיתוף משאבים בין מקורות (CORS)

כדי לטפל ב-CORS בגלל השימוש בשיטה POST לשליחת ה-SDP, מוסיפים את כתובת ה-URL של אירוח ב-Firebase למערך allowlist בקובץ functions/index.js:

index.js

'use strict';
.....

var allowList = ['https://www.gstatic.com','https://<project-id>.web.app']; //TODO Add Firebase hosting URL.

מידע נוסף על CORS זמין במאמר בנושא שיתוף משאבים בין מקורות (CORS).

טיפול בסיום השידור

כדי לטפל בסיום של שידור WebRTC, מוסיפים את כתובת ה-URL של הפונקציה 'איתות' של Firebase לקובץ public/webrtc_generator.js:

webrtc_generator.js

terminateButton.onclick = function(){
  console.log('Terminating Stream!!')
  var signalingURL = 'https://us-central1-<project-id>.cloudfunctions.net/signaling'; //TODO Add Firebase hosting URL
   var http = new XMLHttpRequest();

פריסה ב-Firebase

כדי לפרוס ל-Firebase, פורסים את המילוי המעודכן של הענן באמצעות Firebase CLI:

$ firebase deploy

הפקודה הזו פורסת אפליקציית אינטרנט וכמה פונקציות ב-Cloud Functions for Firebase:

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.web.app

הגדרת הפרויקט ב-Developer Console

  1. נכנסים ל-Play Console.
  2. לוחצים על Create Project, מזינים שם לפרויקט ולוחצים על Create Project.

שם הפרויקט

בחירת שילוב בין ענן לענן

בדף Project Home ב-Developer Console, בוחרים באפשרות Add cloud-to-cloud integration בקטע Cloud-to-cloud.

הוספת שילוב מענן לענן

  1. מזינים שם שילוב ובוחרים באפשרות מצלמה בקטע סוג המכשיר. השם הזה יופיע באפליקציית Google Home בהמשך, כשתצטרכו להגדיר מכשיר. ב-codelab הזה, הזנו WebRTC Codelab כשם המוצג, אבל אתם יכולים להשתמש בשם אחר.

הוספת שם מוצג

  1. בקטע App branding (מיתוג האפליקציה), מעלים קובץ png של סמל האפליקציה בגודל 144x144 פיקסלים, שנקרא .png.

הוספת סמל לאפליקציה

הפעלת קישור חשבונות

כדי להפעיל את קישור החשבון אחרי פריסת הפרויקט, פועלים לפי השלבים הבאים:

  1. נכנסים אל Developer Console ופותחים את הפרויקט.
  2. בקטע Cloud-to-Cloud, לוחצים על Develop (פיתוח) > Edit (עריכה) לצד השילוב.
  3. בדף הגדרה וקביעת תצורה, מאתרים את הקטע קישור חשבון ומזינים את הפרטים הבאים בתיבות הטקסט המתאימות:

Client-ID

ABC123

סוד לקוח

DEF456

כתובת אתר להרשאה

https://us-central1-
.cloudfunctions.net/fakeauth

כתובת URL לטוקן

https://us-central1-
.cloudfunctions.net/faketoken

עדכון כתובות URL לקישור חשבונות

  1. לוחצים על שמירה > בדיקה.

5. בדיקת המצלמה הווירטואלית של WebRTC

  1. עוברים לכתובת ה-URL של Hosting שהופיעה כשפרסתם את פרויקט Firebase. מוצג הממשק הבא, שהוא אפליקציית הלקוח CameraStream:

הממשק של אפליקציית הלקוח CameraStream

  1. בחלונית רזולוציית סרטון מקומי, בוחרים את הסרטון הרצוי.
  2. נותנים לאפליקציית הלקוח CameraStream הרשאת גישה למצלמת האינטרנט ולמיקרופון. פיד וידאו ממצלמת האינטרנט מופיע בלקוח.
  1. באפליקציית Google Home, מקישים על הוספה > עובד עם Google.

הדף &#39;הגדרת מכשיר&#39; באפליקציית Google Home

  1. מחפשים את הפעולה שיצרתם ובוחרים אותה.

הפעולה לבית חכם באפליקציית Google Home

  1. חשוב לשמור את הקוד האלפאנומרי הייחודי בן חמשת התווים, כי תצטרכו אותו בהמשך.

הקוד האלפאנומרי הייחודי בן חמש הספרות

  1. מקישים על חזרה. המצלמה עם WebRTC נוספת למבנה שלכם באפליקציית Google Home.

התחלת שידור WebRTC

  1. בדף האינטרנט של אפליקציית הלקוח CameraStream, מזינים את הקוד האלפאנומרי מהקטע האחרון בתיבת הטקסט Account linking token value (ערך טוקן לקישור חשבון) ואז לוחצים על Submit (שליחה).

תיבת הטקסט של ערך הטוקן לקישור החשבון

  1. כדי להתחיל סשן WebRTC ממסך חכם של Google, מבצעים אחת מהפעולות הבאות:
  • אומרים "Ok Google, stream WebRTC Camera" (הפעלת סטרימינג של מצלמת WebRTC).
  • במסך החכם של Google, מקישים על שליטה בבית > מצלמה > מצלמת WebRTC.

באפליקציית הלקוח CameraStream של Google בית חכם, אפשר לראות ש-SPD של בקשת ההצעה ו-SPD של התשובה נוצרו והוחלפו בהצלחה. התמונה ממצלמת האינטרנט מועברת בסטרימינג למסך החכם שלכם מבית Google באמצעות WebRTC.

6. מזל טוב

מעולה! למדתם איך לשדר ממצלמת האינטרנט למסך Nest של מכשיר Google Nest באמצעות פרוטוקול WebRTC.

מידע נוסף