הטמעת 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.
  • מצלמת אינטרנט מובנית או חיצונית שתומכת ברזולוציית HD מלאה.
  • מסך Google Nest.

2. שנתחיל?

התקנת ה-CLI של Firebase

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

כדי להתקין את Firebase CLI:

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

יצירת פרויקט

  1. נכנסים למסוף הפיתוח של Google Home.
  2. לוחצים על Create Project, מזינים שם לפרויקט ולוחצים על Create Project.

שם הפרויקט

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

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

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

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

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

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

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

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

  • ספריית המשנה public, שמכילה ממשק משתמש חזיתי (frontend) שמאפשר לשלוט בקלות במצב של מצלמת המכשיר ולעקוב אחריו.
  • ספריית המשנה functions, שמכילה שירות ענן מיושם במלואו שמנהל את המצלמה באמצעות Cloud Functions ל-Firebase ול-Realtime Database.

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

// TODO: Implement full SYNC response.

יצירת פרויקט Firebase

  1. עוברים אל Firebase.
  2. לוחצים על Create a project ומזינים את שם הפרויקט.
  3. מסמנים את התיבה של ההסכם ולוחצים על המשך. אם אין תיבת סימון של הסכמה, אפשר לדלג על השלב הזה.
    יצירת פרויקט Firebase
  4. אחרי שיוצרים את פרויקט Firebase, מחפשים את מזהה הפרויקט. עוברים אל סקירה כללית של הפרויקט ולוחצים על סמל ההגדרות > הגדרות הפרויקט.
    פתיחת הגדרות הפרויקט
  5. הפרויקט מופיע בכרטיסייה General.
    הגדרות כלליות של הפרויקט

התחברות אל Firebase

  1. עוברים לספרייה camerastream-start ומגדירים את Firebase CLI עם פרויקט Actions:
$ cd camerastream-start
$ firebase use <firebase-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. בוחרים באפשרות Functions ו-Hosting. הפעולה הזו מפעילה את ממשקי ה-API והתכונות הנדרשים לפרויקט.
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. 
❯◯ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance
 ◯ Firestore: Deploy rules and create indexes for Firestore
 ◉ Functions: Configure a Cloud Functions directory and its files
 ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ◯ Hosting: Set up GitHub Action deploys
 ◯ Storage: Configure a security rules file for Cloud Storage
 ◯ Extensions: Set up an empty Extensions manifest
  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. מגדירים את האירוח באמצעות הספרייה 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. הודעות של פרוטוקול תיאור הסשן (SDP) של Exchange

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

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

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

הדף Realtime Database במסוף Firebase

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

התפריט הנפתח של המיקום ב-Realtime Database בתיבת הדו-שיח &#39;הגדרת מסד נתונים&#39;

  1. בוחרים באפשרות הפעלה במצב בדיקה ולוחצים על הפעלה. כשמפעילים את Realtime Database, צריך להיות אפשרות להפנות אליו מאפליקציית הלקוח של CameraStream.
  1. במסוף Firebase, בוחרים באפשרות 513f2be95dcd7896.png Project settings (הגדרות הפרויקט) > Project settings (הגדרות הפרויקט) > e584a9026e2b407f.pngAdd Firebase to your Web App (הוספת Firebase לאפליקציית האינטרנט) כדי להפעיל את תהליך העבודה להגדרה.
  2. אם כבר הוספתם אפליקציה לפרויקט Firebase, לוחצים על Add app (הוספת אפליקציה) כדי להציג את אפשרויות הפלטפורמה.
  3. מזינים כינוי לאפליקציה, למשל My web app, ולוחצים על רישום אפליקציה.
  4. בקטע Add Firebase SDK (הוספת ה-SDK של Firebase), בוחרים באפשרות 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 שמתרחשת כש-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

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

כדי לטפל בכוונה EXECUTE, עורכים את הכוונה 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://<firebase-project-id>.web.app']; //TODO Add Firebase hosting URL.

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

טיפול בהפסקת השידור

כדי לטפל בסיום של שידור WebRTC, מוסיפים את כתובת ה-URL של פונקציית ה-signaling ב-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, פורסים את ה-cloud fulfillment המעודכן באמצעות ה-CLI של Firebase:

$ 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. נכנסים ל-Developer Console.
  2. לוחצים על Create Project, מזינים שם לפרויקט ולוחצים על Create Project.

שם הפרויקט

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

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

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

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

הוספת שם מוצג

  1. בקטע מיתוג האפליקציה, מעלים קובץ png של סמל האפליקציה בגודל 144 על 144 פיקסלים ובשם .png.

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

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

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

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

Client-ID

ABC123

סוד לקוח

DEF456

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

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

כתובת URL לטוקן

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

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

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

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

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

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

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

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

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

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

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

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

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

התחלת שידור WebRTC

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

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

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

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

6. מזל טוב

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

מידע נוסף