오버레이 만들기

이 페이지에서는 트랜스코딩된 동영상에 오버레이를 삽입하는 방법을 설명합니다. 오버레이는 출력 동영상 위에 삽입되는 이미지로 구성되며 선택적으로 특정 기간 동안 페이드 인 또는 페이드 아웃될 수 있습니다. 오버레이를 삽입하려면 JobConfig 템플릿에서 overlays 배열을 사용합니다.

지원되는 이미지 파일 형식 목록을 참조하세요.

Cloud Storage에 이미지 업로드

시작하려면 다음을 수행하여 오버레이 이미지를 Cloud Storage 버킷에 업로드합니다.

  1. Google Cloud Console에서 Cloud Storage 브라우저 페이지로 이동합니다.
    Cloud Storage 브라우저 페이지로 이동
  2. 버킷 이름을 클릭하여 엽니다.
  3. 파일 업로드를 클릭합니다.
  4. 로컬 머신에서 업로드할 이미지 파일을 선택합니다.

오버레이 만들기

정적 또는 애니메이션의 두 가지 오버레이 유형을 만들 수 있습니다. 두 유형의 오버레이 모두 정적 이미지를 사용합니다. 정적 오버레이를 표시하거나 숨길 수 있습니다. 애니메이션 오버레이는 이미지의 페이드 인 및 페이드 아웃 애니메이션을 지원합니다.

하나의 출력 동영상에 여러 개의 오버레이를 삽입할 수 있습니다.

정적 오버레이 만들기

image 객체에서 uri 필드를 사용하여 Cloud Storage에서 오버레이 이미지를 지정합니다. resolution 객체에서 x 및 y 값을 0에서 1.0으로 설정합니다. 값이 0이면 해당 크기에 대한 소스 이미지 해상도를 유지하며 값이 1.0이면 출력 동영상의 크기에 맞게 이미지가 확장됩니다. 예를 들어 x: 1y: 0.5 값을 사용하여 오버레이 이미지를 출력 동영상의 전체 너비와 높이의 절반으로 확장합니다.

animations 배열에서 x 및 y 좌표가 0에서 1.0인 animationStatic 객체를 만듭니다. 이러한 좌표는 출력 동영상의 해상도를 기준으로 합니다. x: 0y: 0 값을 사용하여 오버레이의 왼쪽 상단 모서리를 출력 동영상의 왼쪽 상단 모서리에 배치합니다. startTimeOffset 필드를 사용하여 출력 동영상 타임라인에 오버레이가 표시되는 시간을 지정합니다.

정적 애니메이션을 삭제하려면 animationEnd 객체를 만듭니다. startTimeOffset 필드를 사용하여 출력 동영상 타임라인에서 애니메이션을 종료해야 하는 시점(즉, 오버레이가 사라지는 시점)을 지정합니다.

이 구성을 작업 템플릿에 추가하거나 임시 작업 구성에 포함할 수 있습니다.

REST

요청 데이터를 사용하기 전에 다음을 바꿉니다.

  • PROJECT_ID: IAM 설정에 나열된 Google Cloud 프로젝트 ID입니다.
  • LOCATION: 작업이 실행될 위치입니다. 지원되는 리전 중 하나를 사용합니다.
    위치 표시
    • us-central1
    • us-west1
    • us-west2
    • us-east1
    • us-east4
    • southamerica-east1
    • asia-east1
    • asia-south1
    • asia-southeast1
    • europe-west1
    • europe-west2
    • europe-west4
  • STORAGE_BUCKET_NAME: 만든 Cloud Storage 버킷의 이름입니다.
  • STORAGE_INPUT_VIDEO: Cloud Storage 버킷에 있는 트랜스코딩하는 동영상의 이름입니다(예: my-vid.mp4). 이 필드는 버킷에서 만든 폴더(예: input/my-vid.mp4)를 고려해야 합니다.
  • STORAGE_INPUT_OVERLAY: 오버레이에 사용할 Cloud Storage 버킷의 이미지 이름입니다(예: my-overlay.png). 이 필드는 버킷에서 만든 폴더(예: input/my-overlay.png)를 고려해야 합니다.
  • STORAGE_OUTPUT_FOLDER: 인코딩된 동영상 출력을 저장할 Cloud Storage 폴더 이름입니다.

요청을 보내려면 다음 옵션 중 하나를 펼칩니다.

다음과 비슷한 JSON 응답이 표시됩니다.

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/jobs/JOB_ID",
  "config": {
   ...
  },
  "state": "PENDING",
  "createTime": CREATE_TIME,
  "ttlAfterCompletionDays": 30
}

gcloud

  1. 작업 필드를 정의하는 request.json 파일을 만듭니다. gcloud 명령어를 다음과 같이 바꿉니다.
    • STORAGE_BUCKET_NAME: 만든 Cloud Storage 버킷의 이름입니다.
    • STORAGE_INPUT_VIDEO: Cloud Storage 버킷에 있는 트랜스코딩하는 동영상의 이름입니다(예: my-vid.mp4). 이 필드는 버킷에서 만든 폴더(예: input/my-vid.mp4)를 고려해야 합니다.
    • STORAGE_INPUT_OVERLAY: 오버레이에 사용할 Cloud Storage 버킷의 이미지 파일 이름입니다(예: my-overlay.png). 이 필드는 버킷에서 만든 폴더(예: input/my-overlay.png)를 고려해야 합니다.
    • LOCATION: 작업이 실행될 위치입니다. 다음 목록의 위치를 사용합니다.
      위치 표시
      • us-central1
      • us-west1
      • us-west2
      • us-east1
      • us-east4
      • southamerica-east1
      • asia-east1
      • asia-south1
      • asia-southeast1
      • europe-west1
      • europe-west2
      • europe-west4
    • STORAGE_OUTPUT_FOLDER: 인코딩된 동영상 출력을 저장할 Cloud Storage 폴더 이름입니다.
    {
      "config": {
        "inputs": [
              {
                "key": "input0",
                "uri": "gs://STORAGE_BUCKET_NAME/STORAGE_INPUT_VIDEO"
              }
        ],
        "elementaryStreams": [
          {
            "key": "video-stream0",
            "videoStream": {
              "h264": {
                "heightPixels": 360,
                "widthPixels": 640,
                "bitrateBps": 550000,
                "frameRate": 60
              }
            }
          },
          {
            "key": "audio-stream0",
            "audioStream": {
              "codec": "aac",
              "bitrateBps": 64000
            }
          }
        ],
        "muxStreams": [
          {
            "key": "sd",
            "container": "mp4",
            "elementaryStreams": [
              "video-stream0",
              "audio-stream0"
            ]
          }
        ],
        "output": {
          "uri": "gs://STORAGE_BUCKET_NAME/STORAGE_OUTPUT_FOLDER/"
        },
        "overlays": [
          {
            "image": {
              "uri": "gs://STORAGE_BUCKET_NAME/STORAGE_INPUT_OVERLAY",
              "resolution": {
                "x": 1,
                "y": 0.5
              },
              "alpha": 1
            },
            "animations": [
              {
                "animationStatic": {
                  "xy": {
                    "x": 0,
                    "y": 0
                  },
                  "startTimeOffset": "0s"
                }
              },
              {
                "animationEnd": {
                  "startTimeOffset": "10s"
                }
              }
            ]
          }
        ]
      }
    }
    
  2. 다음 명령어를 실행합니다.
    gcloud transcoder jobs create --location=LOCATION --file="request.json"
    
    다음과 비슷한 응답이 표시됩니다.
    {
      "name": "projects/PROJECT_NUMBER/locations/LOCATION/jobs/JOB_ID",
      "config": {
       ...
      },
      "state": "PENDING",
      "createTime": CREATE_TIME,
      "ttlAfterCompletionDays": 30
    }
    

C#

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용C# 설정 안내를 따르세요. 자세한 내용은 Transcoder API C# API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


using Google.Api.Gax.ResourceNames;
using Google.Cloud.Video.Transcoder.V1;
using Google.Protobuf.WellKnownTypes;
using System;

public class CreateJobWithStaticOverlaySample
{
    public Job CreateJobWithStaticOverlay(
        string projectId, string location, string inputUri, string overlayImageUri, string outputUri)
    {
        // Create the client.
        TranscoderServiceClient client = TranscoderServiceClient.Create();

        // Build the parent location name.
        LocationName parent = new LocationName(projectId, location);

        // Build the job config.
        VideoStream videoStream0 = new VideoStream
        {
            H264 = new VideoStream.Types.H264CodecSettings
            {
                BitrateBps = 550000,
                FrameRate = 60,
                HeightPixels = 360,
                WidthPixels = 640
            }
        };

        AudioStream audioStream0 = new AudioStream
        {
            Codec = "aac",
            BitrateBps = 64000
        };

        // Create the overlay image. Image resolution is based on output video
        // resolution. To respect the original image aspect ratio, set either x
        // or y to 0.0. This example stretches the overlay image the full width
        // and half of the height of the output video.
        Overlay.Types.Image overlayImage = new Overlay.Types.Image
        {
            Uri = overlayImageUri,
            Alpha = 1,
            Resolution = new Overlay.Types.NormalizedCoordinate
            {
                X = 1,
                Y = 0.5
            }
        };

        // Create the starting animation (when the overlay appears). Use the values x: 0 and y: 0 to
        // position the top-left corner of the overlay in the top-left corner of the output video.
        Overlay.Types.Animation animationStart = new Overlay.Types.Animation
        {
            AnimationStatic = new Overlay.Types.AnimationStatic
            {
                Xy = new Overlay.Types.NormalizedCoordinate
                {
                    X = 0,
                    Y = 0
                },
                StartTimeOffset = Duration.FromTimeSpan(TimeSpan.FromSeconds(0))
            }
        };

        // Create the ending animation (when the overlay disappears). In this example, the overlay
        // disappears at the 10-second mark in the output video.
        Overlay.Types.Animation animationEnd = new Overlay.Types.Animation
        {
            AnimationEnd = new Overlay.Types.AnimationEnd
            {
                StartTimeOffset = Duration.FromTimeSpan(TimeSpan.FromSeconds(10))
            }
        };

        // Create the overlay and add the image and animations to it.
        Overlay overlay = new Overlay
        {
            Image = overlayImage,
            Animations = { animationStart, animationEnd }
        };

        ElementaryStream elementaryStream0 = new ElementaryStream
        {
            Key = "video_stream0",
            VideoStream = videoStream0
        };

        ElementaryStream elementaryStream1 = new ElementaryStream
        {
            Key = "audio_stream0",
            AudioStream = audioStream0
        };

        MuxStream muxStream0 = new MuxStream
        {
            Key = "sd",
            Container = "mp4",
            ElementaryStreams = { "video_stream0", "audio_stream0" }
        };

        Input input = new Input
        {
            Key = "input0",
            Uri = inputUri
        };

        Output output = new Output
        {
            Uri = outputUri
        };

        JobConfig jobConfig = new JobConfig
        {
            Inputs = { input },
            Output = output,
            ElementaryStreams = { elementaryStream0, elementaryStream1 },
            MuxStreams = { muxStream0 },
            Overlays = { overlay }
        };

        // Build the job.
        Job newJob = new Job
        {
            InputUri = inputUri,
            OutputUri = outputUri,
            Config = jobConfig
        };

        // Call the API.
        Job job = client.CreateJob(parent, newJob);

        // Return the result.
        return job;
    }
}

Go

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Go 설정 안내를 따르세요. 자세한 내용은 Transcoder API Go API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

import (
	"context"
	"fmt"
	"io"

	"github.com/golang/protobuf/ptypes/duration"

	transcoder "cloud.google.com/go/video/transcoder/apiv1"
	"cloud.google.com/go/video/transcoder/apiv1/transcoderpb"
)

// createJobWithStaticOverlay creates a job based on a given configuration that
// includes a static overlay. See
// https://cloud.google.com/transcoder/docs/how-to/create-overlays#create-static-overlay
// for more information.
func createJobWithStaticOverlay(w io.Writer, projectID string, location string, inputURI string, overlayImageURI string, outputURI string) error {
	// projectID := "my-project-id"
	// location := "us-central1"
	// inputURI := "gs://my-bucket/my-video-file"
	// overlayImageURI := "gs://my-bucket/my-overlay-image-file"
	// outputURI := "gs://my-bucket/my-output-folder/"
	ctx := context.Background()
	client, err := transcoder.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	req := &transcoderpb.CreateJobRequest{
		Parent: fmt.Sprintf("projects/%s/locations/%s", projectID, location),
		Job: &transcoderpb.Job{
			InputUri:  inputURI,
			OutputUri: outputURI,
			JobConfig: &transcoderpb.Job_Config{
				Config: &transcoderpb.JobConfig{
					ElementaryStreams: []*transcoderpb.ElementaryStream{
						{
							Key: "video_stream0",
							ElementaryStream: &transcoderpb.ElementaryStream_VideoStream{
								VideoStream: &transcoderpb.VideoStream{
									CodecSettings: &transcoderpb.VideoStream_H264{
										H264: &transcoderpb.VideoStream_H264CodecSettings{
											BitrateBps:   550000,
											FrameRate:    60,
											HeightPixels: 360,
											WidthPixels:  640,
										},
									},
								},
							},
						},
						{
							Key: "audio_stream0",
							ElementaryStream: &transcoderpb.ElementaryStream_AudioStream{
								AudioStream: &transcoderpb.AudioStream{
									Codec:      "aac",
									BitrateBps: 64000,
								},
							},
						},
					},
					MuxStreams: []*transcoderpb.MuxStream{
						{
							Key:               "sd",
							Container:         "mp4",
							ElementaryStreams: []string{"video_stream0", "audio_stream0"},
						},
					},
					Overlays: []*transcoderpb.Overlay{
						{
							Image: &transcoderpb.Overlay_Image{
								Uri: overlayImageURI,
								Resolution: &transcoderpb.Overlay_NormalizedCoordinate{
									X: 1,
									Y: 0.5,
								},
								Alpha: 1,
							},
							Animations: []*transcoderpb.Overlay_Animation{
								{
									AnimationType: &transcoderpb.Overlay_Animation_AnimationStatic{
										AnimationStatic: &transcoderpb.Overlay_AnimationStatic{
											Xy: &transcoderpb.Overlay_NormalizedCoordinate{
												X: 0,
												Y: 0,
											},
											StartTimeOffset: &duration.Duration{
												Seconds: 0,
											},
										},
									},
								},

								{
									AnimationType: &transcoderpb.Overlay_Animation_AnimationEnd{
										AnimationEnd: &transcoderpb.Overlay_AnimationEnd{
											StartTimeOffset: &duration.Duration{
												Seconds: 10,
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
	// Creates the job. Jobs take a variable amount of time to run.
	// You can query for the job state; see getJob() in get_job.go.
	response, err := client.CreateJob(ctx, req)
	if err != nil {
		return fmt.Errorf("createJobWithStaticOverlay: %w", err)
	}

	fmt.Fprintf(w, "Job: %v", response.GetName())
	return nil
}

Java

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Java 설정 안내를 따르세요. 자세한 내용은 Transcoder API Java API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


import com.google.cloud.video.transcoder.v1.AudioStream;
import com.google.cloud.video.transcoder.v1.CreateJobRequest;
import com.google.cloud.video.transcoder.v1.ElementaryStream;
import com.google.cloud.video.transcoder.v1.Input;
import com.google.cloud.video.transcoder.v1.Job;
import com.google.cloud.video.transcoder.v1.JobConfig;
import com.google.cloud.video.transcoder.v1.LocationName;
import com.google.cloud.video.transcoder.v1.MuxStream;
import com.google.cloud.video.transcoder.v1.Output;
import com.google.cloud.video.transcoder.v1.Overlay;
import com.google.cloud.video.transcoder.v1.Overlay.AnimationEnd;
import com.google.cloud.video.transcoder.v1.Overlay.AnimationStatic;
import com.google.cloud.video.transcoder.v1.Overlay.NormalizedCoordinate;
import com.google.cloud.video.transcoder.v1.TranscoderServiceClient;
import com.google.cloud.video.transcoder.v1.VideoStream;
import com.google.protobuf.Duration;
import java.io.IOException;

public class CreateJobWithStaticOverlay {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project-id";
    String location = "us-central1";
    String inputUri = "gs://my-bucket/my-video-file";
    String overlayImageUri = "gs://my-bucket/my-overlay-image.jpg";
    String outputUri = "gs://my-bucket/my-output-folder/";

    createJobWithStaticOverlay(projectId, location, inputUri, overlayImageUri, outputUri);
  }

  // Creates a job from an ad-hoc configuration and adds a static overlay to it.
  public static void createJobWithStaticOverlay(
      String projectId, String location, String inputUri, String overlayImageUri, String outputUri)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (TranscoderServiceClient transcoderServiceClient = TranscoderServiceClient.create()) {

      VideoStream videoStream0 =
          VideoStream.newBuilder()
              .setH264(
                  VideoStream.H264CodecSettings.newBuilder()
                      .setBitrateBps(550000)
                      .setFrameRate(60)
                      .setHeightPixels(360)
                      .setWidthPixels(640))
              .build();

      AudioStream audioStream0 =
          AudioStream.newBuilder().setCodec("aac").setBitrateBps(64000).build();

      // Create the overlay image. Image resolution is based on output video resolution.
      // To respect the original image aspect ratio, set either x or y to 0.0. This example
      // stretches the overlay image the full width and half of the height of the
      // output video.
      Overlay.Image overlayImage =
          Overlay.Image.newBuilder()
              .setUri(overlayImageUri)
              .setResolution(NormalizedCoordinate.newBuilder().setX(1).setY(0.5).build())
              .setAlpha(1)
              .build();

      // Create the starting animation (when the overlay appears). Use the values x: 0 and y: 0 to
      // position the top-left corner of the overlay in the top-left corner of the output video.
      Overlay.Animation animationStart =
          Overlay.Animation.newBuilder()
              .setAnimationStatic(
                  AnimationStatic.newBuilder()
                      .setXy(NormalizedCoordinate.newBuilder().setX(0).setY(0).build())
                      .setStartTimeOffset(Duration.newBuilder().setSeconds(0).build())
                      .build())
              .build();

      // Create the ending animation (when the overlay disappears). In this example, the overlay
      // disappears at the 10-second mark in the output video.
      Overlay.Animation animationEnd =
          Overlay.Animation.newBuilder()
              .setAnimationEnd(
                  AnimationEnd.newBuilder()
                      .setStartTimeOffset(Duration.newBuilder().setSeconds(10).build())
                      .build())
              .build();

      // Create the overlay and add the image and animations to it.
      Overlay overlay =
          Overlay.newBuilder()
              .setImage(overlayImage)
              .addAnimations(animationStart)
              .addAnimations(animationEnd)
              .build();

      JobConfig config =
          JobConfig.newBuilder()
              .addInputs(Input.newBuilder().setKey("input0").setUri(inputUri))
              .setOutput(Output.newBuilder().setUri(outputUri))
              .addElementaryStreams(
                  ElementaryStream.newBuilder()
                      .setKey("video_stream0")
                      .setVideoStream(videoStream0))
              .addElementaryStreams(
                  ElementaryStream.newBuilder()
                      .setKey("audio_stream0")
                      .setAudioStream(audioStream0))
              .addMuxStreams(
                  MuxStream.newBuilder()
                      .setKey("sd")
                      .setContainer("mp4")
                      .addElementaryStreams("video_stream0")
                      .addElementaryStreams("audio_stream0")
                      .build())
              .addOverlays(overlay) // Add the overlay to the job config
              .build();

      CreateJobRequest createJobRequest =
          CreateJobRequest.newBuilder()
              .setJob(
                  Job.newBuilder()
                      .setInputUri(inputUri)
                      .setOutputUri(outputUri)
                      .setConfig(config)
                      .build())
              .setParent(LocationName.of(projectId, location).toString())
              .build();

      // Send the job creation request and process the response.
      Job job = transcoderServiceClient.createJob(createJobRequest);
      System.out.println("Job: " + job.getName());
    }
  }
}

Node.js

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Node.js 설정 안내를 따르세요. 자세한 내용은 Transcoder API Node.js API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// projectId = 'my-project-id';
// location = 'us-central1';
// inputUri = 'gs://my-bucket/my-video-file';
// overlayImageUri = 'gs://my-bucket/my-overlay-image-file';
// outputUri = 'gs://my-bucket/my-output-folder/';

// Imports the Transcoder library
const {TranscoderServiceClient} =
  require('@google-cloud/video-transcoder').v1;

// Instantiates a client
const transcoderServiceClient = new TranscoderServiceClient();

async function createJobFromStaticOverlay() {
  // Construct request
  const request = {
    parent: transcoderServiceClient.locationPath(projectId, location),
    job: {
      inputUri: inputUri,
      outputUri: outputUri,
      config: {
        elementaryStreams: [
          {
            key: 'video-stream0',
            videoStream: {
              h264: {
                heightPixels: 360,
                widthPixels: 640,
                bitrateBps: 550000,
                frameRate: 60,
              },
            },
          },
          {
            key: 'audio-stream0',
            audioStream: {
              codec: 'aac',
              bitrateBps: 64000,
            },
          },
        ],
        muxStreams: [
          {
            key: 'sd',
            container: 'mp4',
            elementaryStreams: ['video-stream0', 'audio-stream0'],
          },
        ],
        overlays: [
          {
            image: {
              uri: overlayImageUri,
              resolution: {
                x: 1,
                y: 0.5,
              },
              alpha: 1.0,
            },
            animations: [
              {
                animationStatic: {
                  xy: {
                    x: 0,
                    y: 0,
                  },
                  startTimeOffset: {
                    seconds: 0,
                  },
                },
              },
              {
                animationEnd: {
                  startTimeOffset: {
                    seconds: 10,
                  },
                },
              },
            ],
          },
        ],
      },
    },
  };

  // Run request
  const [response] = await transcoderServiceClient.createJob(request);
  console.log(`Job: ${response.name}`);
}

createJobFromStaticOverlay();

PHP

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용PHP 설정 안내를 따르세요. 자세한 내용은 Transcoder API PHP API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

use Google\Cloud\Video\Transcoder\V1\AudioStream;
use Google\Cloud\Video\Transcoder\V1\Client\TranscoderServiceClient;
use Google\Cloud\Video\Transcoder\V1\CreateJobRequest;
use Google\Cloud\Video\Transcoder\V1\ElementaryStream;
use Google\Cloud\Video\Transcoder\V1\Job;
use Google\Cloud\Video\Transcoder\V1\JobConfig;
use Google\Cloud\Video\Transcoder\V1\MuxStream;
use Google\Cloud\Video\Transcoder\V1\Overlay;
use Google\Cloud\Video\Transcoder\V1\VideoStream;
use Google\Protobuf\Duration;

/**
 * Creates a job based on a supplied job config that includes a static image overlay.
 *
 * @param string $projectId The ID of your Google Cloud Platform project.
 * @param string $location The location of the job.
 * @param string $inputUri Uri of the video in the Cloud Storage bucket.
 * @param string $overlayImageUri Uri of the image for the overlay in the Cloud Storage bucket.
 * @param string $outputUri Uri of the video output folder in the Cloud Storage bucket.
 */
function create_job_with_static_overlay($projectId, $location, $inputUri, $overlayImageUri, $outputUri)
{
    // Instantiate a client.
    $transcoderServiceClient = new TranscoderServiceClient();

    $formattedParent = $transcoderServiceClient->locationName($projectId, $location);
    $jobConfig =
        (new JobConfig())->setElementaryStreams([
            (new ElementaryStream())
                ->setKey('video-stream0')
                ->setVideoStream(
                    (new VideoStream())
                        ->setH264(
                            (new VideoStream\H264CodecSettings())
                                ->setBitrateBps(550000)
                                ->setFrameRate(60)
                                ->setHeightPixels(360)
                                ->setWidthPixels(640)
                        )
                ),
            (new ElementaryStream())
                ->setKey('audio-stream0')
                ->setAudioStream(
                    (new AudioStream())
                        ->setCodec('aac')
                        ->setBitrateBps(64000)
                )
        ])->setMuxStreams([
            (new MuxStream())
                ->setKey('sd')
                ->setContainer('mp4')
                ->setElementaryStreams(['video-stream0', 'audio-stream0'])
        ])->setOverlays([
            (new Overlay())
                ->setImage(
                    (new Overlay\Image())
                        ->setUri($overlayImageUri)
                        ->setResolution(
                            (new Overlay\NormalizedCoordinate())
                                ->setX(1)
                                ->setY(0.5)
                        )
                        ->setAlpha(1)
                )
                ->setAnimations([
                    (new Overlay\Animation())
                        ->setAnimationStatic(
                            (new Overlay\AnimationStatic())
                                ->setXy(
                                    (new Overlay\NormalizedCoordinate())
                                        ->setY(0)
                                        ->setX(0)
                                )
                                ->setStartTimeOffset(
                                    (new Duration())
                                        ->setSeconds(0)
                                )
                        ),
                    (new Overlay\Animation())
                        ->setAnimationEnd(
                            (new Overlay\AnimationEnd())
                                ->setStartTimeOffset(
                                    (new Duration())
                                        ->setSeconds(10)
                                )
                        )
                ])
        ]);

    $job = (new Job())
        ->setInputUri($inputUri)
        ->setOutputUri($outputUri)
        ->setConfig($jobConfig);
    $request = (new CreateJobRequest())
        ->setParent($formattedParent)
        ->setJob($job);

    $response = $transcoderServiceClient->createJob($request);

    // Print job name.
    printf('Job: %s' . PHP_EOL, $response->getName());
}

Python

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Python 설정 안내를 따르세요. 자세한 내용은 Transcoder API Python API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


import argparse

from google.cloud.video import transcoder_v1
from google.cloud.video.transcoder_v1.services.transcoder_service import (
    TranscoderServiceClient,
)
from google.protobuf import duration_pb2 as duration

def create_job_with_static_overlay(
    project_id: str,
    location: str,
    input_uri: str,
    overlay_image_uri: str,
    output_uri: str,
) -> transcoder_v1.types.resources.Job:
    """Creates a job based on an ad-hoc job configuration that includes a static image overlay.

    Args:
        project_id: The GCP project ID.
        location: The location to start the job in.
        input_uri: Uri of the video in the Cloud Storage bucket.
        overlay_image_uri: Uri of the image for the overlay in the Cloud Storage bucket.
        output_uri: Uri of the video output folder in the Cloud Storage bucket.

    Returns:
        The job resource.
    """

    client = TranscoderServiceClient()

    parent = f"projects/{project_id}/locations/{location}"
    job = transcoder_v1.types.Job()
    job.input_uri = input_uri
    job.output_uri = output_uri
    job.config = transcoder_v1.types.JobConfig(
        elementary_streams=[
            transcoder_v1.types.ElementaryStream(
                key="video-stream0",
                video_stream=transcoder_v1.types.VideoStream(
                    h264=transcoder_v1.types.VideoStream.H264CodecSettings(
                        height_pixels=360,
                        width_pixels=640,
                        bitrate_bps=550000,
                        frame_rate=60,
                    ),
                ),
            ),
            transcoder_v1.types.ElementaryStream(
                key="audio-stream0",
                audio_stream=transcoder_v1.types.AudioStream(
                    codec="aac", bitrate_bps=64000
                ),
            ),
        ],
        mux_streams=[
            transcoder_v1.types.MuxStream(
                key="sd",
                container="mp4",
                elementary_streams=["video-stream0", "audio-stream0"],
            ),
        ],
        overlays=[
            transcoder_v1.types.Overlay(
                image=transcoder_v1.types.Overlay.Image(
                    uri=overlay_image_uri,
                    resolution=transcoder_v1.types.Overlay.NormalizedCoordinate(
                        x=1,
                        y=0.5,
                    ),
                    alpha=1,
                ),
                animations=[
                    transcoder_v1.types.Overlay.Animation(
                        animation_static=transcoder_v1.types.Overlay.AnimationStatic(
                            xy=transcoder_v1.types.Overlay.NormalizedCoordinate(
                                x=0,
                                y=0,
                            ),
                            start_time_offset=duration.Duration(
                                seconds=0,
                            ),
                        ),
                    ),
                    transcoder_v1.types.Overlay.Animation(
                        animation_end=transcoder_v1.types.Overlay.AnimationEnd(
                            start_time_offset=duration.Duration(
                                seconds=10,
                            ),
                        ),
                    ),
                ],
            ),
        ],
    )
    response = client.create_job(parent=parent, job=job)
    print(f"Job: {response.name}")
    return response

Ruby

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Ruby 설정 안내를 따르세요. 자세한 내용은 Transcoder API Ruby API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

# project_id  = "YOUR-GOOGLE-CLOUD-PROJECT"  # (e.g. "my-project")
# location    = "YOUR-JOB-LOCATION"  # (e.g. "us-central1")
# input_uri   = "YOUR-GCS-INPUT-VIDEO"  # (e.g. "gs://my-bucket/my-video-file")
# overlay_image_uri   = "YOUR-GCS-OVERLAY-IMAGE"  # (e.g. "gs://my-bucket/overlay.jpg")
# output_uri  = "YOUR-GCS-OUTPUT-FOLDER/"  # (e.g. "gs://my-bucket/my-output-folder/")

# Require the Transcoder client library.
require "google/cloud/video/transcoder"

# Create a Transcoder client.
client = Google::Cloud::Video::Transcoder.transcoder_service

# Build the resource name of the parent.
parent = client.location_path project: project_id, location: location

# Build the job config.
new_job = {
  input_uri: input_uri,
  output_uri: output_uri,
  config: {
    elementary_streams: [
      {
        key: "video-stream0",
        video_stream: {
          h264: {
            height_pixels: 360,
            width_pixels: 640,
            bitrate_bps: 550_000,
            frame_rate: 60
          }
        }
      },
      {
        key: "audio-stream0",
        audio_stream: {
          codec: "aac",
          bitrate_bps: 64_000
        }
      }
    ],
    mux_streams: [
      {
        key: "sd",
        container: "mp4",
        elementary_streams: [
          "video-stream0",
          "audio-stream0"
        ]
      }
    ],
    overlays: [
      {
        image: {
          uri: overlay_image_uri,
          resolution: {
            x: 1,
            y: 0.5
          },
          alpha: 1
        },
        animations: [
          {
            animation_static: {
              xy: {
                x: 0,
                y: 0
              },
              start_time_offset: {
                seconds: 0
              }
            }
          },
          {
            animation_end: {
              start_time_offset: {
                seconds: 10
              }
            }
          }
        ]
      }
    ]
  }
}

job = client.create_job parent: parent, job: new_job

# Print the job name.
puts "Job: #{job.name}"

출력 동영상에서 정적 오버레이는 다음과 같은 특성을 갖습니다.

  • 타임라인의 시작 부분에 표시되며 10초 동안 표시됩니다.
  • 출력 동영상의 전체 너비와 높이의 절반을 확장합니다.
  • 출력 동영상의 왼쪽 상단에 있습니다.

이 구성에 대한 샘플 출력 동영상을 참조하세요. 이 동영상은 샘플 오버레이 이미지를 사용합니다.

애니메이션 오버레이 만들기

image 객체에서 uri 필드를 사용하여 Cloud Storage에서 오버레이 이미지를 지정합니다. resolution 객체에서 x 및 y 값을 0에서 1.0으로 설정합니다. 값이 0이면 해당 크기에 대한 소스 이미지 해상도를 유지하며 값이 1.0이면 출력 동영상의 크기에 맞게 이미지가 확장됩니다. 예를 들어 x: 0y: 0 값을 사용하여 오버레이 이미지의 원래 해상도를 유지합니다.

animations 배열에서 fadeTypeFADE_INanimationFade 객체를 만듭니다. x 및 y 좌표를 0에서 1.0으로 설정합니다. 이러한 좌표는 출력 동영상의 해상도를 기준으로 합니다. x: 0.5y: 0.5 값을 사용하여 오버레이의 왼쪽 상단 모서리를 출력 동영상 중앙에 배치합니다. startTimeOffset 필드를 사용하여 출력 동영상 타임라인에 오버레이가 표시되기 시작하는 시점을 지정합니다. 오버레이는 endTimeOffset 필드에 설정된 시간까지 전부 표시되어야 합니다.

오버레이를 페이드 아웃하려면 또 다른 animationFade 객체를 만듭니다. 이번에는 fadeTypeFADE_OUT로 설정합니다. 이전과 같이 위치 좌표와 시작 및 종료 시간을 입력합니다.

이 구성을 작업 템플릿에 추가하거나 임시 작업 구성에 포함할 수 있습니다.

REST

요청 데이터를 사용하기 전에 다음을 바꿉니다.

  • PROJECT_ID: IAM 설정에 나열된 Google Cloud 프로젝트 ID입니다.
  • LOCATION: 작업이 실행될 위치입니다. 지원되는 리전 중 하나를 사용합니다.
    위치 표시
    • us-central1
    • us-west1
    • us-west2
    • us-east1
    • us-east4
    • southamerica-east1
    • asia-east1
    • asia-south1
    • asia-southeast1
    • europe-west1
    • europe-west2
    • europe-west4
  • STORAGE_BUCKET_NAME: 만든 Cloud Storage 버킷의 이름입니다.
  • STORAGE_INPUT_VIDEO: Cloud Storage 버킷에 있는 트랜스코딩하는 동영상의 이름입니다(예: my-vid.mp4). 이 필드는 버킷에서 만든 폴더(예: input/my-vid.mp4)를 고려해야 합니다.
  • STORAGE_INPUT_OVERLAY: 오버레이에 사용할 Cloud Storage 버킷의 이미지 이름입니다(예: my-overlay.png). 이 필드는 버킷에서 만든 폴더(예: input/my-overlay.png)를 고려해야 합니다.
  • STORAGE_OUTPUT_FOLDER: 인코딩된 동영상 출력을 저장할 Cloud Storage 폴더 이름입니다.

요청을 보내려면 다음 옵션 중 하나를 펼칩니다.

다음과 비슷한 JSON 응답이 표시됩니다.

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/jobs/JOB_ID",
  "config": {
   ...
  },
  "state": "PENDING",
  "createTime": CREATE_TIME,
  "ttlAfterCompletionDays": 30
}

gcloud

  1. 작업 필드를 정의하는 request.json 파일을 만듭니다. gcloud 명령어를 다음과 같이 바꿉니다.
    • STORAGE_BUCKET_NAME: 만든 Cloud Storage 버킷의 이름입니다.
    • STORAGE_INPUT_VIDEO: Cloud Storage 버킷에 있는 트랜스코딩하는 동영상의 이름입니다(예: my-vid.mp4). 이 필드는 버킷에서 만든 폴더(예: input/my-vid.mp4)를 고려해야 합니다.
    • STORAGE_INPUT_OVERLAY: 오버레이에 사용할 Cloud Storage 버킷의 이미지 파일 이름입니다(예: my-overlay.png). 이 필드는 버킷에서 만든 폴더(예: input/my-overlay.png)를 고려해야 합니다.
    • LOCATION: 작업이 실행될 위치입니다. 다음 목록의 위치를 사용합니다.
      위치 표시
      • us-central1
      • us-west1
      • us-west2
      • us-east1
      • us-east4
      • southamerica-east1
      • asia-east1
      • asia-south1
      • asia-southeast1
      • europe-west1
      • europe-west2
      • europe-west4
    • STORAGE_OUTPUT_FOLDER: 인코딩된 동영상 출력을 저장할 Cloud Storage 폴더 이름입니다.
    {
      "config": {
        "inputs": [
              {
                "key": "input0",
                "uri": "gs://STORAGE_BUCKET_NAME/STORAGE_INPUT_VIDEO"
              }
        ],
        "elementaryStreams": [
          {
            "key": "video-stream0",
            "videoStream": {
              "h264": {
                "heightPixels": 360,
                "widthPixels": 640,
                "bitrateBps": 550000,
                "frameRate": 60
              }
            }
          },
          {
            "key": "audio-stream0",
            "audioStream": {
              "codec": "aac",
              "bitrateBps": 64000
            }
          }
        ],
        "muxStreams": [
          {
            "key": "sd",
            "container": "mp4",
            "elementaryStreams": [
              "video-stream0",
              "audio-stream0"
            ]
          }
        ],
        "output": {
          "uri": "gs://STORAGE_BUCKET_NAME/STORAGE_OUTPUT_FOLDER/"
        },
        "overlays": [
          {
            "image": {
              "uri": "gs://STORAGE_BUCKET_NAME/STORAGE_INPUT_OVERLAY",
              "resolution": {
                "x": 0,
                "y": 0
              },
              "alpha": 1
            },
            "animations": [
              {
                "animationFade": {
                  "fadeType": "FADE_IN",
                  "xy": {
                    "x": 0.5,
                    "y": 0.5
                  },
                  "startTimeOffset": "5s",
                  "endTimeOffset": "10s"
                }
              },
              {
                "animationFade": {
                  "fadeType": "FADE_OUT",
                  "xy": {
                    "x": 0.5,
                    "y": 0.5
                  },
                  "startTimeOffset": "12s",
                  "endTimeOffset": "15s"
                }
              }
            ]
          }
        ]
      }
    }
    
  2. 다음 명령어를 실행합니다.
    gcloud transcoder jobs create --location=LOCATION --file="request.json"
    
    다음과 비슷한 응답이 표시됩니다.
    {
      "name": "projects/PROJECT_NUMBER/locations/LOCATION/jobs/JOB_ID",
      "config": {
       ...
      },
      "state": "PENDING",
      "createTime": CREATE_TIME,
      "ttlAfterCompletionDays": 30
    }
    

C#

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용C# 설정 안내를 따르세요. 자세한 내용은 Transcoder API C# API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


using Google.Api.Gax.ResourceNames;
using Google.Cloud.Video.Transcoder.V1;
using Google.Protobuf.WellKnownTypes;
using System;

public class CreateJobWithAnimatedOverlaySample
{
    public Job CreateJobWithAnimatedOverlay(
        string projectId, string location, string inputUri, string overlayImageUri, string outputUri)
    {
        // Create the client.
        TranscoderServiceClient client = TranscoderServiceClient.Create();

        // Build the parent location name.
        LocationName parent = new LocationName(projectId, location);

        // Build the job config.
        VideoStream videoStream0 = new VideoStream
        {
            H264 = new VideoStream.Types.H264CodecSettings
            {
                BitrateBps = 550000,
                FrameRate = 60,
                HeightPixels = 360,
                WidthPixels = 640
            }
        };

        AudioStream audioStream0 = new AudioStream
        {
            Codec = "aac",
            BitrateBps = 64000
        };

        // Create the overlay image. Image resolution is based on output video resolution.
        // This example uses the values x: 0 and y: 0 to maintain the original resolution
        // of the overlay image.
        Overlay.Types.Image overlayImage = new Overlay.Types.Image
        {
            Uri = overlayImageUri,
            Alpha = 1,
            Resolution = new Overlay.Types.NormalizedCoordinate
            {
                X = 0,
                Y = 0
            }
        };

        // Create the starting animation (when the overlay starts to fade in). Use the values x: 0.5
        // and y: 0.5 to position the top-left corner of the overlay in the center of the output
        // video.
        Overlay.Types.Animation animationFadeIn = new Overlay.Types.Animation
        {
            AnimationFade = new Overlay.Types.AnimationFade
            {
                FadeType = Overlay.Types.FadeType.FadeIn,
                Xy = new Overlay.Types.NormalizedCoordinate
                {
                    X = 0.5,
                    Y = 0.5
                },
                StartTimeOffset = Duration.FromTimeSpan(TimeSpan.FromSeconds(5)),
                EndTimeOffset = Duration.FromTimeSpan(TimeSpan.FromSeconds(10))
            }
        };

        // Create the ending animation (when the overlay starts to fade out). The overlay will start
        // to fade out at the 12-second mark in the output video.
        Overlay.Types.Animation animationFadeOut = new Overlay.Types.Animation
        {
            AnimationFade = new Overlay.Types.AnimationFade
            {
                FadeType = Overlay.Types.FadeType.FadeOut,
                Xy = new Overlay.Types.NormalizedCoordinate
                {
                    X = 0.5,
                    Y = 0.5
                },
                StartTimeOffset = Duration.FromTimeSpan(TimeSpan.FromSeconds(12)),
                EndTimeOffset = Duration.FromTimeSpan(TimeSpan.FromSeconds(15))
            }
        };

        // Create the overlay and add the image and animations to it.
        Overlay overlay = new Overlay
        {
            Image = overlayImage,
            Animations = { animationFadeIn, animationFadeOut }
        };

        ElementaryStream elementaryStream0 = new ElementaryStream
        {
            Key = "video_stream0",
            VideoStream = videoStream0
        };

        ElementaryStream elementaryStream1 = new ElementaryStream
        {
            Key = "audio_stream0",
            AudioStream = audioStream0
        };

        MuxStream muxStream0 = new MuxStream
        {
            Key = "sd",
            Container = "mp4",
            ElementaryStreams = { "video_stream0", "audio_stream0" }
        };

        Input input = new Input
        {
            Key = "input0",
            Uri = inputUri
        };

        Output output = new Output
        {
            Uri = outputUri
        };

        JobConfig jobConfig = new JobConfig
        {
            Inputs = { input },
            Output = output,
            ElementaryStreams = { elementaryStream0, elementaryStream1 },
            MuxStreams = { muxStream0 },
            Overlays = { overlay }
        };

        // Build the job.
        Job newJob = new Job
        {
            InputUri = inputUri,
            OutputUri = outputUri,
            Config = jobConfig
        };

        // Call the API.
        Job job = client.CreateJob(parent, newJob);

        // Return the result.
        return job;
    }
}

Go

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Go 설정 안내를 따르세요. 자세한 내용은 Transcoder API Go API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

import (
	"context"
	"fmt"
	"io"

	"github.com/golang/protobuf/ptypes/duration"

	transcoder "cloud.google.com/go/video/transcoder/apiv1"
	"cloud.google.com/go/video/transcoder/apiv1/transcoderpb"
)

// createJobWithAnimatedOverlay creates a job based on a given configuration that
// includes an animated overlay. See
// https://cloud.google.com/transcoder/docs/how-to/create-overlays#create-animated-overlay
// for more information.
func createJobWithAnimatedOverlay(w io.Writer, projectID string, location string, inputURI string, overlayImageURI string, outputURI string) error {
	// projectID := "my-project-id"
	// location := "us-central1"
	// inputURI := "gs://my-bucket/my-video-file"
	// overlayImageURI := "gs://my-bucket/my-overlay-image-file"
	// outputURI := "gs://my-bucket/my-output-folder/"
	ctx := context.Background()
	client, err := transcoder.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	req := &transcoderpb.CreateJobRequest{
		Parent: fmt.Sprintf("projects/%s/locations/%s", projectID, location),
		Job: &transcoderpb.Job{
			InputUri:  inputURI,
			OutputUri: outputURI,
			JobConfig: &transcoderpb.Job_Config{
				Config: &transcoderpb.JobConfig{
					ElementaryStreams: []*transcoderpb.ElementaryStream{
						{
							Key: "video_stream0",
							ElementaryStream: &transcoderpb.ElementaryStream_VideoStream{
								VideoStream: &transcoderpb.VideoStream{
									CodecSettings: &transcoderpb.VideoStream_H264{
										H264: &transcoderpb.VideoStream_H264CodecSettings{
											BitrateBps:   550000,
											FrameRate:    60,
											HeightPixels: 360,
											WidthPixels:  640,
										},
									},
								},
							},
						},
						{
							Key: "audio_stream0",
							ElementaryStream: &transcoderpb.ElementaryStream_AudioStream{
								AudioStream: &transcoderpb.AudioStream{
									Codec:      "aac",
									BitrateBps: 64000,
								},
							},
						},
					},
					MuxStreams: []*transcoderpb.MuxStream{
						{
							Key:               "sd",
							Container:         "mp4",
							ElementaryStreams: []string{"video_stream0", "audio_stream0"},
						},
					},
					Overlays: []*transcoderpb.Overlay{
						{
							Image: &transcoderpb.Overlay_Image{
								Uri: overlayImageURI,
								Resolution: &transcoderpb.Overlay_NormalizedCoordinate{
									X: 0,
									Y: 0,
								},
								Alpha: 1,
							},
							Animations: []*transcoderpb.Overlay_Animation{
								{
									AnimationType: &transcoderpb.Overlay_Animation_AnimationFade{
										AnimationFade: &transcoderpb.Overlay_AnimationFade{
											FadeType: transcoderpb.Overlay_FADE_IN,
											Xy: &transcoderpb.Overlay_NormalizedCoordinate{
												X: 0.5,
												Y: 0.5,
											},
											StartTimeOffset: &duration.Duration{
												Seconds: 5,
											},
											EndTimeOffset: &duration.Duration{
												Seconds: 10,
											},
										},
									},
								},

								{
									AnimationType: &transcoderpb.Overlay_Animation_AnimationFade{
										AnimationFade: &transcoderpb.Overlay_AnimationFade{
											FadeType: transcoderpb.Overlay_FADE_OUT,
											Xy: &transcoderpb.Overlay_NormalizedCoordinate{
												X: 0.5,
												Y: 0.5,
											},
											StartTimeOffset: &duration.Duration{
												Seconds: 12,
											},
											EndTimeOffset: &duration.Duration{
												Seconds: 15,
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
	// Creates the job. Jobs take a variable amount of time to run.
	// You can query for the job state; see getJob() in get_job.go.
	response, err := client.CreateJob(ctx, req)
	if err != nil {
		return fmt.Errorf("createJobWithAnimatedOverlay: %w", err)
	}

	fmt.Fprintf(w, "Job: %v", response.GetName())
	return nil
}

Java

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Java 설정 안내를 따르세요. 자세한 내용은 Transcoder API Java API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


import com.google.cloud.video.transcoder.v1.AudioStream;
import com.google.cloud.video.transcoder.v1.CreateJobRequest;
import com.google.cloud.video.transcoder.v1.ElementaryStream;
import com.google.cloud.video.transcoder.v1.Input;
import com.google.cloud.video.transcoder.v1.Job;
import com.google.cloud.video.transcoder.v1.JobConfig;
import com.google.cloud.video.transcoder.v1.LocationName;
import com.google.cloud.video.transcoder.v1.MuxStream;
import com.google.cloud.video.transcoder.v1.Output;
import com.google.cloud.video.transcoder.v1.Overlay;
import com.google.cloud.video.transcoder.v1.Overlay.Animation;
import com.google.cloud.video.transcoder.v1.Overlay.AnimationFade;
import com.google.cloud.video.transcoder.v1.Overlay.FadeType;
import com.google.cloud.video.transcoder.v1.Overlay.NormalizedCoordinate;
import com.google.cloud.video.transcoder.v1.TranscoderServiceClient;
import com.google.cloud.video.transcoder.v1.VideoStream;
import com.google.protobuf.Duration;
import java.io.IOException;

public class CreateJobWithAnimatedOverlay {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project-id";
    String location = "us-central1";
    String inputUri = "gs://my-bucket/my-video-file";
    String overlayImageUri = "gs://my-bucket/my-overlay-image.jpg";
    String outputUri = "gs://my-bucket/my-output-folder/";

    createJobWithAnimatedOverlay(projectId, location, inputUri, overlayImageUri, outputUri);
  }

  // Creates a job from an ad-hoc configuration and adds an animated overlay to it.
  public static void createJobWithAnimatedOverlay(
      String projectId, String location, String inputUri, String overlayImageUri, String outputUri)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (TranscoderServiceClient transcoderServiceClient = TranscoderServiceClient.create()) {

      VideoStream videoStream0 =
          VideoStream.newBuilder()
              .setH264(
                  VideoStream.H264CodecSettings.newBuilder()
                      .setBitrateBps(550000)
                      .setFrameRate(60)
                      .setHeightPixels(360)
                      .setWidthPixels(640))
              .build();

      AudioStream audioStream0 =
          AudioStream.newBuilder().setCodec("aac").setBitrateBps(64000).build();

      // Create the overlay image. Image resolution is based on output video resolution.
      // This example uses the values x: 0 and y: 0 to maintain the original resolution
      // of the overlay image.
      Overlay.Image overlayImage =
          Overlay.Image.newBuilder()
              .setUri(overlayImageUri)
              .setResolution(NormalizedCoordinate.newBuilder().setX(0).setY(0).build())
              .setAlpha(1)
              .build();

      // Create the starting animation (when the overlay starts to fade in). Use the values x: 0.5
      // and y: 0.5 to position the top-left corner of the overlay in the top-left corner of the
      // output video.
      Overlay.Animation animationFadeIn =
          Animation.newBuilder()
              .setAnimationFade(
                  AnimationFade.newBuilder()
                      .setFadeType(FadeType.FADE_IN)
                      .setXy(NormalizedCoordinate.newBuilder().setX(0.5).setY(0.5).build())
                      .setStartTimeOffset(Duration.newBuilder().setSeconds(5).build())
                      .setEndTimeOffset(Duration.newBuilder().setSeconds(10).build())
                      .build())
              .build();

      // Create the ending animation (when the overlay starts to fade out). The overlay will start
      // to fade out at the 12-second mark in the output video.
      Overlay.Animation animationFadeOut =
          Animation.newBuilder()
              .setAnimationFade(
                  AnimationFade.newBuilder()
                      .setFadeType(FadeType.FADE_OUT)
                      .setXy(NormalizedCoordinate.newBuilder().setX(0.5).setY(0.5).build())
                      .setStartTimeOffset(Duration.newBuilder().setSeconds(12).build())
                      .setEndTimeOffset(Duration.newBuilder().setSeconds(15).build())
                      .build())
              .build();

      // Create the overlay and add the image and animations to it.
      Overlay overlay =
          Overlay.newBuilder()
              .setImage(overlayImage)
              .addAnimations(animationFadeIn)
              .addAnimations(animationFadeOut)
              .build();

      JobConfig config =
          JobConfig.newBuilder()
              .addInputs(Input.newBuilder().setKey("input0").setUri(inputUri))
              .setOutput(Output.newBuilder().setUri(outputUri))
              .addElementaryStreams(
                  ElementaryStream.newBuilder()
                      .setKey("video_stream0")
                      .setVideoStream(videoStream0))
              .addElementaryStreams(
                  ElementaryStream.newBuilder()
                      .setKey("audio_stream0")
                      .setAudioStream(audioStream0))
              .addMuxStreams(
                  MuxStream.newBuilder()
                      .setKey("sd")
                      .setContainer("mp4")
                      .addElementaryStreams("video_stream0")
                      .addElementaryStreams("audio_stream0")
                      .build())
              .addOverlays(overlay) // Add the overlay to the job config
              .build();

      CreateJobRequest createJobRequest =
          CreateJobRequest.newBuilder()
              .setJob(
                  Job.newBuilder()
                      .setInputUri(inputUri)
                      .setOutputUri(outputUri)
                      .setConfig(config)
                      .build())
              .setParent(LocationName.of(projectId, location).toString())
              .build();

      // Send the job creation request and process the response.
      Job job = transcoderServiceClient.createJob(createJobRequest);
      System.out.println("Job: " + job.getName());
    }
  }
}

Node.js

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Node.js 설정 안내를 따르세요. 자세한 내용은 Transcoder API Node.js API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// projectId = 'my-project-id';
// location = 'us-central1';
// inputUri = 'gs://my-bucket/my-video-file';
// overlayImageUri = 'gs://my-bucket/my-overlay-image-file';
// outputUri = 'gs://my-bucket/my-output-folder/';

// Imports the Transcoder library
const {TranscoderServiceClient} =
  require('@google-cloud/video-transcoder').v1;

// Instantiates a client
const transcoderServiceClient = new TranscoderServiceClient();

async function createJobFromAnimatedOverlay() {
  // Construct request
  const request = {
    parent: transcoderServiceClient.locationPath(projectId, location),
    job: {
      inputUri: inputUri,
      outputUri: outputUri,
      config: {
        elementaryStreams: [
          {
            key: 'video-stream0',
            videoStream: {
              h264: {
                heightPixels: 360,
                widthPixels: 640,
                bitrateBps: 550000,
                frameRate: 60,
              },
            },
          },
          {
            key: 'audio-stream0',
            audioStream: {
              codec: 'aac',
              bitrateBps: 64000,
            },
          },
        ],
        muxStreams: [
          {
            key: 'sd',
            container: 'mp4',
            elementaryStreams: ['video-stream0', 'audio-stream0'],
          },
        ],
        overlays: [
          {
            image: {
              uri: overlayImageUri,
              resolution: {
                x: 0,
                y: 0,
              },
              alpha: 1.0,
            },
            animations: [
              {
                animationFade: {
                  fadeType: 'FADE_IN',
                  xy: {
                    x: 0.5,
                    y: 0.5,
                  },
                  startTimeOffset: {
                    seconds: 5,
                  },
                  endTimeOffset: {
                    seconds: 10,
                  },
                },
              },
              {
                animationFade: {
                  fadeType: 'FADE_OUT',
                  xy: {
                    x: 0.5,
                    y: 0.5,
                  },
                  startTimeOffset: {
                    seconds: 12,
                  },
                  endTimeOffset: {
                    seconds: 15,
                  },
                },
              },
            ],
          },
        ],
      },
    },
  };

  // Run request
  const [response] = await transcoderServiceClient.createJob(request);
  console.log(`Job: ${response.name}`);
}

createJobFromAnimatedOverlay();

PHP

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용PHP 설정 안내를 따르세요. 자세한 내용은 Transcoder API PHP API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

use Google\Cloud\Video\Transcoder\V1\AudioStream;
use Google\Cloud\Video\Transcoder\V1\Client\TranscoderServiceClient;
use Google\Cloud\Video\Transcoder\V1\CreateJobRequest;
use Google\Cloud\Video\Transcoder\V1\ElementaryStream;
use Google\Cloud\Video\Transcoder\V1\Job;
use Google\Cloud\Video\Transcoder\V1\JobConfig;
use Google\Cloud\Video\Transcoder\V1\MuxStream;
use Google\Cloud\Video\Transcoder\V1\Overlay;
use Google\Cloud\Video\Transcoder\V1\VideoStream;
use Google\Protobuf\Duration;

/**
 * Creates a job based on a supplied job config that includes an animated overlay.
 *
 * @param string $projectId The ID of your Google Cloud Platform project.
 * @param string $location The location of the job.
 * @param string $inputUri Uri of the video in the Cloud Storage bucket.
 * @param string $overlayImageUri Uri of the image for the overlay in the Cloud Storage bucket.
 * @param string $outputUri Uri of the video output folder in the Cloud Storage bucket.
 */
function create_job_with_animated_overlay($projectId, $location, $inputUri, $overlayImageUri, $outputUri)
{
    // Instantiate a client.
    $transcoderServiceClient = new TranscoderServiceClient();

    $formattedParent = $transcoderServiceClient->locationName($projectId, $location);
    $jobConfig =
        (new JobConfig())->setElementaryStreams([
            (new ElementaryStream())
                ->setKey('video-stream0')
                ->setVideoStream(
                    (new VideoStream())->setH264(
                        (new VideoStream\H264CodecSettings())
                            ->setBitrateBps(550000)
                            ->setFrameRate(60)
                            ->setHeightPixels(360)
                            ->setWidthPixels(640)
                    )
                ),
            (new ElementaryStream())
                ->setKey('audio-stream0')
                ->setAudioStream(
                    (new AudioStream())
                        ->setCodec('aac')
                        ->setBitrateBps(64000)
                )
        ])->setMuxStreams([
            (new MuxStream())
                ->setKey('sd')
                ->setContainer('mp4')
                ->setElementaryStreams(['video-stream0', 'audio-stream0'])
        ])->setOverlays([
            (new Overlay())->setImage(
                (new Overlay\Image())
                    ->setUri($overlayImageUri)
                    ->setResolution(
                        (new Overlay\NormalizedCoordinate())
                            ->setX(0)
                            ->setY(0)
                    )
                    ->setAlpha(1)
            )->setAnimations([
                (new Overlay\Animation())->setAnimationFade(
                    (new Overlay\AnimationFade())
                        ->setFadeType(Overlay\FadeType::FADE_IN)
                        ->setXy(
                            (new Overlay\NormalizedCoordinate())
                                ->setY(0.5)
                                ->setX(0.5)
                        )
                        ->setStartTimeOffset(new Duration(['seconds' => 5]))
                        ->setEndTimeOffset(new Duration(['seconds' => 10]))
                ),
                (new Overlay\Animation())->setAnimationFade(
                    (new Overlay\AnimationFade())
                        ->setFadeType(Overlay\FadeType::FADE_OUT)
                        ->setXy(
                            (new Overlay\NormalizedCoordinate())
                                ->setY(0.5)
                                ->setX(0.5)
                        )
                        ->setStartTimeOffset(new Duration(['seconds' => 12]))
                        ->setEndTimeOffset(new Duration(['seconds' => 15]))
                )
            ])
        ]);

    $job = (new Job())
        ->setInputUri($inputUri)
        ->setOutputUri($outputUri)
        ->setConfig($jobConfig);
    $request = (new CreateJobRequest())
        ->setParent($formattedParent)
        ->setJob($job);

    $response = $transcoderServiceClient->createJob($request);

    // Print job name.
    printf('Job: %s' . PHP_EOL, $response->getName());
}

Python

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Python 설정 안내를 따르세요. 자세한 내용은 Transcoder API Python API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.


import argparse

from google.cloud.video import transcoder_v1
from google.cloud.video.transcoder_v1.services.transcoder_service import (
    TranscoderServiceClient,
)
from google.protobuf import duration_pb2 as duration

def create_job_with_animated_overlay(
    project_id: str,
    location: str,
    input_uri: str,
    overlay_image_uri: str,
    output_uri: str,
) -> transcoder_v1.types.resources.Job:
    """Creates a job based on an ad-hoc job configuration that includes an animated image overlay.

    Args:
        project_id: The GCP project ID.
        location: The location to start the job in.
        input_uri: Uri of the video in the Cloud Storage bucket.
        overlay_image_uri: Uri of the image for the overlay in the Cloud Storage bucket.
        output_uri: Uri of the video output folder in the Cloud Storage bucket.

    Returns:
        The job resource.
    """

    client = TranscoderServiceClient()

    parent = f"projects/{project_id}/locations/{location}"
    job = transcoder_v1.types.Job()
    job.input_uri = input_uri
    job.output_uri = output_uri
    job.config = transcoder_v1.types.JobConfig(
        elementary_streams=[
            transcoder_v1.types.ElementaryStream(
                key="video-stream0",
                video_stream=transcoder_v1.types.VideoStream(
                    h264=transcoder_v1.types.VideoStream.H264CodecSettings(
                        height_pixels=360,
                        width_pixels=640,
                        bitrate_bps=550000,
                        frame_rate=60,
                    ),
                ),
            ),
            transcoder_v1.types.ElementaryStream(
                key="audio-stream0",
                audio_stream=transcoder_v1.types.AudioStream(
                    codec="aac", bitrate_bps=64000
                ),
            ),
        ],
        mux_streams=[
            transcoder_v1.types.MuxStream(
                key="sd",
                container="mp4",
                elementary_streams=["video-stream0", "audio-stream0"],
            ),
        ],
        overlays=[
            transcoder_v1.types.Overlay(
                image=transcoder_v1.types.Overlay.Image(
                    uri=overlay_image_uri,
                    resolution=transcoder_v1.types.Overlay.NormalizedCoordinate(
                        x=0,
                        y=0,
                    ),
                    alpha=1,
                ),
                animations=[
                    transcoder_v1.types.Overlay.Animation(
                        animation_fade=transcoder_v1.types.Overlay.AnimationFade(
                            fade_type=transcoder_v1.types.Overlay.FadeType.FADE_IN,
                            xy=transcoder_v1.types.Overlay.NormalizedCoordinate(
                                x=0.5,
                                y=0.5,
                            ),
                            start_time_offset=duration.Duration(
                                seconds=5,
                            ),
                            end_time_offset=duration.Duration(
                                seconds=10,
                            ),
                        ),
                    ),
                    transcoder_v1.types.Overlay.Animation(
                        animation_fade=transcoder_v1.types.Overlay.AnimationFade(
                            fade_type=transcoder_v1.types.Overlay.FadeType.FADE_OUT,
                            xy=transcoder_v1.types.Overlay.NormalizedCoordinate(
                                x=0.5,
                                y=0.5,
                            ),
                            start_time_offset=duration.Duration(
                                seconds=12,
                            ),
                            end_time_offset=duration.Duration(
                                seconds=15,
                            ),
                        ),
                    ),
                ],
            ),
        ],
    )
    response = client.create_job(parent=parent, job=job)
    print(f"Job: {response.name}")
    return response

Ruby

이 샘플을 사용해 보기 전에 Transcoder API 빠른 시작: 클라이언트 라이브러리 사용Ruby 설정 안내를 따르세요. 자세한 내용은 Transcoder API Ruby API 참고 문서를 확인하세요.

Transcoder API에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 로컬 개발 환경의 인증 설정을 참조하세요.

# project_id  = "YOUR-GOOGLE-CLOUD-PROJECT"  # (e.g. "my-project")
# location    = "YOUR-JOB-LOCATION"  # (e.g. "us-central1")
# input_uri   = "YOUR-GCS-INPUT-VIDEO"  # (e.g. "gs://my-bucket/my-video-file")
# overlay_image_uri   = "YOUR-GCS-OVERLAY-IMAGE"  # (e.g. "gs://my-bucket/overlay.jpg")
# output_uri  = "YOUR-GCS-OUTPUT-FOLDER/"  # (e.g. "gs://my-bucket/my-output-folder/")

# Require the Transcoder client library.
require "google/cloud/video/transcoder"

# Create a Transcoder client.
client = Google::Cloud::Video::Transcoder.transcoder_service

# Build the resource name of the parent.
parent = client.location_path project: project_id, location: location

# Build the job config.
new_job = {
  input_uri: input_uri,
  output_uri: output_uri,
  config: {
    elementary_streams: [
      {
        key: "video-stream0",
        video_stream: {
          h264: {
            height_pixels: 360,
            width_pixels: 640,
            bitrate_bps: 550_000,
            frame_rate: 60
          }
        }
      },
      {
        key: "audio-stream0",
        audio_stream: {
          codec: "aac",
          bitrate_bps: 64_000
        }
      }
    ],
    mux_streams: [
      {
        key: "sd",
        container: "mp4",
        elementary_streams: [
          "video-stream0",
          "audio-stream0"
        ]
      }
    ],
    overlays: [
      {
        image: {
          uri: overlay_image_uri,
          resolution: {
            x: 0,
            y: 0
          },
          alpha: 1
        },
        animations: [
          {
            animation_fade: {
              fade_type: Google::Cloud::Video::Transcoder::V1::Overlay::FadeType::FADE_IN,
              xy: {
                x: 0.5,
                y: 0.5
              },
              start_time_offset: {
                seconds: 5
              },
              end_time_offset: {
                seconds: 10
              }
            }
          },
          {
            animation_fade: {
              fade_type: Google::Cloud::Video::Transcoder::V1::Overlay::FadeType::FADE_OUT,
              xy: {
                x: 0.5,
                y: 0.5
              },
              start_time_offset: {
                seconds: 12
              },
              end_time_offset: {
                seconds: 15
              }
            }
          }
        ]
      }
    ]
  }
}

job = client.create_job parent: parent, job: new_job

# Print the job name.
puts "Job: #{job.name}"

결과 동영상에서 애니메이션 오버레이의 특징은 다음과 같습니다.

  1. 출력 동영상의 5초 지점에서 페이드 인이 되기 시작합니다. 오버레이의 알파 값은 0에서 시작하여 1.0에서 끝납니다. 오버레이의 왼쪽 상단 모서리가 출력 동영상의 중앙에 나타납니다. 오버레이는 오버레이 이미지의 원래 해상도로 나타납니다.
  2. 페이드 인 후 2초 동안 오버레이가 표시됩니다.
  3. 출력 동영상의 12초 지점에서 페이드 아웃되기 시작합니다. 오버레이의 알파 값은 1.0에서 시작하여 0에서 끝납니다.
  4. 애니메이션은 15초 지점에서 사라집니다.

이 구성에 대한 샘플 출력 동영상을 참조하세요. 이 동영상은 샘플 오버레이 이미지를 사용합니다.