偵測鏡頭轉換

鏡頭轉換分析功能會偵測影片中的鏡頭變換。

本節示範幾個分析影片中鏡頭轉換的方法。

以下範例示範如何對位於 Cloud Storage 的檔案執行鏡頭轉換的影片分析。

想要更深入瞭解?請參閱詳細的 Python 教學課程

REST

傳送影片註解要求

以下說明如何對 videos:annotate 方法傳送 POST 要求。這個範例使用 Google Cloud CLI 建立存取權杖。如需安裝 gcloud CLI 的操作說明,請參閱 Video Intelligence API 快速入門

使用任何要求資料之前,請先替換以下項目:

  • INPUT_URI:包含要註解檔案的 Cloud Storage bucket,包括檔案名稱。開頭必須為 gs://
  • PROJECT_NUMBER:專案的數值 ID Google Cloud

HTTP 方法和網址:

POST https://videointelligence.googleapis.com/v1/videos:annotate

JSON 要求主體:

{
    "inputUri": "INPUT_URI",
    "features": ["SHOT_CHANGE_DETECTION"]
}

如要傳送要求,請展開以下其中一個選項:

您應該會收到如下的 JSON 回應:

如果回應成功,Video Intelligence API 會傳回作業的 name。上文顯示這類回應的範例,其中 project-name 是專案名稱,而 operation-id 是為要求建立的長時間執行作業 ID。

  • PROJECT_NUMBER:專案編號
  • LOCATION_ID:應進行註解的雲端地區。支援的雲端區域包括:us-east1us-west1europe-west1asia-east1。如果沒有指定任何地區,則會依據影片檔案位置來決定地區。
  • OPERATION_ID:為要求建立的長時間執行作業 ID,並在您開始作業時提供於回應中,例如 12345....

取得註解結果

如要擷取作業結果,請使用從 videos:annotate 呼叫傳回的作業名稱,發出 GET 要求,如下列範例所示。

使用任何要求資料之前,請先替換以下項目:

  • OPERATION_NAME:Video Intelligence API 傳回的作業名稱。作業名稱的格式為 projects/PROJECT_NUMBER/locations/LOCATION_ID/operations/OPERATION_ID
  • PROJECT_NUMBER:專案的數值 ID Google Cloud

HTTP 方法和網址:

GET https://videointelligence.googleapis.com/v1/OPERATION_NAME

如要傳送要求,請展開以下其中一個選項:

您應該會收到如下的 JSON 回應:

鏡頭偵測註解會以 shotAnnotations 清單傳回。 注意:只有在 done 欄位的值為 True 時,系統才會傳回這個欄位。 如果作業未完成,則回應不會含有這個欄位。

下載註解結果

將註解從來源複製到目標值區:(請參閱「複製檔案和物件」)

gcloud storage cp gcs_uri gs://my-bucket

注意:如果輸出 GCS URI 是由使用者提供,註解就會儲存在該 GCS URI 中。

Go


func shotChangeURI(w io.Writer, file string) error {
	ctx := context.Background()
	client, err := video.NewClient(ctx)
	if err != nil {
		return err
	}
	defer client.Close()

	op, err := client.AnnotateVideo(ctx, &videopb.AnnotateVideoRequest{
		Features: []videopb.Feature{
			videopb.Feature_SHOT_CHANGE_DETECTION,
		},
		InputUri: file,
	})
	if err != nil {
		return err
	}
	resp, err := op.Wait(ctx)
	if err != nil {
		return err
	}

	// A single video was processed. Get the first result.
	result := resp.AnnotationResults[0].ShotAnnotations

	for _, shot := range result {
		start, _ := ptypes.Duration(shot.StartTimeOffset)
		end, _ := ptypes.Duration(shot.EndTimeOffset)

		fmt.Fprintf(w, "Shot: %s to %s\n", start, end)
	}

	return nil
}

Java

如要向 Video Intelligence 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

// Instantiate a com.google.cloud.videointelligence.v1.VideoIntelligenceServiceClient
try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) {
  // Provide path to file hosted on GCS as "gs://bucket-name/..."
  AnnotateVideoRequest request =
      AnnotateVideoRequest.newBuilder()
          .setInputUri(gcsUri)
          .addFeatures(Feature.SHOT_CHANGE_DETECTION)
          .build();

  // Create an operation that will contain the response when the operation completes.
  OperationFuture<AnnotateVideoResponse, AnnotateVideoProgress> response =
      client.annotateVideoAsync(request);

  System.out.println("Waiting for operation to complete...");
  // Print detected shot changes and their location ranges in the analyzed video.
  for (VideoAnnotationResults result : response.get().getAnnotationResultsList()) {
    if (result.getShotAnnotationsCount() > 0) {
      System.out.println("Shots: ");
      for (VideoSegment segment : result.getShotAnnotationsList()) {
        double startTime =
            segment.getStartTimeOffset().getSeconds()
                + segment.getStartTimeOffset().getNanos() / 1e9;
        double endTime =
            segment.getEndTimeOffset().getSeconds()
                + segment.getEndTimeOffset().getNanos() / 1e9;
        System.out.printf("Location: %.3f:%.3f\n", startTime, endTime);
      }
    } else {
      System.out.println("No shot changes detected in " + gcsUri);
    }
  }
}

Node.js

如要向 Video Intelligence 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

// Imports the Google Cloud Video Intelligence library
const video = require('@google-cloud/video-intelligence').v1;

// Creates a client
const client = new video.VideoIntelligenceServiceClient();

/**
 * TODO(developer): Uncomment the following line before running the sample.
 */
// const gcsUri = 'GCS URI of file to analyze, e.g. gs://my-bucket/my-video.mp4';

const request = {
  inputUri: gcsUri,
  features: ['SHOT_CHANGE_DETECTION'],
};

// Detects camera shot changes
const [operation] = await client.annotateVideo(request);
console.log('Waiting for operation to complete...');
const [operationResult] = await operation.promise();
// Gets shot changes
const shotChanges = operationResult.annotationResults[0].shotAnnotations;
console.log('Shot changes:');

if (shotChanges.length === 1) {
  console.log('The entire video is one shot.');
} else {
  shotChanges.forEach((shot, shotIdx) => {
    console.log(`Scene ${shotIdx} occurs from:`);
    if (shot.startTimeOffset === undefined) {
      shot.startTimeOffset = {};
    }
    if (shot.endTimeOffset === undefined) {
      shot.endTimeOffset = {};
    }
    if (shot.startTimeOffset.seconds === undefined) {
      shot.startTimeOffset.seconds = 0;
    }
    if (shot.startTimeOffset.nanos === undefined) {
      shot.startTimeOffset.nanos = 0;
    }
    if (shot.endTimeOffset.seconds === undefined) {
      shot.endTimeOffset.seconds = 0;
    }
    if (shot.endTimeOffset.nanos === undefined) {
      shot.endTimeOffset.nanos = 0;
    }
    console.log(
      `\tStart: ${shot.startTimeOffset.seconds}` +
        `.${(shot.startTimeOffset.nanos / 1e6).toFixed(0)}s`
    );
    console.log(
      `\tEnd: ${shot.endTimeOffset.seconds}.` +
        `${(shot.endTimeOffset.nanos / 1e6).toFixed(0)}s`
    );
  });
}

Python

如要進一步瞭解如何安裝及使用 Python 專用的 Video Intelligence API 用戶端程式庫,請參閱 Video Intelligence API 用戶端程式庫
"""Detects camera shot changes."""
video_client = videointelligence.VideoIntelligenceServiceClient()
features = [videointelligence.Feature.SHOT_CHANGE_DETECTION]
operation = video_client.annotate_video(
    request={"features": features, "input_uri": path}
)
print("\nProcessing video for shot change annotations:")

result = operation.result(timeout=90)
print("\nFinished processing.")

# first result is retrieved because a single video was processed
for i, shot in enumerate(result.annotation_results[0].shot_annotations):
    start_time = (
        shot.start_time_offset.seconds + shot.start_time_offset.microseconds / 1e6
    )
    end_time = (
        shot.end_time_offset.seconds + shot.end_time_offset.microseconds / 1e6
    )
    print("\tShot {}: {} to {}".format(i, start_time, end_time))

其他語言

C#: 請按照用戶端程式庫頁面上的 C# 設定說明操作, 然後參閱 .NET 適用的 Video Intelligence 參考說明文件

PHP: 請按照用戶端程式庫頁面的 PHP 設定說明 操作,然後前往 PHP 適用的 Video Intelligence 參考文件

Ruby: 請按照用戶端程式庫頁面的 Ruby 設定說明 操作,然後前往 Ruby 適用的 Video Intelligence 參考說明文件