使用 Video Intelligence API 和 Cloud Vision API 处理用户生成的内容(教程)

本教程介绍如何部署一组 Cloud Functions 函数,以便使用 Cloud Vision APICloud Video Intelligence API 处理图片和视频。使用 Video Intelligence API 和 Cloud Vision API 处理用户生成的内容中介绍了此功能。

请按照本教程部署该解决方案所需的 Cloud Functions 函数和其他 Google Cloud Platform (GCP) 组件。

目标

费用

本教程使用 Cloud Platform 的可计费组件,包括:

  • Cloud Functions
  • Cloud Pub/Sub
  • Cloud Storage
  • BigQuery
  • Vision API
  • Video Intelligence API

运行本教程的资源耗费在免费层级配额范围内。若不享受免费层级,则测试 10 张图片和 10 个视频的费用大约为 $5。请使用价格计算器根据您的预计使用情况来估算费用。Cloud Platform 新用户可能有资格免费试用

准备工作

  1. 创建 Google Cloud Platform (GCP) 项目,或使用现有项目。

    转到“项目”页面

  2. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  3. 启用 Cloud Functions, Cloud Storage, BigQuery, Vision, and Video Intelligence API。

    启用 API

  4. 安装并初始化 Google Cloud SDK

  5. 更新并安装 gcloud 组件:

    gcloud components update && gcloud components install beta
  6. 为 Node.js 开发准备好环境。

    转到设置指南

架构

下图展示了其概要架构:

概要架构

克隆 github 代码库

本教程中的所有 Cloud Functions 函数都可以在 GitHub 上找到。使用您选择的工具或使用以下命令从 GitHub 下载代码:

git clone https://github.com/GoogleCloudPlatform/cloud-functions-intelligentcontent-nodejs

创建 Cloud Storage 存储分区

Cloud Storage 存储分区为上传图片和视频提供存储位置。请按照以下步骤创建四个不同的 Cloud Storage 存储分区:

  1. 创建一个用于存储图片和视频文件的存储分区。将 [IV_BUCKET_NAME] 替换为有效的 Cloud Storage 存储分区名称

    gsutil mb [IV_BUCKET_NAME]
  2. 创建一个用于存储过滤后的图片和视频文件的存储分区。将 [FILTERED_BUCKET_NAME] 替换为有效的 Cloud Storage 存储分区名称。

    gsutil mb [FILTERED_BUCKET_NAME]
  3. 创建一个用于存储已标记图片和视频文件的存储分区。将 [FLAGGED_BUCKET_NAME] 替换为有效的 Cloud Storage 存储分区名称。

    gsutil mb [FLAGGED_BUCKET_NAME]
  4. 创建一个用作 Cloud Functions 函数暂存位置的存储分区。将 [STAGING_BUCKET_NAME] 替换为有效的 Cloud Storage 存储分区名称。

    gsutil mb [STAGING_BUCKET_NAME]

创建 Cloud Pub/Sub 主题

您可以使用 Cloud Pub/Sub 主题以处理 Cloud Storage 通知消息以及 Cloud Functions 函数之间的消息。

  1. 创建一个主题,以在您的某个文件上传到 Cloud Storage 时接收 Cloud Storage 通知。将 [UPLOAD_NOTIFICATION_TOPIC] 替换为有效的 Cloud Pub/Sub 主题名称

    gcloud pubsub topics create [UPLOAD_NOTIFICATION_TOPIC]
  2. 创建一个主题,以从 Vision API 接收消息。将 [VISION_TOPIC_NAME] 替换为有效的主题名称。config.json 文件中的默认值为 visionapiservice

    gcloud pubsub topics create [VISION_TOPIC_NAME]
  3. 创建一个主题,以从 Video Intelligence API 接收消息。将 [VIDEOIQ_TOPIC_NAME] 替换为有效的主题名称。config.json 文件中的默认值为 videointelligenceservice

    gcloud pubsub topics create [VIDEOIQ_TOPIC_NAME]
  4. 创建一个主题,以接收要存储在 BigQuery 中的消息。将 [BIGQUERY_TOPIC_NAME] 替换为有效的主题名称。config.json 文件中的默认值为 bqinsert

    gcloud pubsub topics create [BIGQUERY_TOPIC_NAME]

创建 Cloud Storage 通知

  1. 创建一个仅在某个新对象被放入 Cloud Storage 文件上传存储分区时会触发的通知。将 [UPLOAD_NOTIFICATION_TOPIC] 替换为您的主题,将 [IV_BUCKET] 替换为您的文件上传存储分区名称。

    gsutil notification create -t [UPLOAD_NOTIFICATION_TOPIC] -f json -e OBJECT_FINALIZE [IV_BUCKET_NAME]
  2. 确认已为存储分区创建了通知:

    gsutil notification list [IV_BUCKET_NAME]

    如果成功执行函数,生成的输出如下:

    Filters: Event Types: OBJECT_FINALIZE

创建 BigQuery 数据集和表

Vision API 和 Video Intelligence API 的结果存储在 BigQuery 中。

  1. 创建 BigQuery 数据集。将 [PROJECT_ID] 替换为您的项目 ID,将 [DATASET_ID] 替换为您的数据集名称。config.json 文件中的 [DATASET_ID] 默认值为 intelligentcontentfilter

    bq --project_id [PROJECT_ID] mk [DATASET_ID]
  2. 从架构文件创建 BigQuery 表。将 [PROJECT_ID] 替换为您的项目 ID,将 [DATASET_ID].[TABLE_NAME] 替换为您的数据集 ID 和表名称。config.json 文件中的 [DATASET_ID] 默认值为 intelligentcontentfilter[TABLE_NAME] 的默认值为 filtered_content

    bq --project_id [PROJECT_ID] mk --schema intelligent_content_bq_schema.json -t [DATASET_ID].[TABLE_NAME]
  3. 验证您的 BigQuery 表是否已创建。将 [PROJECT_ID] 替换为您的项目 ID,将 [DATASET_ID].[TABLE_NAME] 替换为您的数据集 ID 和表名称。

    bq --project_id [PROJECT_ID] show [DATASET_ID].[TABLE_NAME]

    生成的输出如下:

    BigQuery 表

部署 Cloud Functions 函数

下一步是部署 Cloud Functions 函数。

修改 JSON 配置文件

下载代码后,修改 config.json 文件以使用特定的 Cloud Storage 存储分区、Cloud Pub/Sub 主题名称以及 BigQuery 数据集 ID 和表名称。

{
  "VISION_TOPIC": "projects/[PROJECT-ID]/topics/visionapiservice",
  "VIDEOINTELLIGENCE_TOPIC": "projects/[PROJECT-ID]/topics/videointelligenceservice",
  "BIGQUERY_TOPIC": "projects/[PROJECT-ID]/topics/bqinsert",
  "REJECTED_BUCKET": "[FLAGGED_BUCKET_NAME]",
  "RESULT_BUCKET": "[FILTERED_BUCKET_NAME]",
  "DATASET_ID": "[DATASET_ID]",
  "TABLE_NAME": "[TABLE_NAME]",
  "GCS_AUTH_BROWSER_URL_BASE": "https://storage.cloud.google.com/" ,
  "API_Constants": {
  	"ADULT" : "adult",
  	"VIOLENCE" : "violence",
  	"SPOOF" : "spoof",
  	"MEDICAL" : "medical"
  }
}

部署 GCStoPubsub 函数

部署 GCStoPubsub Cloud Functions 函数,其中包含从 Cloud Pub/Sub 接收 Cloud Storage 通知消息,并使用另一个 Cloud Pub/Sub 消息将该消息转发给合适的函数的逻辑。

  • [STAGING_BUCKET_NAME] 替换为 Cloud Storage 暂存存储分区名称,将 [UPLOAD_NOTIIFICATION_TOPIC] 替换为文件上传通知主题名称。

    gcloud functions deploy GCStoPubsub --stage-bucket [STAGING_BUCKET_NAME] --trigger-topic [UPLOAD_NOTIIFICATION_TOPIC] --entry-point GCStoPubsub

对于每个 Cloud Functions 函数,命令行输出类似于以下内容:

Copying file:///var/folders/69/wsyfjkld5fq1w_wf7d5pxbv80030br/T/tmphzfCsc/fun.zip [Content-Type=application/zip]...
/ [1 files][138.4 KiB/138.4 KiB]
Operation completed over 1 objects/138.4 KiB.
Deploying function (may take a while - up to 2 minutes)...
...............................................................done.
availableMemoryMb: 256
entryPoint: GCStoPubsub
eventTrigger:
  eventType: providers/cloud.pubsub/eventTypes/topic.publish
  failurePolicy: {}
  resource: projects/[PROJECT-ID]/topics/intelligentcontentfileupload
latestOperation: operations/c2VjcmV0LXplcGh5ci0xMTIxL3VzLWNlbnRyYWwxL0dDU3RvUHVic3ViL0tRaGxHeVFhZHdR
name: projects/[PROJECT-ID]/locations/us-central1/functions/GCStoPubsub
serviceAccount: [PROJECT-ID]@appspot.gserviceaccount.com
sourceArchiveUrl: gs://[STAGING_BUCKET_NAME]/us-central1-GCStoPubsub-bnnmzdzqtjoo.zip
status: READY
timeout: 60s
updateTime: '2017-09-01T14:59:03Z'
versionId: '01'

部署 visionAPI 函数

  • 部署您的 visionAPI Cloud Functions 函数,其中包含使用 Cloud Pub/Sub 接收消息、调用 Vision API,并使用另一个 Cloud Pub/Sub 消息将该消息转发到 insertIntoBigQuery Cloud Functions 函数的逻辑。将 [STAGING_BUCKET_NAME] 替换为您的 Cloud Storage 暂存存储分区名称,将 [VISION_TOPIC_NAME] 替换为您的 Vision API 主题名称。

    gcloud functions deploy visionAPI --stage-bucket [STAGING_BUCKET_NAME] --trigger-topic [VISION_TOPIC_NAME] --entry-point visionAPI

部署 videoIntelligenceAPI 函数

  • 部署您的 videoIntelligenceAPI Cloud Functions 函数,其中包含使用 Cloud Pub/Sub 接收消息、调用 Video Intelligence API,并使用另一个 Cloud Pub/Sub 消息将该消息转发到 insertIntoBigQuery Cloud Functions 函数的逻辑。将 [STAGING_BUCKET_NAME] 替换为您的 Cloud Storage 暂存存储分区名称,将 [VIDEOIQ_TOPIC_NAME] 替换为您的 Video Intelligence API 主题名称。

    gcloud functions deploy videoIntelligenceAPI --stage-bucket [STAGING_BUCKET_NAME] --trigger-topic [VIDEOIQ_TOPIC_NAME] --entry-point videoIntelligenceAPI --timeout 540

部署 insertIntoBigQuery 函数

  • 部署 insertIntoBigQuery Cloud Functions 函数,其中包含使用 Cloud Pub/Sub 接收消息,并调用 BigQuery API 将数据插入 BigQuery 表的逻辑。将 [STAGING_BUCKET_NAME] 替换为您的 Cloud Storage 暂存存储分区名称,将 [BIGQUERY_TOPIC_NAME] 替换为您的 BigQuery 主题名称。

    gcloud functions deploy insertIntoBigQuery --stage-bucket [STAGING_BUCKET_NAME] --trigger-topic [BIGQUERY_TOPIC_NAME] --entry-point insertIntoBigQuery

测试流

下图展示了处理流。

processing-flow

您可以通过将文件上传到 Cloud Storage、检查日志以及在 BigQuery 中查看结果来测试该处理流程。

  1. 将图片和视频文件上传到 [IV_BUCKET_NAME],其中 [LOCAL_FILE_NAME] 是文件名。

    gsutil cp [LOCAL_FILE_NAME] [IV_BUCKET_NAME]
  2. 通过查看 Cloud Logging 中捕获的 Cloud Functions 日志,验证您的 Cloud Functions 函数是否已触发并成功运行:

    1. 测试 GCStoPubsub

      gcloud functions logs read --filter "finished with status" "GCStoPubsub" --limit 100

      生成的输出如下:

      GCStoPubsub 日志

    2. 测试 insertIntoBigQuery

      gcloud functions logs read --filter "finished with status" "insertIntoBigQuery" --limit 100

      生成的输出如下:

      insertIntoBigQuery 日志

  3. 创建 SQL 命令以查询 BigQuery。将 [PROJECT_ID][DATASET_ID][TABLE_NAME] 分别替换为您的项目 ID、数据集 ID 和 BigQuery 表名称。

    echo "
    #standardSql
    SELECT insertTimestamp,
    contentUrl,
    flattenedSafeSearch.flaggedType,
    flattenedSafeSearch.likelihood
    FROM \`${PROJECT_ID}.${DATASET_ID}.${TABLE_NAME}\`
    CROSS JOIN UNNEST(safeSearch) AS flattenedSafeSearch
    ORDER BY insertTimestamp DESC,
    contentUrl,
    flattenedSafeSearch.flaggedType
    LIMIT 1000
    " > sql.txt
    
  4. 使用以下命令查看 BigQuery 结果:

    bq --project_id [PROJECT_ID] query < sql.txt

    生成的输出如下:

    BigQuery 结果

    或者,您可以登录 BigQuery 网页界面并运行查询:

    1. 在浏览器中打开 https://bigquery.cloud.google.com
    2. 点击编写查询以开始查询,如下所示:

      编写查询

    3. 在文本框中输入以下 SQL。将 [PROJECT_ID][DATASET_ID][TABLE_NAME] 分别替换为您的项目 ID、数据集 ID 和 BigQuery 表名称。

      #standardSql
      SELECT insertTimestamp,
      contentUrl,
      flattenedSafeSearch.flaggedType,
      flattenedSafeSearch.likelihood
      FROM `[PROJECT_ID].[DATASET_ID].[TABLE_NAME]`
      CROSS JOIN UNNEST(safeSearch) AS flattenedSafeSearch
      ORDER BY insertTimestamp DESC,
      contentUrl,
      flattenedSafeSearch.flaggedType
      LIMIT 1000
      

      以下示例展示了此 SQL 在界面中的外观:

      SQL 查询

      生成的输出如下:

      SQL 查询结果

清理

为避免因本教程中使用的资源而导致您的 Google Cloud Platform 帐号产生费用,请执行以下操作:

学完当前教程后,您可以清理在 Google Cloud 上创建的资源,以免这些资源占用配额,日后产生费用。以下部分介绍如何删除或关闭这些资源。

删除项目

为避免支付费用,最简单的方法是删除您为本教程创建的项目。

如需删除项目,请执行以下操作:

  1. 在 Cloud Console 中,转到项目页面。
  2. 在项目列表中,选择要删除的项目,然后点击删除项目
  3. 在对话框中,输入项目 ID,然后点击关闭

删除所有组件

  1. 删除 Cloud Functions 函数:

    gcloud functions delete GCStoPubsub
    gcloud functions delete visionAPI
    gcloud functions delete videoIntelligenceAPI
    gcloud functions delete insertIntoBigQuery
  2. 删除 BigQuery 表和数据集,用您的值替换变量:

    bq --project_id [PROJECT_ID] rm -r -f [DATASET_ID]
  3. 删除 Cloud Storage 存储分区,用您的值替换变量:

    gsutil -m rm -r [IV_BUCKET_NAME]
    gsutil -m rm -r [FLAGGED_BUCKET_NAME]
    gsutil -m rm -r [FILTERED_BUCKET_NAME]
    gsutil -m rm -r [STAGING_BUCKET_NAME]
  4. 删除 Cloud Pub/Sub 主题,用您的值替换变量:

    gcloud pubsub topics delete [UPLOAD_NOTIFICATION_TOPIC]
    gcloud pubsub topics delete [VISION_TOPIC_NAME]
    gcloud pubsub topics delete [VIDEOIQ_TOPIC_NAME]
    gcloud pubsub topics delete [BIGQUERY_TOPIC_NAME]

后续步骤