使用 Python 和 Google Meet REST API 觀察會議事件

本教學課程將示範如何使用 Google Meet REST API 和 透過 Google Workspace Events API 和 Google Cloud Pub/Sub 觀察事件並做出回應 在 Meet 會議空間中。範例應用程式會將 會議開始和結束、參與者加入或離開的時間,以及何時決定 並取得預先產生的會議成果

您可以訂閱 Meet 使用者,接收該使用者擁有或發起的任何會議空間的活動,而非訂閱特定會議空間。詳情請參閱 訂閱 Google Meet 活動

必要條件

如果您需要為貴機構啟用下列任何必要條件,請請求 Google Workspace 管理員啟用這些條件:

準備環境

本節說明如何建立及設定本機環境,以及 用於這個教學課程的 Google Cloud 專案

建立工作目錄和 Python 虛擬環境

如何建立並啟用新的虛擬帳號 環境,請在下列項目中執行 指令。

Linux/macOS

mkdir meet-tutorial
cd meet-tutorial
python3 -mvenv env
source env/bin/activate

Windows (命令提示字元)

mkdir meet-tutorial
cd meet-tutorial
python3 -mvenv env
env/bin/activate.bat

Windows (PowerShell)

mkdir meet-tutorial
cd meet-tutorial
python3 -mvenv env
env/bin/activate.ps1

建立 Google Cloud 專案

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,前往「選單」圖示 > IAM 與管理員 > 建立專案

    前往「建立專案」

  2. 在「Project Name」(專案名稱) 欄位,輸入專案的描述性名稱。

    選用:如要編輯「專案 ID」,請按一下「編輯」。無法變更專案 ID 因此請在專案建立後根據 專案。

  3. 按一下「地區」欄位中的「瀏覽」,即可查看可能的地理位置 專案。然後按一下「選取」
  4. 點選「建立」。Google Cloud 控制台前往「資訊主頁」頁面,已建立專案 幾分鐘內

gcloud CLI

在下列任一開發環境中,存取 Google Cloud CLI (`gcloud`):

  • Cloud Shell:如要使用已設定 gcloud CLI 的線上終端機,請啟用 Cloud Shell。
    啟用 Cloud Shell
  • Local Shell:如要使用本機開發環境, 安裝初始化 使用 gcloud CLI
    如要建立 Cloud 專案,請使用「gcloud projects create」指令:
    gcloud projects create PROJECT_ID
    敬上 設定您要建立的專案 ID,以取代 PROJECT_ID

啟用 Google Cloud 專案的計費功能

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,前往「Billing」。按一下 選單 > 帳單 >「我的專案」

    前往「我的專案帳單」頁面

  2. 在「選取機構」中,選擇相關聯的機構 管理 Google Cloud 專案
  3. 在專案列中,開啟「動作」選單 (), 按一下 [變更帳單],然後選擇 Cloud Billing 帳戶。
  4. 按一下 [設定帳戶]

gcloud CLI

  1. 如要列出可用的帳單帳戶,請執行:
    gcloud billing accounts list
  2. 將帳單帳戶連結至 Google Cloud 專案:
    gcloud billing projects link PROJECT_ID --billing-account=BILLING_ACCOUNT_ID

    更改下列內容:

    • PROJECT_ID 是您要啟用計費功能的 Cloud 專案的 專案 ID
    • BILLING_ACCOUNT_ID 是要連結的帳單帳戶 ID 套用配額

設定驗證與授權

通過驗證及授權後,應用程式就能存取 Meet REST API 再複習一下,機構節點 是所有 Google Cloud Platform 資源的根節點需要使用者授權才能呼叫 Meet REST API。 本節將說明如何設定使用者憑證和要求 或授權。

設定 OAuth 同意畫面並選擇範圍

以下步驟會提供建議的預留位置資訊,協助您設定應用程式的 OAuth 同意畫面。請在將應用程式發布至外部之前,更新這項資訊。

  1. 在 Google Cloud 控制台中,前往「選單」圖示 > API 與服務 >「OAuth 同意畫面」

    前往 OAuth 同意畫面

  2. 在「使用者類型」下方選取「內部」,然後點選「建立」
  3. 在「App name」(應用程式名稱) 中輸入 Meet REST API Tutorial
  4. 填寫應用程式註冊表單,然後按一下「Save and Continue」
  5. 按一下「新增或移除範圍」。畫面上會顯示包含範圍清單的面板 。
  6. 在「手動新增範圍」下方,貼上下列範圍:
    • https://www.googleapis.com/auth/meetings.space.created
  7. 按一下「新增至資料表」
  8. 按一下「更新」
  9. 選取需要的範圍後 請按一下「儲存並繼續」
  10. 如果您選取的使用者類型為「外部」,請新增測試使用者:
    1. 在「測試使用者」下方,按一下「新增使用者」
    2. 輸入您的電子郵件地址和其他任何授權測試使用者,然後按一下 儲存並繼續
  11. 查看應用程式註冊摘要。如要修改資訊,請按一下「編輯」。如果應用程式 註冊看起來沒有問題,請按一下 [返回資訊主頁]

建立用戶端 ID

用戶端 ID 在 OAuth 2.0 期間可做為應用程式的憑證 流程由於應用程式在本機執行,因此請建立電腦用戶端 ID。

  1. 在 Google Cloud 控制台中,依序點選「選單」圖示 > 「API 與」「服務」 >「憑證」

    前往「憑證」

  2. 依序按一下「建立憑證」>「OAuth 用戶端 ID」
  3. 依序按一下「應用程式類型」>「電腦版應用程式」
  4. 在「名稱」欄位中輸入憑證的名稱。這個名稱只會顯示在 Google Cloud 控制台中。
  5. 點選「建立」。系統會顯示「OAuth client created」(已建立 OAuth 用戶端) 畫面,其中顯示新的用戶端 ID 和用戶端密碼。
  6. 按一下「OK」(確定)。新建立的憑證會顯示在「OAuth 2.0 用戶端 ID」之下。

安裝 Google Auth 程式庫

安裝 Google 驗證程式庫:

pip install google-auth google-auth-oauthlib

執行授權

Meet REST API 需要使用者憑證,格式為 OAuth 2.0 存取權杖在本節中,您將實作 OAuth 2.0 流程以要求 使用者的存取權杖和更新權杖。

  1. 在工作目錄中,建立 main.py 檔案並新增下列內容 內容:

    import os
    import json
    
    from google.auth.transport import requests
    from google.oauth2.credentials import Credentials
    from google_auth_oauthlib.flow import InstalledAppFlow
    
    def authorize() -> Credentials:
        """Ensure valid credentials for calling the Meet REST API."""
        CLIENT_SECRET_FILE = "./client_secret.json"
        credentials = None
    
        if os.path.exists('token.json'):
            credentials = Credentials.from_authorized_user_file('token.json')
    
        if credentials is None:
            flow = InstalledAppFlow.from_client_secrets_file(
                CLIENT_SECRET_FILE,
                scopes=[
                    'https://www.googleapis.com/auth/meetings.space.created',
                ])
            flow.run_local_server(port=0)
            credentials = flow.credentials
    
        if credentials and credentials.expired:
            credentials.refresh(requests.Request())
    
        if credentials is not None:
            with open("token.json", "w") as f:
                f.write(credentials.to_json())
    
        return credentials
    
    USER_CREDENTIALS = authorize()
    
  2. 如要執行程式碼,用戶端 ID 和稍早建立的密鑰都在 這通常代表交易 不會十分要求關聯語意將下載的用戶端密鑰檔案複製到正常運作的專案 並重新命名為 client_secret.json

  3. 如果您想要測試授權的運作方式,請執行下列指令。 應用程式會提示授權,並在token.json 專案工作目錄

    python3 main.py

新增 Meet REST API

授權碼完成後,即可啟用授權並呼叫 認識 REST API。

啟用 API

雖然本節的重點放在 Meet REST API,但本教學課程也會使用 Google Cloud Pub/Sub 和 Google Workspace Events API。

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,啟用 Google Meet REST API、 Google Workspace Events API 和 Google Cloud Pub/Sub。

    啟用 API

  2. 確認您已在正確的位置啟用 API Cloud 專案,然後點選「下一步」

  3. 確認您要啟用的 API 正確無誤,然後按一下「啟用」

gcloud CLI

  1. 如有必要,請將目前的 Cloud 專案設為您使用 gcloud config set project 指令建立的專案:

    gcloud config set project PROJECT_ID

    PROJECT_ID 替換為以下專案的專案 ID: 您建立的 Cloud 專案

  2. 啟用 Google Meet REST API、Google Workspace Events API 和 使用 gcloud services enable 指令的 Google Cloud Pub/Sub:

    gcloud services enable meet.googleapis.com workspaceevents.googleapis.com pubsub.googleapis.com

安裝 Meet REST API 用戶端程式庫

請按照下列步驟安裝 Meet REST API 用戶端程式庫:

  1. 執行下列指令:

    pip install google-apps-meet
  2. 編輯 main.py 檔案以匯入用戶端:

    from google.apps import meet_v2 as meet
    

建立聊天室

現在 Meet REST API 已可供使用,請定義函式以建立 會議空間

編輯 main.py 並新增:

def create_space() -> meet.Space:
    """Create a meeting space."""
    client = meet.SpacesServiceClient(credentials=USER_CREDENTIALS)
    request = meet.CreateSpaceRequest()
    return client.create_space(request=request)

訂閱事件

如要接收會議空間的相關活動,請使用 Google Workspace 事件 API。您還必須建立並訂閱 Google Cloud Pub/Sub 主題,會做為通知端點 接收事件。

設定 Google Cloud Pub/Sub

如要建立及訂閱 Pub/Sub 主題,請按照下列步驟操作:

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,前往「選單」圖示 > Pub/Sub

    前往「Pub/Sub」頁面

    確認已選取應用程式的 Cloud 專案。

  2. 按一下「」(建立主題),然後執行下列操作: 包括:
    1. 輸入 workspace-events 做為主題名稱。
    2. 保持選取「新增預設訂閱項目」
    3. 點選「建立」。完整主題名稱的格式為 projects/{project}/topics/{topic}。建立記事 以在後續步驟中使用。
  3. 授予將 Pub/Sub 訊息發布至主題的權限:
    1. 在側邊面板中,開啟 「權限」分頁。
    2. 按一下「新增主體」
    3. 在「New principals」(新增主體) 中輸入 meet-api-event-push@system.gserviceaccount.com
    4. 在「指派角色」中,選取 Pub/Sub Publisher
    5. 按一下 [儲存]

    系統可能需要幾分鐘的時間才能更新主題的權限。

gcloud CLI

  1. 在 Cloud 專案中,執行下列指令來建立主題:
    gcloud pubsub topics create workspace-events

    輸出結果會顯示完整的主題名稱,格式為 projects/{project}/topics/{topic}。請記下這個名稱,以便在後續步驟中使用。

  2. 授予將訊息發布至主題的權限:
     gcloud pubsub topics add-iam-policy-binding workspace-events --member='serviceAccount:meet-api-event-push@system.gserviceaccount.com' --role='roles/pubsub.publisher'

    系統可能需要幾分鐘的時間才能更新主題的權限。

  3. 為主題建立 Pub/Sub 訂閱項目:
    gcloud pubsub subscriptions create workspace-events-sub --topic=TOPIC_NAME

    更改下列內容:

    • TOPIC_NAME:您建立的主題名稱

請記下主題名稱,並確認 {project} 的值為 應用程式的 Cloud 專案 ID。您將會使用主題名稱來建立 Google Workspace 日後訂閱。

建立服務帳戶

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,前往「選單」圖示 > IAM 與管理員 >「服務帳戶」

    前往「Service Accounts」(服務帳戶) 頁面

  2. 按一下「建立服務帳戶」
  3. 填寫服務帳戶詳細資料,然後按一下「建立並繼續」。 注意:根據預設,Google 會建立不重複的服務帳戶 ID。
  4. 選用:為服務帳戶指派角色,授予 Google Cloud 專案資源的存取權。詳情請參閱「授予、變更及撤銷資源的存取權」。
  5. 按一下「繼續」
  6. 選用:輸入可以透過這個服務帳戶管理及執行動作的使用者或群組。詳情請參閱「管理服務帳戶模擬功能」。
  7. 按一下 [完成]。請記下服務帳戶的電子郵件地址。

gcloud CLI

  1. 建立服務帳戶:
    gcloud iam service-accounts create meet-event-listener \
      --display-name="meet-event-listener"
  2. 選用:為服務帳戶指派角色,授予 Google Cloud 專案資源的存取權。詳情請參閱「授予、變更及撤銷資源的存取權」。

使用服務帳戶

建立服務帳戶後,請授予自己模擬服務帳戶的權限 新建立的服務帳戶

Google Cloud 控制台

  1. 在新建立的服務帳戶「Actions」欄中,依序點選 >「Manage permissions」
  2. 按一下「新增金鑰」。 >>「授予存取權」
  3. 在「新增主體」下方輸入您的電子郵件地址。
  4. 依序選取「Service accounts」(服務帳戶) >>「Service Account Token Creator」(服務帳戶權杖建立者) 做為角色
  5. 按一下 [儲存]
  6. 返回終端機,然後使用 gcloud 登入,將應用程式預設憑證設為 新建立的服務帳戶系統提示您進行授權時,使用相同的登入電子郵件地址 帳戶。
    gcloud auth application-default login --impersonate-service-account=SERVICE_ACCOUNT_EMAIL

gcloud CLI

  1. 如要新增權限,請執行 gcloud iam service-accounts add-iam-policy-binding 使用服務帳戶和使用者的電子郵件地址
    gcloud iam service-accounts add-iam-policy-binding \
      SERVICE_ACCOUNT_EMAIL \
      --member="user:YOUR_EMAIL \
      --role="roles/iam.serviceAccountTokenCreator"
  2. 登入即可將應用程式預設憑證設為 新建立的服務帳戶系統提示授權時,請使用先前步驟中使用的帳戶登入。
    gcloud auth application-default login --impersonate-service-account=SERVICE_ACCOUNT_EMAIL

安裝 Pub/Sub 用戶端程式庫

  1. 使用 pip 安裝 Pub/Sub 的用戶端程式庫:

    pip install google-cloud-pubsub
  2. 然後編輯 main.py 以匯入用戶端:

    from google.cloud import pubsub_v1
    

建立 Google Workspace 訂閱方案

將以下程式碼加入 main.py 以定義訂閱的方法 Meet 活動。這段程式碼會訂閱會議空間的所有事件。訂閱後,事件會發布至 Pub/Sub 主題。

def subscribe_to_space(space_name: str = None, topic_name: str = None):
    """Subscribe to events for a meeting space."""
    session = requests.AuthorizedSession(USER_CREDENTIALS)
    body = {
        'targetResource': f"//meet.googleapis.com/{space_name}",
        "eventTypes": [
            "google.workspace.meet.conference.v2.started",
            "google.workspace.meet.conference.v2.ended",
            "google.workspace.meet.participant.v2.joined",
            "google.workspace.meet.participant.v2.left",
            "google.workspace.meet.recording.v2.fileGenerated",
            "google.workspace.meet.transcript.v2.fileGenerated",
        ],
        "payloadOptions": {
            "includeResource": False,
        },
        "notificationEndpoint": {
            "pubsubTopic": topic_name
        },
        "ttl": "86400s",
    }
    response = session.post("https://workspaceevents.googleapis.com/v1/subscriptions", json=body)
    return response

接著,請新增對應的程式碼,以便擷取及處理事件。

監聽及處理事件

繼續編輯 main.py,並新增下列程式碼範例。這組代碼 實作接收端,並使用 Google Cloud Pub/Sub API 來提取 發布活動消息各種處理常式方法會列印資訊 關於相應的事件

def format_participant(participant: meet.Participant) -> str:
    """Formats a participant for display on the console."""
    if participant.anonymous_user:
        return f"{participant.anonymous_user.display_name} (Anonymous)"

    if participant.signedin_user:
        return f"{participant.signedin_user.display_name} (ID: {participant.signedin_user.user})"

    if participant.phone_user:
        return f"{participant.phone_user.display_name} (Phone)"

    return "Unknown participant"


def fetch_participant_from_session(session_name: str) -> meet.Participant:
    """Fetches the participant for a session."""
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    # Use the parent path of the session to fetch the participant details
    parsed_session_path = client.parse_participant_session_path(session_name)
    participant_resource_name = client.participant_path(
        parsed_session_path["conference_record"],
        parsed_session_path["participant"])
    return client.get_participant(name=participant_resource_name)


def on_conference_started(message: pubsub_v1.subscriber.message.Message):
    """Display information about a conference when started."""
    payload = json.loads(message.data)
    resource_name = payload.get("conferenceRecord").get("name")
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    conference = client.get_conference_record(name=resource_name)
    print(f"Conference (ID {conference.name}) started at {conference.start_time.rfc3339()}")


def on_conference_ended(message: pubsub_v1.subscriber.message.Message):
    """Display information about a conference when ended."""
    payload = json.loads(message.data)
    resource_name = payload.get("conferenceRecord").get("name")
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    conference = client.get_conference_record(name=resource_name)
    print(f"Conference (ID {conference.name}) ended at {conference.end_time.rfc3339()}")


def on_participant_joined(message: pubsub_v1.subscriber.message.Message):
    """Display information about a participant when they join a meeting."""
    payload = json.loads(message.data)
    resource_name = payload.get("participantSession").get("name")
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    session = client.get_participant_session(name=resource_name)
    participant = fetch_participant_from_session(resource_name)
    display_name = format_participant(participant)
    print(f"{display_name} joined at {session.start_time.rfc3339()}")


def on_participant_left(message: pubsub_v1.subscriber.message.Message):
    """Display information about a participant when they leave a meeting."""
    payload = json.loads(message.data)
    resource_name = payload.get("participantSession").get("name")
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    session = client.get_participant_session(name=resource_name)
    participant = fetch_participant_from_session(resource_name)
    display_name = format_participant(participant)
    print(f"{display_name} left at {session.end_time.rfc3339()}")


def on_recording_ready(message: pubsub_v1.subscriber.message.Message):
    """Display information about a recorded meeting when artifact is ready."""
    payload = json.loads(message.data)
    resource_name = payload.get("recording").get("name")
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    recording = client.get_recording(name=resource_name)
    print(f"Recording available at {recording.drive_destination.export_uri}")


def on_transcript_ready(message: pubsub_v1.subscriber.message.Message):
    """Display information about a meeting transcript when artifact is ready."""
    payload = json.loads(message.data)
    resource_name = payload.get("transcript").get("name")
    client = meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)
    transcript = client.get_transcript(name=resource_name)
    print(f"Transcript available at {transcript.docs_destination.export_uri}")


def on_message(message: pubsub_v1.subscriber.message.Message) -> None:
    """Handles an incoming event from the Google Cloud Pub/Sub API."""
    event_type = message.attributes.get("ce-type")
    handler = {
        "google.workspace.meet.conference.v2.started": on_conference_started,
        "google.workspace.meet.conference.v2.ended": on_conference_ended,
        "google.workspace.meet.participant.v2.joined": on_participant_joined,
        "google.workspace.meet.participant.v2.left": on_participant_left,
        "google.workspace.meet.recording.v2.fileGenerated": on_recording_ready,
        "google.workspace.meet.transcript.v2.fileGenerated": on_transcript_ready,
    }.get(event_type)

    try:
        if handler is not None:
            handler(message)
        message.ack()
    except Exception as error:
        print("Unable to process event")
        print(error)


def listen_for_events(subscription_name: str = None):
    """Subscribe to events on the subscription."""
    subscriber = pubsub_v1.SubscriberClient()
    with subscriber:
        future = subscriber.subscribe(subscription_name, callback=on_message)
        print("Listening for events")
        try:
            future.result()
        except KeyboardInterrupt:
            future.cancel()
    print("Done")

完成程式碼

main.py 中加入以下程式碼,即可呼叫建立聊天室的方法。 訂閱事件及監聽更新 TOPIC_NAME 和專屬於您主題的 SUBSCRIPTION_NAME 常數 和訂閱項目名稱 已建立。

  1. 將程式碼新增至 main.py

    space = create_space()
    print(f"Join the meeting at {space.meeting_uri}")
    
    TOPIC_NAME = "projects/PROJECT_ID/topics/TOPIC_ID"
    SUBSCRIPTION_NAME = "projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID"
    
    subscription = subscribe_to_space(topic_name=TOPIC_NAME, space_name=space.name)
    listen_for_events(subscription_name=SUBSCRIPTION_NAME)
    

    更改下列內容:

    • PROJECT_ID: 例如 my-sample-project-191923

    • TOPIC_ID:您在 Cloud 專案中建立的 Pub/Sub 主題名稱。

    • SUBSCRIPTION_ID:訂閱項目的名稱,例如 使用 workspace-events-sub

  2. 執行程式:

    python3 main.py

如果您之前未曾執行該程式,則程式會提示您授權 一切都是從 0 開始將存取權授予應用程式,以便呼叫 Meet REST API。 程式成功執行後,您應該會看到類似下方的輸出內容:

Join the meeting at https://meet.google.com/abc-mnop-xyz

加入會議

如要產生應用程式活動,請透過網址加入會議 。加入後,您可以嘗試以下動作, 觸發事件:

  • 離開會議再重新加入。
  • 邀請其他人,或使用手機撥入會議。
  • 啟用錄音和轉錄稿功能。

每項活動都會產生事件,應用程式會接收並記錄至 Google Cloud 控制台。

完成後,請使用 ctrl-c 中斷程式。

選用:可嘗試的其他步驟

應用程式會記錄事件的基本詳細資料。如要繼續探索 Meet REST API,請嘗試修改應用程式,以執行這些額外的 動作。

選用:清除

避免系統向您的 Google Cloud 控制台帳戶收取資源費用 我們建議您清除所用資源 已建立。

如要刪除訂閱項目:

控制台

  1. 在 Google Cloud 控制台中,依序前往「Menu」 >「Pub/Sub」 >「Subscriptions」

    前往「訂閱項目」頁面

  2. 選取訂閱,然後點選 其他動作

  3. 按一下 [Delete] (刪除),畫面上會顯示「刪除訂閱項目」視窗。

  4. 按一下「刪除」。

gcloud CLI

  1. 刪除訂閱項目:

    gcloud pubsub subscriptions delete SUBSCRIPTION_NAME

如要刪除主題:

控制台

  1. 前往 Google Cloud 控制台中的「選單」 > Pub/Sub > 主題

    前往「主題」

  2. 選取主題並按一下 其他動作

  3. 按一下 [Delete] (刪除),畫面上會顯示「刪除主題」視窗。

  4. 輸入 delete,然後按一下「Delete」(刪除)

gcloud CLI

  1. 刪除主題:

    gcloud pubsub topics delete TOPIC_NAME

如要刪除專案,請進行以下操作:

控制台

  1. 在 Google Cloud 控制台中,前往「管理資源」頁面。按一下 選單 > IAM 與管理員 >「管理資源」

    前往 Resource Manager

  2. 在專案清單中選取要刪除的專案,然後按一下 刪除
  3. 在對話方塊中輸入專案 ID,然後按一下「Shut down」(關閉) 即可刪除 專案。

gcloud CLI

  1. 如要刪除專案,請使用 gcloud projects 刪除 指令:

    gcloud projects delete PROJECT_ID