This page explains how to insert overlays into transcoded videos. An overlay
consists of an image that is inserted on top of the output video, and can
optionally be faded in or out over a specified time period. To insert an
overlay, use the
overlays
array in
the JobConfig
template.
See the
list of supported image file formats .
Upload an image to Cloud Storage
To get started, do the following to upload an overlay image to your
Cloud Storage bucket:
In the Google Cloud console, go to the Cloud Storage Browser page.
Go to the Cloud Storage Browser page
Click the name of your bucket to open it.
Click Upload files .
Select an image file to upload from your local machine.
Create an overlay
You can create two types of overlays: static or
animated . Both types of overlays use a static image.
You can show or hide static overlays. Animated overlays support fade
in and fade out animations of the image.
You can insert multiple overlays into a single output video.
Create a static overlay
In the image
object, use the
uri
field to
specify the overlay image in Cloud Storage. In the resolution
object, set
the x and y values from 0 to 1.0. A value of 0 maintains the source image
resolution for that dimension; a value of 1.0 will stretch the image to match
the dimension of the output video. For example, use the values x: 1
and y:
0.5
to stretch the overlay image the full width and half of the height of the
output video.
In the animations
array, create an animationStatic
object with x and y
coordinates from 0 to 1.0. These coordinates are based on the output video
resolution. 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. Specify when the overlay
should appear in the output video timeline using the startTimeOffset
field.
To remove the static animation, create an animationEnd
object. Specify when
the animation should end (that is, the overlay should disappear) in the output
video timeline using the startTimeOffset
field.
You can add this configuration to a
job template or include it in an
ad-hoc job configuration :
REST
Before using any of the request data,
make the following replacements:
PROJECT_ID
: Your Google Cloud project ID listed in
the IAM Settings .
LOCATION
: The location where your job will run. Use
one of the supported regions .
Show locations
us-central1
us-west1
us-west2
us-east1
us-east4
southamerica-east1
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-southeast1
europe-west1
europe-west2
europe-west4
STORAGE_BUCKET_NAME
: The name of the Cloud Storage
bucket you created.
STORAGE_INPUT_VIDEO
: The name of the video in your
Cloud Storage bucket that you are transcoding, such as my-vid.mp4
.
This field should take into account any folders that you created in the
bucket (for example, input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY
: The name of the
image in your Cloud Storage bucket that you are using for the overlay, such as
my-overlay.png
. This field should take into account any folders that you created in the
bucket (for example, input/my-overlay.png
).
STORAGE_OUTPUT_FOLDER
: The Cloud Storage
folder name where you want to save the encoded video outputs.
Note: You don't need to create the output folder object before
creating the job. When processing the job, the Transcoder API automatically prepends the
folder name you specify as part of the names of the objects saved to Cloud Storage.
To send your request, expand one of these options:
curl (Linux, macOS, or Cloud Shell)
Note:
The following command assumes that you have logged in to
the gcloud
CLI with your user account by running
gcloud init
or
gcloud auth login
, or by using Cloud Shell ,
which automatically logs you into the gcloud
CLI
.
You can check the currently active account by running
gcloud auth list
.
Save the request body in a file named request.json
.
Run the following command in the terminal to create or overwrite
this file in the current directory:
cat > request.json << 'EOF'
{
"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"
}
}
]
}
]
}
}
EOF
Then execute the following command to send your REST request:
curl -X POST \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ -d @request.json \ "https://transcoder.googleapis.com/v1/projects/PROJECT_ID /locations/LOCATION /jobs"
PowerShell (Windows)
Save the request body in a file named request.json
.
Run the following command in the terminal to create or overwrite
this file in the current directory:
@'
{
"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"
}
}
]
}
]
}
}
'@ | Out-File -FilePath request.json -Encoding utf8
Then execute the following command to send your REST request:
$cred = gcloud auth print-access-token $headers = @{ "Authorization" = "Bearer $cred" } Invoke-WebRequest ` -Method POST ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -InFile request.json ` -Uri "https://transcoder.googleapis.com/v1/projects/PROJECT_ID /locations/LOCATION /jobs" | Select-Object -Expand Content
You should receive a JSON response similar to the following:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
gcloud
Create a request.json
file that defines the job fields. Make
the following replacements for the
gcloud
command:
STORAGE_BUCKET_NAME : The
name of the Cloud Storage bucket you created.
STORAGE_INPUT_VIDEO : The
name of the video in your Cloud Storage bucket that you are
transcoding, such as my-vid.mp4
. This field should take into
account any folders that you created in the bucket (for example,
input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY : The name of the
image file in your Cloud Storage bucket that you are using for the overlay, such as
my-overlay.png
. This field should take into account any folders that you created in the
bucket (for example, input/my-overlay.png
).
LOCATION : The location where
your job will run. Use a location from the following list.
Show locations
us-central1
us-west1
us-west2
us-east1
us-east4
southamerica-east1
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-southeast1
europe-west1
europe-west2
europe-west4
STORAGE_OUTPUT_FOLDER : The
Cloud Storage folder name where you want to save the encoded video
outputs.
Note: You don't need to create the output folder object before
creating the job. When processing the job, the Transcoder API automatically prepends the
folder name you specify as part of the names of the objects saved to 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"
}
}
]
}
]
}
}
Run the following command:
gcloud transcoder jobs create --location=LOCATION --file="request.json"
You should see a response similar to the following:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
Go
Before trying this sample, follow the Go setup instructions in the
Transcoder API quickstart using
client libraries .
For more information, see the
Transcoder API Go API
reference documentation .
To authenticate to Transcoder API, set up Application Default Credentials.
For more information, see
Set up authentication for a local development environment .
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
}
Node.js
Before trying this sample, follow the Node.js setup instructions in the
Transcoder API quickstart using
client libraries .
For more information, see the
Transcoder API Node.js API
reference documentation .
To authenticate to Transcoder API, set up Application Default Credentials.
For more information, see
Set up authentication for a local development environment .
/**
* 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();
Python
Before trying this sample, follow the Python setup instructions in the
Transcoder API quickstart using
client libraries .
For more information, see the
Transcoder API Python API
reference documentation .
To authenticate to Transcoder API, set up Application Default Credentials.
For more information, see
Set up authentication for a local development environment .
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
In the output video, the static overlay has the following characteristics:
It appears at the beginning of the timeline and is visible for 10 seconds.
It stretches the full width and half of the height of the output video.
It is positioned in the top-left corner of the output video.
See the sample output video for
this configuration. This video uses a
sample overlay image .
Create an animated overlay
In the image
object, use the
uri
field to
specify the overlay image in Cloud Storage. In the resolution
object, set
the x and y values from 0 to 1.0. A value of 0 maintains the source image
resolution for that dimension; a value of 1.0 will stretch the image to match
the dimension of the output video. For example, use the values x: 0
and y: 0
to maintain the original resolution of the overlay image.
In the animations
array, create an animationFade
object with a fadeType
of
FADE_IN
. Set the x and y coordinates from 0 to 1.0. These coordinates are
based on the output video resolution. 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.
Specify when the overlay should start to appear in the output video timeline
using the startTimeOffset
field. The overlay should be fully visible by the
time set in the endTimeOffset
field.
To fade out the overlay, create another animationFade
object. This time, set
the fadeType
to FADE_OUT
. Input the position coordinates and start and end
times as before.
You can add this configuration to a
job template or include it in an
ad-hoc job configuration :
REST
Before using any of the request data,
make the following replacements:
PROJECT_ID
: Your Google Cloud project ID listed in
the IAM Settings .
LOCATION
: The location where your job will run. Use
one of the supported regions .
Show locations
us-central1
us-west1
us-west2
us-east1
us-east4
southamerica-east1
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-southeast1
europe-west1
europe-west2
europe-west4
STORAGE_BUCKET_NAME
: The name of the Cloud Storage
bucket you created.
STORAGE_INPUT_VIDEO
: The name of the video in your
Cloud Storage bucket that you are transcoding, such as my-vid.mp4
.
This field should take into account any folders that you created in the
bucket (for example, input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY
: The name of the
image in your Cloud Storage bucket that you are using for the overlay, such as
my-overlay.png
. This field should take into account any folders that you created in the
bucket (for example, input/my-overlay.png
).
STORAGE_OUTPUT_FOLDER
: The Cloud Storage
folder name where you want to save the encoded video outputs.
Note: You don't need to create the output folder object before
creating the job. When processing the job, the Transcoder API automatically prepends the
folder name you specify as part of the names of the objects saved to Cloud Storage.
To send your request, expand one of these options:
curl (Linux, macOS, or Cloud Shell)
Note:
The following command assumes that you have logged in to
the gcloud
CLI with your user account by running
gcloud init
or
gcloud auth login
, or by using Cloud Shell ,
which automatically logs you into the gcloud
CLI
.
You can check the currently active account by running
gcloud auth list
.
Save the request body in a file named request.json
.
Run the following command in the terminal to create or overwrite
this file in the current directory:
cat > request.json << 'EOF'
{
"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"
}
}
]
}
]
}
}
EOF
Then execute the following command to send your REST request:
curl -X POST \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ -d @request.json \ "https://transcoder.googleapis.com/v1/projects/PROJECT_ID /locations/LOCATION /jobs"
PowerShell (Windows)
Save the request body in a file named request.json
.
Run the following command in the terminal to create or overwrite
this file in the current directory:
@'
{
"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"
}
}
]
}
]
}
}
'@ | Out-File -FilePath request.json -Encoding utf8
Then execute the following command to send your REST request:
$cred = gcloud auth print-access-token $headers = @{ "Authorization" = "Bearer $cred" } Invoke-WebRequest ` -Method POST ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -InFile request.json ` -Uri "https://transcoder.googleapis.com/v1/projects/PROJECT_ID /locations/LOCATION /jobs" | Select-Object -Expand Content
You should receive a JSON response similar to the following:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
gcloud
Create a request.json
file that defines the job fields. Make
the following replacements for the
gcloud
command:
STORAGE_BUCKET_NAME : The
name of the Cloud Storage bucket you created.
STORAGE_INPUT_VIDEO : The
name of the video in your Cloud Storage bucket that you are
transcoding, such as my-vid.mp4
. This field should take into
account any folders that you created in the bucket (for example,
input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY : The name of the
image file in your Cloud Storage bucket that you are using for the overlay, such as
my-overlay.png
. This field should take into account any folders that you created in the
bucket (for example, input/my-overlay.png
).
LOCATION : The location where
your job will run. Use a location from the following list.
Show locations
us-central1
us-west1
us-west2
us-east1
us-east4
southamerica-east1
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-southeast1
europe-west1
europe-west2
europe-west4
STORAGE_OUTPUT_FOLDER : The
Cloud Storage folder name where you want to save the encoded video
outputs.
Note: You don't need to create the output folder object before
creating the job. When processing the job, the Transcoder API automatically prepends the
folder name you specify as part of the names of the objects saved to 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"
}
}
]
}
]
}
}
Run the following command:
gcloud transcoder jobs create --location=LOCATION --file="request.json"
You should see a response similar to the following:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
Go
Before trying this sample, follow the Go setup instructions in the
Transcoder API quickstart using
client libraries .
For more information, see the
Transcoder API Go API
reference documentation .
To authenticate to Transcoder API, set up Application Default Credentials.
For more information, see
Set up authentication for a local development environment .
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
}
Node.js
Before trying this sample, follow the Node.js setup instructions in the
Transcoder API quickstart using
client libraries .
For more information, see the
Transcoder API Node.js API
reference documentation .
To authenticate to Transcoder API, set up Application Default Credentials.
For more information, see
Set up authentication for a local development environment .
/**
* 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();
Python
Before trying this sample, follow the Python setup instructions in the
Transcoder API quickstart using
client libraries .
For more information, see the
Transcoder API Python API
reference documentation .
To authenticate to Transcoder API, set up Application Default Credentials.
For more information, see
Set up authentication for a local development environment .
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
In the resulting video, the animated overlay has the following characteristics:
It starts to fade in at the 5-second mark in the output video. The alpha
value for the overlay starts at 0 and ends at 1.0. The top-left corner of
the overlay appears at the center of the output video. The overlay appears
at the original resolution of the overlay image.
After it fades in, the overlay shows for 2 seconds.
It starts to fade out at the 12-second mark in the output video. The alpha
value for the overlay starts at 1.0 and ends at 0.
The animation disappears by the 15-second mark.
See the sample output video
for this configuration. This video uses a
sample overlay image .