Triển khai CameraStream bằng WebRTC

1. Trước khi bắt đầu

Thuộc tính CameraStream thuộc về các thiết bị có khả năng truyền trực tuyến nguồn cấp dữ liệu video đến màn hình thông minh, thiết bị Chromecast và điện thoại thông minh. Giao thức WebRTC hiện được hỗ trợ trong đặc điểm CameraStream, nghĩa là bạn có thể giảm đáng kể độ trễ khởi động và truyền trực tuyến từ thiết bị máy ảnh sang thiết bị hiển thị Google Nest.

Thiết bị máy ảnh phát trực tuyến đến thiết bị màn hình Google Nest

Điều kiện tiên quyết

Kiến thức bạn sẽ học được

  • Cách triển khai dịch vụ đám mây nhà thông minh.
  • Cách kết nối dịch vụ của bạn với Trợ lý Google.
  • Cách truyền trực tuyến đến thiết bị màn hình Google Nest bằng giao thức WebRTC.

Bạn cần có

  • Một trình duyệt web, chẳng hạn như Google Chrome.
  • Thiết bị iOS hoặc Android có ứng dụng Google Home.
  • Node.js phiên bản 10.16 trở lên.
  • Gói Blaze (trả theo mức sử dụng) cho Firebase.
  • Thiết bị webcam tích hợp hoặc bên ngoài có thể hỗ trợ độ phân giải full HD.
  • Thiết bị Google Nest có màn hình.

2. Bắt đầu

Cài đặt Giao diện dòng lệnh (CLI) của Firebase

Giao diện dòng lệnh (CLI) của Firebase cho phép bạn phân phát ứng dụng web trên máy và triển khai ứng dụng đó lên Lưu trữ Firebase.

Để cài đặt Firebase CLI, hãy làm theo các bước sau:

  1. Trong dòng lệnh, hãy tải xuống và cài đặt Giao diện dòng lệnh (CLI) của Firebase:
$ npm install -g firebase-tools
  1. Xác minh rằng CLI đã được cài đặt đúng cách:
$ firebase --version
  1. Uỷ quyền cho Giao diện dòng lệnh Firebase bằng Tài khoản Google của bạn:
$ firebase login

Tạo một dự án

  1. Chuyển đến Google Home Developer Console.
  2. Nhấp vào Create Project (Tạo dự án), nhập tên cho dự án rồi nhấp vào Create Project (Tạo dự án).

Đặt tên dự án

Chạy ứng dụng khách CameraStream

Mã nguồn cho lớp học lập trình này bao gồm một ứng dụng WebRTC giúp thiết lập, đàm phán và quản lý phiên WebRTC giữa webcam và thiết bị hiển thị nhà thông minh của Google.

Để chạy ứng dụng khách CameraStream WebRTC, hãy làm theo một trong những cách sau:

  • Nhấp vào nút sau để tải mã nguồn xuống máy phát triển:

  • Sao chép kho lưu trữ này trên GitHub:
    $ git clone https://github.com/google-home/smarthome-camerastream-webrtc.git
    

Mã này chứa các thư mục sau:

  • Thư mục camerastream-start chứa mã khởi đầu mà bạn sẽ xây dựng.
  • Thư mục camerastream-done chứa mã giải pháp cho lớp học lập trình đã hoàn tất.

Thư mục camerastream-start chứa các thư mục con sau:

  • Thư mục con public chứa giao diện người dùng phía trước để dễ dàng kiểm soát và theo dõi trạng thái của thiết bị máy ảnh.
  • Thư mục con functions chứa một dịch vụ đám mây được triển khai đầy đủ để quản lý máy ảnh bằng Cloud Functions cho Firebase và Cơ sở dữ liệu theo thời gian thực.

Mã khởi động chứa các ghi chú TODO cho biết vị trí bạn cần thêm hoặc thay đổi mã, chẳng hạn như ví dụ sau:

// TODO: Implement full SYNC response.

Tạo dự án Firebase

  1. Chuyển đến Firebase.
  2. Nhấp vào Tạo dự án rồi nhập tên dự án.
  3. Đánh dấu vào hộp đồng ý rồi nhấp vào Tiếp tục. Nếu không có hộp đánh dấu thoả thuận, bạn có thể bỏ qua bước này.
    Tạo dự án Firebase
  4. Sau khi tạo dự án Firebase, hãy tìm mã dự án. Chuyển đến phần Tổng quan về dự án rồi nhấp vào biểu tượng cài đặt > Cài đặt dự án.
    Mở phần cài đặt dự án
  5. Dự án của bạn được liệt kê trong thẻ Chung.
    Cài đặt chung của dự án

Kết nối với Firebase

  1. Chuyển đến thư mục camerastream-start rồi thiết lập Firebase CLI bằng dự án Hành động:
$ cd camerastream-start
$ firebase use <firebase-project-id>
  1. Trong thư mục camerastream-start, hãy chuyển đến thư mục functions rồi cài đặt tất cả các phần phụ thuộc cần thiết:
$ cd functions
$ npm install
  1. Nếu bạn thấy thông báo sau, hãy bỏ qua. Cảnh báo này là do các phần phụ thuộc cũ. Để biết thêm thông tin, hãy xem vấn đề này trên GitHub.
found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details
  1. Khởi chạy dự án Firebase:
$ firebase init
  1. Chọn HàmLưu trữ. Thao tác này sẽ khởi chạy các API và tính năng cần thiết cho dự án của bạn.
? 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. Định cấu hình Cloud Functions bằng các tệp mặc định và đảm bảo bạn không ghi đè các tệp index.jspackage.json hiện có trong mẫu dự án:
? 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. Định cấu hình tính năng Lưu trữ bằng thư mục public trong mã dự án và sử dụng tệp index.html hiện có:
? 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. Trao đổi tin nhắn Giao thức mô tả phiên (SDP)

Việc trao đổi thông báo SDP là một bước quan trọng trong việc thiết lập luồng WebRTC. SDP là một giao thức dựa trên văn bản mô tả các đặc điểm của một phiên đa phương tiện. Giao thức này được dùng trong WebRTC để đàm phán các tham số của kết nối ngang hàng, chẳng hạn như bộ mã hoá và giải mã được dùng, địa chỉ IP của người tham gia và cổng dùng để truyền tải nội dung nghe nhìn.

Để sử dụng Cơ sở dữ liệu theo thời gian thực làm máy chủ nhằm trao đổi thông điệp SDP giữa webcam và ứng dụng khách CameraStream cho nhà thông minh, hãy làm theo các bước sau:

  1. Trong bảng điều khiển của Firebase, hãy nhấp vào Tạo > Cơ sở dữ liệu theo thời gian thực > Tạo cơ sở dữ liệu.

Trang Cơ sở dữ liệu theo thời gian thực trong bảng điều khiển Firebase

  1. Trong trình đơn thả xuống Vị trí cơ sở dữ liệu theo thời gian thực, hãy chọn một vị trí thích hợp để lưu trữ cơ sở dữ liệu.

Trình đơn thả xuống vị trí Cơ sở dữ liệu theo thời gian thực trong hộp thoại Thiết lập cơ sở dữ liệu

  1. Chọn Bắt đầu ở chế độ thử nghiệm rồi nhấp vào Bật. Khi bật Cơ sở dữ liệu theo thời gian thực, bạn cần có khả năng tham chiếu cơ sở dữ liệu đó từ ứng dụng khách CameraStream.
  1. Trong bảng điều khiển của Firebase, hãy chọn 513f2be95dcd7896.png Cài đặt dự án > Cài đặt dự án > e584a9026e2b407f.pngThêm Firebase vào ứng dụng web của bạn để bắt đầu quy trình thiết lập.
  2. Nếu bạn đã thêm một ứng dụng vào dự án Firebase, hãy nhấp vào Thêm ứng dụng để hiển thị các tuỳ chọn nền tảng.
  3. Nhập biệt hiệu cho ứng dụng, chẳng hạn như My web app, rồi nhấp vào Đăng ký ứng dụng.
  4. Trong phần Thêm SDK Firebase, hãy chọn Sử dụng thẻ <script>.
  5. Sao chép các giá trị từ đối tượng firebasebaseConfig rồi dán các giá trị đó vào tệp camaerastream-start/public/webrtc_generator.js.
const firebaseConfig = {
  apiKey: "XXXXX",
  authDomain: "XXXXX",
  projectId: "XXXXX",
  storageBucket: "XXXXX",
  messagingSenderId: "XXXXX",
  appId: "XXXXX",
  measurementId: "XXXXX"
};
  1. Nhấp vào Tiếp tục đến bảng điều khiển để hoàn tất quy trình. Bạn sẽ thấy ứng dụng web mới tạo trên trang Cài đặt dự án.

4. Tạo máy ảnh WebRTC

Giờ đây, khi bạn đã định cấu hình Hành động, dịch vụ đám mây của bạn cần xử lý các ý định sau:

  • Ý định SYNC xảy ra khi Trợ lý muốn biết người dùng đã kết nối thiết bị nào. Thông báo này được gửi đến dịch vụ của bạn khi người dùng liên kết một tài khoản. Bạn nên phản hồi bằng tải trọng JSON của thiết bị và chức năng của người dùng.
  • Ý định EXECUTE/QUERY xảy ra khi Trợ lý muốn thay mặt người dùng kiểm soát một thiết bị. Bạn nên phản hồi bằng một tải trọng JSON có trạng thái thực thi của từng thiết bị được yêu cầu.

Trong phần này, bạn cập nhật các hàm mà bạn đã triển khai trước đó để xử lý các ý định này.

Cập nhật phản hồi SYNC

  1. Chuyển đến tệp functions/index.js. Tệp này chứa mã để phản hồi các yêu cầu của Trợ lý.
  2. Chỉnh sửa ý định SYNC để trả về siêu dữ liệu và chức năng của thiết bị:

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 chưa được xác định trong mã. Thêm nội dung sau vào const _ = require('underscore');:
// Hardcoded user ID
const USER_ID = '123';

Xử lý ý định EXECUTE

Ý định EXECUTE xử lý các lệnh để cập nhật trạng thái thiết bị. Phản hồi trả về trạng thái của từng lệnh (ví dụ: SUCCESS, ERROR hoặc PENDING) và trạng thái thiết bị mới.

Để xử lý ý định EXECUTE, hãy chỉnh sửa ý định EXECUTE để trả về điểm cuối signaling của dự án Firebase trong tệp 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],
    },
  };
});

Xử lý tính năng Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS)

Để xử lý CORS do sử dụng phương thức POST để gửi SDP, hãy thêm URL Lưu trữ Firebase vào mảng allowlist trong tệp functions/index.js:

index.js

'use strict';
.....

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

Để biết thêm thông tin về CORS, hãy xem bài viết Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS).

Xử lý việc chấm dứt luồng

Để xử lý việc chấm dứt luồng WebRTC, hãy thêm URL hàm "signaling" (gửi tín hiệu) của Firebase vào tệp 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();

Triển khai lên Firebase

Để triển khai cho Firebase, hãy triển khai phương thức thực hiện trên đám mây đã cập nhật bằng Firebase CLI:

$ firebase deploy

Lệnh này triển khai một ứng dụng web và một số Cloud Functions cho Firebase:

...

✔ Deploy complete!

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

Định cấu hình dự án trong Developer Console

  1. Chuyển đến Developer Console (Bảng điều khiển dành cho nhà phát triển).
  2. Nhấp vào Create Project (Tạo dự án), nhập tên cho dự án rồi nhấp vào Create Project (Tạo dự án).

Đặt tên dự án

Chọn chế độ tích hợp đám mây với đám mây

Trên trang Trang chủ dự án trong Developer Console, hãy chọn Thêm chế độ tích hợp đám mây với đám mây trong phần Đám mây với đám mây.

Thêm tính năng tích hợp từ đám mây sang đám mây

  1. Nhập tên tích hợp rồi chọn Máy ảnh trong phần Loại thiết bị. Tên này sẽ xuất hiện trong ứng dụng Google Home sau khi có thiết bị cần thiết lập. Đối với lớp học lập trình này, chúng tôi đã nhập Lớp học lập trình WebRTC làm tên hiển thị, nhưng bạn có thể sử dụng một tên khác.

Thêm tên hiển thị

  1. Trong phần Xây dựng thương hiệu ứng dụng, hãy tải tệp png lên cho biểu tượng ứng dụng, có kích thước 144 x 144 px và tên là .png.

Thêm biểu tượng ứng dụng

Bật tính năng liên kết tài khoản

Để bật tính năng liên kết tài khoản sau khi triển khai dự án, hãy làm theo các bước sau:

  1. Chuyển đến Developer Console (Bảng điều khiển dành cho nhà phát triển) rồi mở dự án.
  2. Trong mục Đám mây với đám mây, hãy nhấp vào Phát triển > Chỉnh sửa bên cạnh chế độ tích hợp.
  3. Trên trang Thiết lập và định cấu hình, hãy tìm mục Liên kết tài khoản rồi nhập thông tin sau vào các hộp văn bản tương ứng:

ID khách hàng

ABC123

Mật khẩu ứng dụng khách

DEF456

URL Uỷ quyền

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

URL mã thông báo

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

Cập nhật URL liên kết tài khoản

  1. Nhấp vào Lưu > Kiểm thử.

5. Kiểm thử máy ảnh WebRTC ảo

  1. Chuyển đến URL lưu trữ mà bạn thấy khi triển khai dự án Firebase. Bạn sẽ thấy giao diện sau đây, đó là ứng dụng khách CameraStream:

Giao diện ứng dụng máy khách CameraStream

  1. Trong bảng điều khiển Local Video Resolution (Độ phân giải video cục bộ), hãy chọn video bạn muốn.
  2. Cấp quyền cho ứng dụng khách CameraStream truy cập vào webcam và micrô của bạn. Một nguồn cấp dữ liệu video từ webcam của bạn sẽ xuất hiện trên ứng dụng.
  1. Trong ứng dụng Google Home, hãy nhấn vào Thêm > Hoạt động với Google.

Trang Thiết lập thiết bị trong ứng dụng Google Home

  1. Tìm Hành động mà bạn đã tạo rồi chọn hành động đó.

Hành động nhà thông minh trong ứng dụng Google Home

  1. Hãy ghi lại mã gồm 5 ký tự chữ và số duy nhất vì bạn sẽ cần mã này sau này.

Mã gồm 5 chữ số, gồm chữ và số, duy nhất

  1. Nhấn vào Đưa tôi quay lại. Camera WebRTC được thêm vào cấu trúc của bạn trong ứng dụng Google Home.

Bắt đầu luồng WebRTC

  1. Trên trang web của ứng dụng khách CameraStream, hãy nhập mã gồm chữ và số từ mục cuối cùng vào hộp văn bản Account linking token value (Giá trị mã thông báo liên kết tài khoản) rồi nhấp vào Submit (Gửi).

Hộp văn bản Giá trị mã thông báo liên kết tài khoản

  1. Để bắt đầu một phiên WebRTC từ thiết bị màn hình thông minh của Google, hãy làm theo một trong những cách sau:
  • Nói "Ok Google, truyền trực tuyến Máy ảnh WebRTC."
  • Trên thiết bị màn hình thông minh của Google, hãy nhấn vào Điều khiển nhà > Máy ảnh > Máy ảnh WebRTC.

Trong ứng dụng khách CameraStream của nhà thông minh của Google, bạn sẽ thấy Offer SPD và Answer SDP đã được tạo và trao đổi thành công. Hình ảnh từ webcam được truyền trực tuyến đến thiết bị màn hình thông minh của Google bằng WebRTC.

6. Xin chúc mừng

Xin chúc mừng! Bạn đã tìm hiểu cách truyền trực tuyến từ webcam đến thiết bị màn hình Google Nest bằng giao thức WebRTC.

Tìm hiểu thêm