1. לפני שמתחילים
המאפיין CameraStream
שייך למכשירים עם יכולת להעביר סטרימינג של פידים של וידאו למסכים חכמים, למכשירי Chromecast ולטלפונים חכמים. פרוטוקול WebRTC נתמך עכשיו במאפיין CameraStream
, כך שאפשר לצמצם באופן משמעותי את זמן האחזור של ההפעלה והסטרימינג ממכשיר מצלמה למכשיר תצוגה של Google Nest.
דרישות מוקדמות
- מומלץ לעיין במאמר מבוא ל-Cloud-to-cloud.
מה תלמדו
- איך פורסים שירות ענן לבית חכם.
- איך מחברים את השירות ל-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:
- בטרמינל, מורידים ומתקינים את Firebase CLI:
$ npm install -g firebase-tools
- מוודאים שה-CLI מותקן בצורה נכונה:
$ firebase --version
- נותנים הרשאה ל-CLI של Firebase באמצעות חשבון Google:
$ firebase login
יצירת פרויקט
- נכנסים למסוף הפיתוח של Google Home.
- לוחצים על 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
- עוברים אל Firebase.
- לוחצים על Create a project ומזינים את שם הפרויקט.
- מסמנים את התיבה של ההסכם ולוחצים על המשך. אם אין תיבת סימון של הסכמה, אפשר לדלג על השלב הזה.
- אחרי שיוצרים את פרויקט Firebase, מחפשים את מזהה הפרויקט. עוברים אל סקירה כללית של הפרויקט ולוחצים על סמל ההגדרות > הגדרות הפרויקט.
- הפרויקט מופיע בכרטיסייה General.
התחברות אל Firebase
- עוברים לספרייה
camerastream-start
ומגדירים את Firebase CLI עם פרויקט Actions:
$ cd camerastream-start $ firebase use <firebase-project-id>
- בספרייה
camerastream-start
, עוברים לתיקייהfunctions
ומתקינים את כל הרכיבים התלויים הנדרשים:
$ cd functions $ npm install
- אם ההודעה הבאה מופיעה, אפשר להתעלם ממנה. האזהרה הזו נובעת מיחסי תלות ישנים יותר. מידע נוסף זמין בבעיה הזו ב-GitHub.
found 5 high severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details
- מפעילים את פרויקט Firebase:
$ firebase init
- בוחרים באפשרות 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
- מגדירים את 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
- מגדירים את האירוח באמצעות הספרייה
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 לבית החכם, פועלים לפי השלבים הבאים:
- במסוף Firebase, לוחצים על Build (פיתוח) > Realtime Database (מסד נתונים בזמן אמת) > Create database (יצירת מסד נתונים).
- בתפריט הנפתח מיקום של Realtime Database, בוחרים מיקום מתאים לאירוח מסד הנתונים.
- בוחרים באפשרות הפעלה במצב בדיקה ולוחצים על הפעלה. כשמפעילים את Realtime Database, צריך להיות אפשרות להפנות אליו מאפליקציית הלקוח של CameraStream.
- במסוף Firebase, בוחרים באפשרות Project settings (הגדרות הפרויקט) > Project settings (הגדרות הפרויקט) > Add Firebase to your Web App (הוספת Firebase לאפליקציית האינטרנט) כדי להפעיל את תהליך העבודה להגדרה.
- אם כבר הוספתם אפליקציה לפרויקט Firebase, לוחצים על Add app (הוספת אפליקציה) כדי להציג את אפשרויות הפלטפורמה.
- מזינים כינוי לאפליקציה, למשל
My web app
, ולוחצים על רישום אפליקציה. - בקטע Add Firebase SDK (הוספת ה-SDK של Firebase), בוחרים באפשרות Use <script> tag (שימוש בתג <script>).
- מעתיקים את הערכים מהאובייקט
firebasebaseConfig
ומדביקים אותם בקובץcamaerastream-start/public/webrtc_generator.js
.
const firebaseConfig = {
apiKey: "XXXXX",
authDomain: "XXXXX",
projectId: "XXXXX",
storageBucket: "XXXXX",
messagingSenderId: "XXXXX",
appId: "XXXXX",
measurementId: "XXXXX"
};
- לוחצים על Continue to console כדי להשלים את התהליך. אפליקציית האינטרנט החדשה שיצרתם תופיע בדף Project settings (הגדרות הפרויקט).
4. יצירת מצלמת WebRTC
עכשיו, אחרי שהגדרתם את הפעולה, שירות הענן צריך לטפל בכוונות הבאות:
- כוונה מסוג
SYNC
שמתרחשת כש-Assistant רוצה לדעת אילו מכשירים המשתמש מחבר. המזהה הזה נשלח לשירות שלכם כשהמשתמש מקשר חשבון. צריך להשיב עם עומס נתונים (payload) בפורמט JSON של המכשירים של המשתמש והיכולות שלהם. - כוונה מסוג
EXECUTE/QUERY
שמתרחשת כש-Assistant רוצה לשלוט במכשיר בשם המשתמש. צריך להשיב עם מטען ייעודי (payload) של JSON עם סטטוס הביצוע של כל מכשיר שביקשת.
בקטע הזה מעדכנים את הפונקציות שפרסמתם בעבר כדי לטפל בכוונות האלה.
עדכון התשובה SYNC
- עוברים לקובץ
functions/index.js
. הוא מכיל את הקוד לתגובה לבקשות מ-Assistant. - עורכים את הכוונה
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
},
}],
},
};
});
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
- נכנסים ל-Developer Console.
- לוחצים על Create Project, מזינים שם לפרויקט ולוחצים על Create Project.
בחירת השילוב בין עננים
בדף Project Home במסוף הפיתוח, בוחרים באפשרות Add cloud-to-cloud integration בקטע Cloud-to-cloud.
- מזינים שם לשילוב ובוחרים באפשרות מצלמה בקטע סוג המכשיר. השם הזה יופיע באפליקציית Google Home בשלב מאוחר יותר, כשיהיה מכשיר להגדרה. בקודלאב הזה הזנו WebRTC Codelab כשם מוצג, אבל אפשר להשתמש בשם אחר.
- בקטע מיתוג האפליקציה, מעלים קובץ
png
של סמל האפליקציה בגודל 144 על 144 פיקסלים ובשם
..png
הפעלת קישור החשבונות
כדי להפעיל את הקישור לחשבון אחרי הפריסה של הפרויקט:
- נכנסים ל-Developer Console ופותחים את הפרויקט.
- בקטע Cloud-to-Cloud, לוחצים על Develop (פיתוח) > Edit (עריכה) לצד השילוב.
- בדף Setup & configuration (הגדרה והגדרות אישיות), מחפשים את הקטע Account Linking (קישור חשבונות) ומזינים את הפרטים הבאים בתיבות הטקסט המתאימות:
Client-ID |
|
סוד לקוח |
|
כתובת אתר להרשאה |
|
כתובת URL לטוקן |
|
- לוחצים על שמירה > בדיקה.
5. בדיקת המצלמה הווירטואלית של WebRTC
- עוברים לכתובת ה-URL של האירוח שראיתם כשפרסתם את פרויקט Firebase. יוצג הממשק הבא, שהוא אפליקציית הלקוח של CameraStream:
- בוחרים את הסרטון הרצוי בחלונית רזולוציית וידאו מקומית.
- מעניקים לאפליקציית הלקוח של CameraStream הרשאת גישה למצלמת האינטרנט ולמיקרופון. פיד וידאו מהמצלמה הווירטואלית מופיע בצד הלקוח.
קישור לבית החכם CameraStream
פעולה
- באפליקציית Google Home, מקישים על הוספה > עובד עם Google.
- מחפשים את הפעולה שיצרתם ובוחרים אותה.
- חשוב לזכור את הקוד הייחודי בן חמישה תווים אלפאנומריים, כי תצטרכו אותו בהמשך.
- מקישים על החזרה לאחור. המצלמה עם WebRTC תתווסף למבנה שלכם באפליקציית Google Home.
התחלת שידור WebRTC
- בדף האינטרנט של אפליקציית הלקוח CameraStream, מזינים את הקוד האלפאנומרי מהקטע האחרון בתיבה Account linking token value (ערך האסימון לקישור החשבון) ולוחצים על Submit (שליחה).
- כדי להתחיל סשן WebRTC ממכשיר התצוגה החכמה של Google, מבצעים אחת מהפעולות הבאות:
- אומרים "Ok Google, stream WebRTC Camera".
- במסך החכם של Google, מקישים על בקרת הבית > מצלמה > מצלמת WebRTC.
באפליקציית הלקוח CameraStream לבית החכם של Google, אפשר לראות שה-SPD של ההצעה וה-SDP של התשובה נוצרו והוחלפו בהצלחה. התמונה ממצלמת האינטרנט מועברת בסטרימינג למכשיר המסך החכם של Google באמצעות WebRTC.
6. מזל טוב
מעולה! למדתם איך לבצע סטרימינג ממצלמת האינטרנט למכשיר מסך של Google Nest באמצעות פרוטוקול WebRTC.