Cette page explique comment insérer des superpositions dans des vidéos transcodées. Une superposition se compose d'une image JPEG qui est insérée en haut de la vidéo de sortie. Il est également possible de la faire apparaître ou disparaître en fondu selon une période spécifiée. Pour insérer une superposition, utilisez le tableau overlays
dans le modèle JobConfig
.
Remarque : Vous ne pouvez créer une superposition qu'à l'aide d'une image JPEG. Aucun autre type d'image n'est accepté.
Importer une image dans Cloud Storage
Pour commencer, procédez comme suit pour importer une image en superposition dans votre bucket Cloud Storage :
Dans la console Google Cloud, accédez au navigateur Cloud Storage.
Accéder à la page du navigateur Cloud Storage
Cliquez sur le nom de votre bucket pour l'ouvrir.
Cliquez sur Upload files (Importer des fichiers).
Sélectionnez un fichier JPEG à importer à partir de votre ordinateur local.
Créer une superposition
Vous pouvez créer deux types de superpositions : statique ou animée . Les deux types de superpositions utilisent une image statique.
Vous pouvez afficher ou masquer les superpositions statiques. Les superpositions animées sont compatibles avec les effets de fondu.
Vous pouvez insérer plusieurs superpositions dans une seule vidéo de sortie.
Créer une superposition statique
Dans l'objet image
, spécifiez l'image de superposition dans Cloud Storage à l'aide du champ uri
. Dans l'objet resolution
, définissez les valeurs x et y de 0 à 1.0. Une valeur de 0 conserve la résolution de l'image source pour cette dimension. Une valeur de 1.0 étire l'image pour qu'elle corresponde à la dimension de la vidéo de sortie. Par exemple, utilisez les valeurs x: 1
et y:
0.5
pour étirer l'image en superposition sur toute la largeur et la moitié de la hauteur de la vidéo de sortie.
Dans le tableau animations
, créez un objet animationStatic
avec les coordonnées x et y de 0 à 1.0. Ces coordonnées sont basées sur la résolution de la vidéo de sortie. Utilisez les valeurs x: 0
et y: 0
pour placer l'angle supérieur gauche de la superposition dans l'angle supérieur gauche de la vidéo de sortie. Spécifiez le moment où la superposition doit apparaître dans la timeline de la vidéo de sortie à l'aide du champ startTimeOffset
.
Pour retirer l'animation statique, créez un objet animationEnd
. Spécifiez le moment où l'animation doit prendre fin (quand la superposition doit disparaître) dans la timeline de la vidéo de sortie à l'aide du champ startTimeOffset
.
Vous pouvez ajouter cette configuration à un modèle de tâche ou l'inclure dans une configuration de tâche ad hoc :
REST
Avant d'utiliser les données de requête, effectuez les remplacements suivants:
PROJECT_ID : ID de votre projet Google Cloud répertorié dans les paramètres IAM .
LOCATION : emplacement dans lequel votre tâche sera exécutée. Utilisez l'une des régions disponibles :
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 : nom du bucket Cloud Storage que vous avez créé.
STORAGE_INPUT_VIDEO : nom de la vidéo dans votre bucket Cloud Storage que vous transcodez, par exemple my-vid.mp4
.
Ce champ doit tenir compte des dossiers créés dans le bucket (par exemple, input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY : nom de l'image JPEG dans votre bucket Cloud Storage que vous utilisez pour la superposition, tel que my-overlay.jpg
. Ce champ doit tenir compte des dossiers créés dans le bucket (par exemple, input/my-overlay.jpg
).
STORAGE_OUTPUT_FOLDER : nom du dossier Cloud Storage dans lequel vous souhaitez enregistrer les sorties vidéo encodées.
Remarque : Il n'est pas nécessaire de créer l'objet de dossier de sortie avant de créer la tâche. Lors du traitement de la tâche, l'API Transcoder ajoute automatiquement le nom du dossier spécifié comme préfixe aux noms des objets enregistrés dans Cloud Storage.
Corps JSON de la requête :
{
"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"
}
}
]
}
]
}
}
Pour envoyer votre requête, développez l'une des options suivantes :
curl (Linux, macOS ou Cloud Shell)
Remarque : La commande suivante suppose que vous êtes connecté à la CLI gcloud
avec votre compte utilisateur en exécutant la commande gcloud init
ou gcloud auth login
, ou en utilisant Cloud Shell , qui vous connecte automatiquement à la CLI gcloud
.
Vous pouvez exécuter la commande gcloud auth list
pour vérifier quel est le compte actif actuellement.
Enregistrez le corps de la requête dans un fichier nommé request.json
.
Exécutez la commande suivante dans le terminal pour créer ou écraser ce fichier dans le répertoire actuel :
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
Exécutez ensuite la commande suivante pour envoyer votre requête REST :
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)
Remarque : La commande suivante suppose que vous êtes connecté à la CLI gcloud
avec votre compte utilisateur en exécutant la commande gcloud init
ou gcloud auth login
, ou en utilisant Cloud Shell , qui vous connecte automatiquement à la CLI gcloud
.
Vous pouvez exécuter la commande gcloud auth list
pour vérifier quel est le compte actif actuellement.
Enregistrez le corps de la requête dans un fichier nommé request.json
.
Exécutez la commande suivante dans le terminal pour créer ou écraser ce fichier dans le répertoire actuel :
@'
{
"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
Exécutez ensuite la commande suivante pour envoyer votre requête REST :
$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
Vous devriez recevoir une réponse JSON de ce type :
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
gcloud CLI
Créez un fichier request.json
qui définit les champs de la tâche. Effectuez les remplacements suivants pour la commande gcloud
:
STORAGE_BUCKET_NAME : nom du bucket Cloud Storage que vous avez créé.
STORAGE_INPUT_VIDEO : nom de la vidéo de votre bucket Cloud Storage que vous convertissez, par exemple my-vid.mp4
. Ce champ doit prendre en compte les dossiers que vous avez créés dans le bucket (par exemple, input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY : nom de l'image JPEG de votre bucket Cloud Storage que vous utilisez pour la superposition, par exemple my-overlay.jpg
. Ce champ doit prendre en compte tous les dossiers que vous avez créés dans le bucket (par exemple, input/my-overlay.jpg
).
LOCATION : emplacement d'exécution de votre tâche. Utilisez un emplacement issu de la liste suivante :
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 : nom du dossier Cloud Storage dans lequel vous souhaitez enregistrer les sorties vidéo encodées.
Remarque : Il n'est pas nécessaire de créer l'objet de dossier de sortie avant de créer la tâche. Lors du traitement de la tâche, l'API Transcoder ajoute automatiquement le nom du dossier spécifié comme préfixe aux noms des objets enregistrés dans 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"
}
}
]
}
]
}
}
Exécutez la commande suivante :
gcloud transcoder jobs create --location=LOCATION --file="request.json"
Un résultat semblable aux lignes suivantes doit s'afficher :
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
Go
Avant d'essayer cet exemple, suivez les instructions de configuration de Go dans le guide de démarrage rapide de l'API Transcoder à l'aide de bibliothèques clientes .
Pour en savoir plus, consultez la documentation de référence de l'API Transcoder Go .
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" - Must be a JPEG
// outputURI := "gs://my-bucket/my-output-folder/"
ctx := context.Background()
client, err := transcoder.NewClient(ctx)
if err != nil {
return fmt.Errorf("NewClient: %v", 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: %v", err)
}
fmt.Fprintf(w, "Job: %v", response.GetName())
return nil
}
Node.js
Avant d'essayer cet exemple, suivez les instructions de configuration de Node.js dans le guide de démarrage rapide de l'API Transcoder à l'aide de bibliothèques clientes .
Pour en savoir plus, consultez la documentation de référence de l'API Transcoder Node.js .
/**
* 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'; // Must be a JPEG
// 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
Avant d'essayer cet exemple, suivez les instructions de configuration de Python dans le guide de démarrage rapide de l'API Transcoder à l'aide de bibliothèques clientes .
Pour en savoir plus, consultez la documentation de référence de l'API Transcoder Python .
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, location, input_uri, overlay_image_uri, output_uri
):
"""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 JPEG image for the overlay in the Cloud Storage bucket. Must be a JPEG.
output_uri: Uri of the video output folder in the Cloud Storage bucket."""
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
Dans la vidéo de sortie, la superposition statique présente les caractéristiques suivantes :
Elle s'affiche au début de la chronologie et reste visible pendant 10 secondes.
Elle s'étire jusqu'à la largeur maximale et la moitié de la hauteur de la vidéo de sortie.
Elle est positionnée dans l'angle supérieur gauche de la vidéo de sortie.
Consultez l'exemple de vidéo de sortie pour cette configuration. Cette vidéo utilise un exemple d'image en superposition .
Créer une superposition animée
Dans l'objet image
, spécifiez l'image de superposition dans Cloud Storage à l'aide du champ uri
. Dans l'objet resolution
, définissez les valeurs x et y de 0 à 1.0. Une valeur de 0 conserve la résolution de l'image source pour cette dimension. Une valeur de 1.0 étire l'image pour qu'elle corresponde à la dimension de la vidéo de sortie. Par exemple, utilisez les valeurs x: 0
et y: 0
pour conserver la résolution d'origine de l'image en superposition.
Dans le tableau animations
, créez un objet animationFade
avec un fadeType
défini sur FADE_IN
. Définissez les coordonnées x et y de 0 à 1.0. Ces coordonnées sont basées sur la résolution de la vidéo de sortie. Utilisez les valeurs x: 0.5
et y: 0.5
pour placer l'angle supérieur gauche de la superposition au centre de la vidéo de sortie.
Spécifiez le moment où la superposition doit commencer à apparaître dans la timeline de la vidéo de sortie à l'aide du champ startTimeOffset
. La superposition devient entièrement visible suivant le moment défini dans le champ endTimeOffset
.
Pour faire disparaître progressivement la superposition, créez un autre objet animationFade
. Cette fois-ci, définissez le fadeType
sur FADE_OUT
. Saisissez les coordonnées de position ainsi que les points de départ et de fin de l'animation, comme auparavant.
Vous pouvez ajouter cette configuration à un modèle de tâche ou l'inclure dans une configuration de tâche ad hoc :
REST
Avant d'utiliser les données de requête, effectuez les remplacements suivants:
PROJECT_ID : ID de votre projet Google Cloud répertorié dans les paramètres IAM .
LOCATION : emplacement dans lequel votre tâche sera exécutée. Utilisez l'une des régions disponibles :
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 : nom du bucket Cloud Storage que vous avez créé.
STORAGE_INPUT_VIDEO : nom de la vidéo dans votre bucket Cloud Storage que vous transcodez, par exemple my-vid.mp4
.
Ce champ doit tenir compte des dossiers créés dans le bucket (par exemple, input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY : nom de l'image JPEG dans votre bucket Cloud Storage que vous utilisez pour la superposition, tel que my-overlay.jpg
. Ce champ doit tenir compte des dossiers créés dans le bucket (par exemple, input/my-overlay.jpg
).
STORAGE_OUTPUT_FOLDER : nom du dossier Cloud Storage dans lequel vous souhaitez enregistrer les sorties vidéo encodées.
Remarque : Il n'est pas nécessaire de créer l'objet de dossier de sortie avant de créer la tâche. Lors du traitement de la tâche, l'API Transcoder ajoute automatiquement le nom du dossier spécifié comme préfixe aux noms des objets enregistrés dans Cloud Storage.
Corps JSON de la requête :
{
"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"
}
}
]
}
]
}
}
Pour envoyer votre requête, développez l'une des options suivantes :
curl (Linux, macOS ou Cloud Shell)
Remarque : La commande suivante suppose que vous êtes connecté à la CLI gcloud
avec votre compte utilisateur en exécutant la commande gcloud init
ou gcloud auth login
, ou en utilisant Cloud Shell , qui vous connecte automatiquement à la CLI gcloud
.
Vous pouvez exécuter la commande gcloud auth list
pour vérifier quel est le compte actif actuellement.
Enregistrez le corps de la requête dans un fichier nommé request.json
.
Exécutez la commande suivante dans le terminal pour créer ou écraser ce fichier dans le répertoire actuel :
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
Exécutez ensuite la commande suivante pour envoyer votre requête REST :
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)
Remarque : La commande suivante suppose que vous êtes connecté à la CLI gcloud
avec votre compte utilisateur en exécutant la commande gcloud init
ou gcloud auth login
, ou en utilisant Cloud Shell , qui vous connecte automatiquement à la CLI gcloud
.
Vous pouvez exécuter la commande gcloud auth list
pour vérifier quel est le compte actif actuellement.
Enregistrez le corps de la requête dans un fichier nommé request.json
.
Exécutez la commande suivante dans le terminal pour créer ou écraser ce fichier dans le répertoire actuel :
@'
{
"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
Exécutez ensuite la commande suivante pour envoyer votre requête REST :
$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
Vous devriez recevoir une réponse JSON de ce type :
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
gcloud CLI
Créez un fichier request.json
qui définit les champs de la tâche. Effectuez les remplacements suivants pour la commande gcloud
:
STORAGE_BUCKET_NAME : nom du bucket Cloud Storage que vous avez créé.
STORAGE_INPUT_VIDEO : nom de la vidéo de votre bucket Cloud Storage que vous convertissez, par exemple my-vid.mp4
. Ce champ doit prendre en compte les dossiers que vous avez créés dans le bucket (par exemple, input/my-vid.mp4
).
STORAGE_INPUT_OVERLAY : nom de l'image JPEG de votre bucket Cloud Storage que vous utilisez pour la superposition, par exemple my-overlay.jpg
. Ce champ doit prendre en compte tous les dossiers que vous avez créés dans le bucket (par exemple, input/my-overlay.jpg
).
LOCATION : emplacement d'exécution de votre tâche. Utilisez un emplacement issu de la liste suivante :
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 : nom du dossier Cloud Storage dans lequel vous souhaitez enregistrer les sorties vidéo encodées.
Remarque : Il n'est pas nécessaire de créer l'objet de dossier de sortie avant de créer la tâche. Lors du traitement de la tâche, l'API Transcoder ajoute automatiquement le nom du dossier spécifié comme préfixe aux noms des objets enregistrés dans 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"
}
}
]
}
]
}
}
Exécutez la commande suivante :
gcloud transcoder jobs create --location=LOCATION --file="request.json"
Un résultat semblable aux lignes suivantes doit s'afficher :
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
Go
Avant d'essayer cet exemple, suivez les instructions de configuration de Go dans le guide de démarrage rapide de l'API Transcoder à l'aide de bibliothèques clientes .
Pour en savoir plus, consultez la documentation de référence de l'API Transcoder Go .
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" - Must be a JPEG
// outputURI := "gs://my-bucket/my-output-folder/"
ctx := context.Background()
client, err := transcoder.NewClient(ctx)
if err != nil {
return fmt.Errorf("NewClient: %v", 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: %v", err)
}
fmt.Fprintf(w, "Job: %v", response.GetName())
return nil
}
Node.js
Avant d'essayer cet exemple, suivez les instructions de configuration de Node.js dans le guide de démarrage rapide de l'API Transcoder à l'aide de bibliothèques clientes .
Pour en savoir plus, consultez la documentation de référence de l'API Transcoder Node.js .
/**
* 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'; // Must be a JPEG
// 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
Avant d'essayer cet exemple, suivez les instructions de configuration de Python dans le guide de démarrage rapide de l'API Transcoder à l'aide de bibliothèques clientes .
Pour en savoir plus, consultez la documentation de référence de l'API Transcoder Python .
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, location, input_uri, overlay_image_uri, output_uri
):
"""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 JPEG image for the overlay in the Cloud Storage bucket. Must be a JPEG.
output_uri: Uri of the video output folder in the Cloud Storage bucket."""
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
Dans la vidéo obtenue, la superposition animée présente les caractéristiques suivantes :
Elle commence à apparaître au bout de 5 secondes de lecture dans la vidéo de sortie. La valeur alpha de la superposition commence à 0 et se termine à 1.0. Le coin supérieur gauche de la superposition apparaît au centre de la vidéo de sortie. La superposition apparaît dans sa résolution d'image initiale.
Une fois l'image en superposition affichée, elle apparaît pendant 2 secondes.
Elle commence à disparaître au bout de 12 secondes de lecture dans la vidéo de sortie. La valeur alpha de la superposition commence à 0 et se termine à 1.0.
L'animation disparaît avant d'atteindre 15 secondes de lecture.
Consultez l'exemple de vidéo de sortie pour cette configuration. Cette vidéo utilise un exemple d'image en superposition .