En esta página se explica cómo agregar subtítulos a un video de salida.
Los subtítulos (o solo subtítulos ) son la representación visual del audio de un video. Por lo general, los subtítulos están en el mismo idioma que el audio y, además, incluyen sonidos de fondo y cambios de interlocutor.
Por lo general, los subtítulos se usan para traducir el diálogo de un video a un idioma diferente. Por lo general, los subtítulos no incluyen sonidos de fondo ni cambios de interlocutor.
En esta página, se usa el término archivo de subtítulos de entrada para hacer referencia a un archivo de texto que contiene subtítulos. Proporciona este archivo como una entrada a un trabajo.
Agregar subtítulos a una configuración de trabajo
Consulta las entradas y salidas compatibles para conocer los formatos de archivo de subtítulos de entrada admitidos. Se proporciona un archivo de video de muestra y archivos de subtítulos de entrada de muestra para que pruebes la configuración.
Usa la información de las siguientes secciones para agregar subtítulos a una configuración de trabajo. En esta página, se supone que estás familiarizado con los conceptos básicos de JobConfig . Para obtener más información sobre cómo crear trabajos de transcodificación, consulta Crea y administra trabajos .
Agregar subtítulos
Para crear un trabajo que incorpore subtítulos en el contenedor del archivo de video de salida, haz lo siguiente:
Agrega un array inputs
al comienzo de la configuración del trabajo.
Agrega un objeto Input
al array inputs
que define la clave y el URI del video de entrada asociado.
Agrega otro objeto Input
que incluya la ruta de acceso al archivo de subtítulos de entrada.
Nota: No coloques líneas en blanco entre las líneas de texto del archivo de subtítulos de entrada.
Agrega un array editList
a la configuración del trabajo. Este array se usa para agregar entradas al cronograma del video de salida.
Agrega un objeto EditAtom
al array editList
. Este objeto EditAtom
debe hacer referencia a las claves del video de entrada y los subtítulos que agregaste en el array inputs
. Puedes designar un startTimeOffset
y un endTimeOffset
para cortar el video de entrada.
Para agregar las leyendas a los contenedores de salida, agrega un objeto textStream
al array elementaryStreams
. Solo se admite una transmisión de texto incorporada y se agrega a todos los videos de salida (ya que solo hay un cronograma de salida).
Usa el array mapping
en el objeto de configuración textStream
para hacer referencia a la clave del objeto EditAtom
.
La siguiente configuración de ejemplo incorpora subtítulos CEA-608 en un video.
Puedes agregar esta configuración a una plantilla de trabajo o incluirla en una configuración de trabajo ad hoc :
REST
Antes de usar cualquiera de los datos de solicitud a continuación, realiza los siguientes reemplazos:
PROJECT_ID
: El ID de tu proyecto de Google Cloud que aparece en Configuración de IAM .
LOCATION
: Es la ubicación en la que se ejecutará tu trabajo. Usa una de las regiones compatibles .
Mostrar ubicaciones
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
: Es el nombre del bucket de Cloud Storage que creaste.
STORAGE_INPUT_VIDEO
: Es el nombre de un video en tu bucket de Cloud Storage que transcodificas, como my-vid.mp4
.
Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_CAPTIONS_FILE
: Es el nombre de un archivo de subtítulos en tu bucket de Cloud Storage, como captions.srt
.
Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/captions.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre de la carpeta de salida del bucket de Cloud Storage en la que deseas guardar los resultados de video codificados.
Nota: No necesitas crear el objeto de carpeta de salida antes de crear el trabajo. Cuando se procesa el trabajo, la API de Transcoder antepone automáticamente el nombre de la carpeta que especificas como parte de los nombres de los objetos guardados en Cloud Storage.
Para enviar tu solicitud, expande una de estas opciones:
curl (Linux, macOS o Cloud Shell)
Nota:
Con el siguiente comando, se supone que accediste a
la CLI de gcloud
con tu cuenta de usuario a través de la ejecución de
gcloud init
o
gcloud auth login
,
o a través del uso de
Cloud Shell ,
que accede de forma automática a la CLI de gcloud
.
Para comprobar la cuenta activa actual, ejecuta gcloud auth list
.
Guarda el cuerpo de la solicitud en un archivo llamado request.json
.
Ejecuta el comando siguiente en la terminal para crear o reemplazar este archivo en el directorio actual:
cat > request.json << 'EOF'
{
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_INPUT_VIDEO "
},
{
"key": "caption_input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_CAPTIONS_FILE "
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0",
"caption_input0"
]
}
],
"elementaryStreams": [
{
"key": "video-stream0",
"videoStream": {
"h264": {
"heightPixels": 360,
"widthPixels": 640,
"bitrateBps": 550000,
"frameRate": 60
}
}
},
{
"key": "audio-stream0",
"audioStream": {
"codec": "aac",
"bitrateBps": 64000
}
},
{
"key": "cea-stream0",
"textStream": {
"codec": "cea608",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "caption_input0",
"inputTrack": 0
}
],
"languageCode": "en-US",
"displayName": "English"
}
}
],
"muxStreams": [
{
"key": "sd-hls",
"container": "ts",
"elementaryStreams": [
"video-stream0",
"audio-stream0"
]
},
{
"key": "sd-dash",
"container": "fmp4",
"elementaryStreams": [
"video-stream0"
]
},
{
"key": "audio-dash",
"container": "fmp4",
"elementaryStreams": [
"audio-stream0"
]
}
],
"manifests": [
{
"fileName": "manifest.m3u8",
"type": "HLS",
"muxStreams": [
"sd-hls"
]
},
{
"fileName": "manifest.mpd",
"type": "DASH",
"muxStreams": [
"sd-dash",
"audio-dash"
]
}
],
"output": {
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_OUTPUT_FOLDER /"
}
}
}
EOF
Luego, ejecuta el siguiente comando para enviar tu solicitud de 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)
Nota:
Con el siguiente comando, se supone que accediste a
la CLI de gcloud
con tu cuenta de usuario a través de la ejecución de
gcloud init
o
gcloud auth login
,
o a través del uso de
Cloud Shell ,
que accede de forma automática a la CLI de gcloud
.
Para comprobar la cuenta activa actual, ejecuta gcloud auth list
.
Guarda el cuerpo de la solicitud en un archivo llamado request.json
.
Ejecuta el comando siguiente en la terminal para crear o reemplazar este archivo en el directorio actual:
@'
{
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_INPUT_VIDEO "
},
{
"key": "caption_input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_CAPTIONS_FILE "
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0",
"caption_input0"
]
}
],
"elementaryStreams": [
{
"key": "video-stream0",
"videoStream": {
"h264": {
"heightPixels": 360,
"widthPixels": 640,
"bitrateBps": 550000,
"frameRate": 60
}
}
},
{
"key": "audio-stream0",
"audioStream": {
"codec": "aac",
"bitrateBps": 64000
}
},
{
"key": "cea-stream0",
"textStream": {
"codec": "cea608",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "caption_input0",
"inputTrack": 0
}
],
"languageCode": "en-US",
"displayName": "English"
}
}
],
"muxStreams": [
{
"key": "sd-hls",
"container": "ts",
"elementaryStreams": [
"video-stream0",
"audio-stream0"
]
},
{
"key": "sd-dash",
"container": "fmp4",
"elementaryStreams": [
"video-stream0"
]
},
{
"key": "audio-dash",
"container": "fmp4",
"elementaryStreams": [
"audio-stream0"
]
}
],
"manifests": [
{
"fileName": "manifest.m3u8",
"type": "HLS",
"muxStreams": [
"sd-hls"
]
},
{
"fileName": "manifest.mpd",
"type": "DASH",
"muxStreams": [
"sd-dash",
"audio-dash"
]
}
],
"output": {
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_OUTPUT_FOLDER /"
}
}
}
'@ | Out-File -FilePath request.json -Encoding utf8
Luego, ejecuta el siguiente comando para enviar tu solicitud de 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
Deberías recibir una respuesta JSON similar a la que se muestra a continuación:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
gcloud
Antes de usar cualquiera de los datos de comando a continuación, haz los siguientes reemplazos:
LOCATION
: Es la ubicación en la que se ejecutará tu trabajo. Usa una de las regiones compatibles .
Mostrar ubicaciones
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
: Es el nombre del bucket de Cloud Storage que creaste.
STORAGE_INPUT_VIDEO
: Es el nombre de un video en tu bucket de Cloud Storage que transcodificas, como my-vid.mp4
.
Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_CAPTIONS_FILE
: Es el nombre de un archivo de subtítulos en tu bucket de Cloud Storage, como captions.srt
.
Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/captions.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre de la carpeta de salida del bucket de Cloud Storage en la que deseas guardar los resultados de video codificados.
Nota: No necesitas crear el objeto de carpeta de salida antes de crear el trabajo. Cuando se procesa el trabajo, la API de Transcoder antepone automáticamente el nombre de la carpeta que especificas como parte de los nombres de los objetos guardados en Cloud Storage.
Guarda el siguiente código en un archivo llamado request.json
.
{
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_INPUT_VIDEO "
},
{
"key": "caption_input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_CAPTIONS_FILE "
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0",
"caption_input0"
]
}
],
"elementaryStreams": [
{
"key": "video-stream0",
"videoStream": {
"h264": {
"heightPixels": 360,
"widthPixels": 640,
"bitrateBps": 550000,
"frameRate": 60
}
}
},
{
"key": "audio-stream0",
"audioStream": {
"codec": "aac",
"bitrateBps": 64000
}
},
{
"key": "cea-stream0",
"textStream": {
"codec": "cea608",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "caption_input0",
"inputTrack": 0
}
],
"languageCode": "en-US",
"displayName": "English"
}
}
],
"muxStreams": [
{
"key": "sd-hls",
"container": "ts",
"elementaryStreams": [
"video-stream0",
"audio-stream0"
]
},
{
"key": "sd-dash",
"container": "fmp4",
"elementaryStreams": [
"video-stream0"
]
},
{
"key": "audio-dash",
"container": "fmp4",
"elementaryStreams": [
"audio-stream0"
]
}
],
"manifests": [
{
"fileName": "manifest.m3u8",
"type": "HLS",
"muxStreams": [
"sd-hls"
]
},
{
"fileName": "manifest.mpd",
"type": "DASH",
"muxStreams": [
"sd-dash",
"audio-dash"
]
}
],
"output": {
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_OUTPUT_FOLDER /"
}
}
}
Ejecuta el siguiente comando:
Linux, macOS o Cloud Shell
gcloud transcoder jobs create --location=LOCATION --file=request.json
Windows (PowerShell)
gcloud transcoder jobs create --location=LOCATION --file=request.json
Windows (cmd.exe)
gcloud transcoder jobs create --location=LOCATION --file=request.json
Deberías recibir una respuesta similar a la que figura a continuación:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
Go
Antes de probar esta muestra, sigue las instrucciones de configuración Go que se encuentran en la Guía de inicio rápido de la API de Transcoder con bibliotecas cliente .
Para obtener más información, consulta la documentación de referencia de la API de Go de la API de Transcoder .
Para autenticarte en la API de Transcoder, configura las credenciales predeterminadas de la aplicación.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local .
import (
"context"
"fmt"
"io"
transcoder "cloud.google.com/go/video/transcoder/apiv1"
"cloud.google.com/go/video/transcoder/apiv1/transcoderpb"
)
// createJobWithEmbeddedCaptions creates a job that embeds closed captions in the
// output video. See https://cloud.google.com/transcoder/docs/how-to/captions-and-subtitles
// for more information.
func createJobWithEmbeddedCaptions(w io.Writer, projectID string, location string, inputVideoURI string, inputCaptionsURI string, outputURI string) error {
// projectID := "my-project-id"
// location := "us-central1"
// inputVideoURI := "gs://my-bucket/my-video-file"
// inputCaptionsURI := "gs://my-bucket/my-captions-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()
// Set up elementary streams. The InputKey field refers to inputs in
// the Inputs array defined the job config.
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,
},
},
},
{
Key: "cea_stream0",
ElementaryStream: &transcoderpb.ElementaryStream_TextStream{
TextStream: &transcoderpb.TextStream{
Codec: "cea608",
Mapping: []*transcoderpb.TextStream_TextMapping{
{
AtomKey: "atom0",
InputKey: "caption_input0",
InputTrack: 0,
},
},
LanguageCode: "en-US",
DisplayName: "English",
},
},
},
}
req := &transcoderpb.CreateJobRequest{
Parent: fmt.Sprintf("projects/%s/locations/%s", projectID, location),
Job: &transcoderpb.Job{
OutputUri: outputURI,
JobConfig: &transcoderpb.Job_Config{
Config: &transcoderpb.JobConfig{
Inputs: []*transcoderpb.Input{
{
Key: "input0",
Uri: inputVideoURI,
},
{
Key: "caption_input0",
Uri: inputCaptionsURI,
},
},
EditList: []*transcoderpb.EditAtom{
{
Key: "atom0",
Inputs: []string{"input0", "caption_input0"},
},
},
ElementaryStreams: elementaryStreams,
MuxStreams: []*transcoderpb.MuxStream{
{
Key: "sd-hls",
Container: "ts",
ElementaryStreams: []string{"video_stream0", "audio_stream0"},
},
{
Key: "sd-dash",
Container: "fmp4",
ElementaryStreams: []string{"video_stream0"},
},
{
Key: "audio-dash",
Container: "fmp4",
ElementaryStreams: []string{"audio_stream0"},
},
},
Manifests: []*transcoderpb.Manifest{
{
FileName: "manifest.m3u8",
Type: transcoderpb.Manifest_HLS,
MuxStreams: []string{"sd-hls"},
},
{
FileName: "manifest.mpd",
Type: transcoderpb.Manifest_DASH,
MuxStreams: []string{"sd-dash", "audio-dash"},
},
},
},
},
},
}
// 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("CreateJob: %w", err)
}
fmt.Fprintf(w, "Job: %v", response.GetName())
return nil
}
Node.js
Antes de probar esta muestra, sigue las instrucciones de configuración Node.js que se encuentran en la Guía de inicio rápido de la API de Transcoder con bibliotecas cliente .
Para obtener más información, consulta la documentación de referencia de la API de Node.js de la API de Transcoder .
Para autenticarte en la API de Transcoder, configura las credenciales predeterminadas de la aplicación.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local .
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// projectId = 'my-project-id';
// location = 'us-central1';
// inputVideoUri = 'gs://my-bucket/my-video-file';
// inputCaptionsUri = 'gs://my-bucket/my-captions-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 createJobWithEmbeddedCaptions() {
// Construct request
const request = {
parent: transcoderServiceClient.locationPath(projectId, location),
job: {
outputUri: outputUri,
config: {
inputs: [
{
key: 'input0',
uri: inputVideoUri,
},
{
key: 'caption_input0',
uri: inputCaptionsUri,
},
],
editList: [
{
key: 'atom0',
inputs: ['input0', 'caption_input0'],
},
],
elementaryStreams: [
{
key: 'video-stream0',
videoStream: {
h264: {
heightPixels: 360,
widthPixels: 640,
bitrateBps: 550000,
frameRate: 60,
},
},
},
{
key: 'audio-stream0',
audioStream: {
codec: 'aac',
bitrateBps: 64000,
},
},
{
key: 'cea-stream0',
textStream: {
codec: 'cea608',
mapping: [
{
atomKey: 'atom0',
inputKey: 'caption_input0',
inputTrack: 0,
},
],
languageCode: 'en-US',
displayName: 'English',
},
},
],
muxStreams: [
{
key: 'sd-hls',
container: 'ts',
elementaryStreams: ['video-stream0', 'audio-stream0'],
},
{
key: 'sd-dash',
container: 'fmp4',
elementaryStreams: ['video-stream0'],
},
{
key: 'audio-dash',
container: 'fmp4',
elementaryStreams: ['audio-stream0'],
},
],
manifests: [
{
fileName: 'manifest.m3u8',
type: 'HLS',
muxStreams: ['sd-hls'],
},
{
fileName: 'manifest.mpd',
type: 'DASH',
muxStreams: ['sd-dash', 'audio-dash'],
},
],
},
},
};
// Run request
const [response] = await transcoderServiceClient.createJob(request);
console.log(`Job: ${response.name}`);
}
createJobWithEmbeddedCaptions();
Python
Antes de probar esta muestra, sigue las instrucciones de configuración Python que se encuentran en la Guía de inicio rápido de la API de Transcoder con bibliotecas cliente .
Para obtener más información, consulta la documentación de referencia de la API de Python de la API de Transcoder .
Para autenticarte en la API de Transcoder, configura las credenciales predeterminadas de la aplicación.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local .
import argparse
from google.cloud.video import transcoder_v1
from google.cloud.video.transcoder_v1.services.transcoder_service import (
TranscoderServiceClient,
)
def create_job_with_embedded_captions(
project_id: str,
location: str,
input_video_uri: str,
input_captions_uri: str,
output_uri: str,
) -> transcoder_v1.types.resources.Job:
"""Creates a job based on an ad-hoc job configuration that embeds closed captions in the output video.
Args:
project_id (str): The GCP project ID.
location (str): The location to start the job in.
input_video_uri (str): Uri of the input video in the Cloud Storage
bucket.
input_captions_uri (str): Uri of the input captions file in the Cloud
Storage bucket.
output_uri (str): 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.output_uri = output_uri
job.config = transcoder_v1.types.JobConfig(
inputs=[
transcoder_v1.types.Input(
key="input0",
uri=input_video_uri,
),
transcoder_v1.types.Input(
key="caption-input0",
uri=input_captions_uri,
),
],
edit_list=[
transcoder_v1.types.EditAtom(
key="atom0",
inputs=["input0", "caption-input0"],
),
],
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,
),
),
transcoder_v1.types.ElementaryStream(
key="cea-stream0",
text_stream=transcoder_v1.types.TextStream(
codec="cea608",
mapping_=[
transcoder_v1.types.TextStream.TextMapping(
atom_key="atom0",
input_key="caption-input0",
input_track=0,
),
],
language_code="en-US",
display_name="English",
),
),
],
mux_streams=[
transcoder_v1.types.MuxStream(
key="sd-hls",
container="ts",
elementary_streams=["video-stream0", "audio-stream0"],
),
transcoder_v1.types.MuxStream(
key="sd-dash",
container="fmp4",
elementary_streams=["video-stream0"],
),
transcoder_v1.types.MuxStream(
key="audio-dash",
container="fmp4",
elementary_streams=["audio-stream0"],
),
],
manifests=[
transcoder_v1.types.Manifest(
file_name="manifest.m3u8",
type_="HLS",
mux_streams=["sd-hls"],
),
transcoder_v1.types.Manifest(
file_name="manifest.mpd",
type_="DASH",
mux_streams=["sd-dash", "audio-dash"],
),
],
)
response = client.create_job(parent=parent, job=job)
print(f"Job: {response.name}")
return response
Agregar subtítulos
Para crear un trabajo que produzca archivos de subtítulos en varios idiomas reproducidos desde un manifiesto, haz lo siguiente:
Agrega un array inputs
a la configuración del trabajo.
Agrega un objeto Input
al array inputs
que define la clave y el URI del video de entrada asociado.
Agrega otro objeto Input
que defina el URI para el archivo de subtítulos de entrada.
Agrega un array editList
a la configuración. Este array se usa para agregar las entradas al cronograma del video de salida.
Agrega un objeto EditAtom
al array editList
que hace referencia a los objetos en el array inputs
por clave. Puedes designar un startTimeOffset
y un endTimeOffset
para cortar el video de entrada.
Para agregar las leyendas a los contenedores de salida, agrega un objeto textStream
al array elementaryStreams
.
Para el archivo de subtítulos independiente, especifica el contenedor en el array muxStream
. Consulta los objetos con las claves text-vtt-en
y text-vtt-es
en la siguiente configuración. Para los subtítulos incorporados , solo necesitas la transmisión primaria.
La siguiente configuración genera varios archivos WebVTT, uno para subtítulos en inglés y otro para subtítulos en español.
Nota: Los subtítulos solo se admiten en los manifiestos de HLS. Los subtítulos no son compatibles con los manifiestos DASH ni en archivos MP4.
Puedes agregar esta configuración a una plantilla de trabajo o incluirla en una configuración de trabajo ad hoc :
REST
Antes de usar cualquiera de los datos de solicitud a continuación, realiza los siguientes reemplazos:
PROJECT_ID
: El ID de tu proyecto de Google Cloud que aparece en Configuración de IAM .
LOCATION
: Es la ubicación en la que se ejecutará tu trabajo. Usa una de las regiones compatibles .
Mostrar ubicaciones
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
: Es el nombre del bucket de Cloud Storage que creaste.
STORAGE_INPUT_VIDEO
: Es el nombre de un video en tu bucket de Cloud Storage que transcodificas, como my-vid.mp4
.
Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_SUBTITLES_FILE1
: Es el nombre del archivo de subtítulos en el bucket de Cloud Storage, como subtitles-en.srt
para los subtítulos en inglés. Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/subtitles-en.srt
).
STORAGE_SUBTITLES_FILE2
: Es el nombre de otro archivo de subtítulos en tu bucket de Cloud Storage, como subtitles-es.srt
para subtítulos en español. Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/subtitles-es.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre de la carpeta de salida del bucket de Cloud Storage en la que deseas guardar los resultados de video codificados.
Nota: No necesitas crear el objeto de carpeta de salida antes de crear el trabajo. Cuando se procesa el trabajo, la API de Transcoder antepone automáticamente el nombre de la carpeta que especificas como parte de los nombres de los objetos guardados en Cloud Storage.
Para enviar tu solicitud, expande una de estas opciones:
curl (Linux, macOS o Cloud Shell)
Nota:
Con el siguiente comando, se supone que accediste a
la CLI de gcloud
con tu cuenta de usuario a través de la ejecución de
gcloud init
o
gcloud auth login
,
o a través del uso de
Cloud Shell ,
que accede de forma automática a la CLI de gcloud
.
Para comprobar la cuenta activa actual, ejecuta gcloud auth list
.
Guarda el cuerpo de la solicitud en un archivo llamado request.json
.
Ejecuta el comando siguiente en la terminal para crear o reemplazar este archivo en el directorio actual:
cat > request.json << 'EOF'
{
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_INPUT_VIDEO "
},
{
"key": "subtitle_input_en",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_SUBTITLES_FILE1 "
},
{
"key": "subtitle_input_es",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_SUBTITLES_FILE2 "
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0",
"subtitle_input_en",
"subtitle_input_es"
]
}
],
"elementaryStreams": [
{
"key": "video-stream0",
"videoStream": {
"h264": {
"heightPixels": 360,
"widthPixels": 640,
"bitrateBps": 550000,
"frameRate": 60
}
}
},
{
"key": "audio-stream0",
"audioStream": {
"codec": "aac",
"bitrateBps": 64000
}
},
{
"key": "vtt-stream-en",
"textStream": {
"codec": "webvtt",
"languageCode": "en-US",
"displayName": "English",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "subtitle_input_en"
}
]
}
},
{
"key": "vtt-stream-es",
"textStream": {
"codec": "webvtt",
"languageCode": "es-ES",
"displayName": "Spanish",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "subtitle_input_es"
}
]
}
}
],
"muxStreams": [
{
"key": "sd-hls-fmp4",
"container": "fmp4",
"elementaryStreams": [
"video-stream0"
]
},
{
"key": "audio-hls-fmp4",
"container": "fmp4",
"elementaryStreams": [
"audio-stream0"
]
},
{
"key": "text-vtt-en",
"container": "vtt",
"elementaryStreams": [
"vtt-stream-en"
],
"segmentSettings": {
"segmentDuration": "6s",
"individualSegments": true
}
},
{
"key": "text-vtt-es",
"container": "vtt",
"elementaryStreams": [
"vtt-stream-es"
],
"segmentSettings": {
"segmentDuration": "6s",
"individualSegments": true
}
}
],
"manifests": [
{
"fileName": "manifest.m3u8",
"type": "HLS",
"muxStreams": [
"sd-hls-fmp4",
"audio-hls-fmp4",
"text-vtt-en",
"text-vtt-es"
]
}
],
"output": {
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_OUTPUT_FOLDER /"
}
}
}
EOF
Luego, ejecuta el siguiente comando para enviar tu solicitud de 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)
Nota:
Con el siguiente comando, se supone que accediste a
la CLI de gcloud
con tu cuenta de usuario a través de la ejecución de
gcloud init
o
gcloud auth login
,
o a través del uso de
Cloud Shell ,
que accede de forma automática a la CLI de gcloud
.
Para comprobar la cuenta activa actual, ejecuta gcloud auth list
.
Guarda el cuerpo de la solicitud en un archivo llamado request.json
.
Ejecuta el comando siguiente en la terminal para crear o reemplazar este archivo en el directorio actual:
@'
{
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_INPUT_VIDEO "
},
{
"key": "subtitle_input_en",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_SUBTITLES_FILE1 "
},
{
"key": "subtitle_input_es",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_SUBTITLES_FILE2 "
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0",
"subtitle_input_en",
"subtitle_input_es"
]
}
],
"elementaryStreams": [
{
"key": "video-stream0",
"videoStream": {
"h264": {
"heightPixels": 360,
"widthPixels": 640,
"bitrateBps": 550000,
"frameRate": 60
}
}
},
{
"key": "audio-stream0",
"audioStream": {
"codec": "aac",
"bitrateBps": 64000
}
},
{
"key": "vtt-stream-en",
"textStream": {
"codec": "webvtt",
"languageCode": "en-US",
"displayName": "English",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "subtitle_input_en"
}
]
}
},
{
"key": "vtt-stream-es",
"textStream": {
"codec": "webvtt",
"languageCode": "es-ES",
"displayName": "Spanish",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "subtitle_input_es"
}
]
}
}
],
"muxStreams": [
{
"key": "sd-hls-fmp4",
"container": "fmp4",
"elementaryStreams": [
"video-stream0"
]
},
{
"key": "audio-hls-fmp4",
"container": "fmp4",
"elementaryStreams": [
"audio-stream0"
]
},
{
"key": "text-vtt-en",
"container": "vtt",
"elementaryStreams": [
"vtt-stream-en"
],
"segmentSettings": {
"segmentDuration": "6s",
"individualSegments": true
}
},
{
"key": "text-vtt-es",
"container": "vtt",
"elementaryStreams": [
"vtt-stream-es"
],
"segmentSettings": {
"segmentDuration": "6s",
"individualSegments": true
}
}
],
"manifests": [
{
"fileName": "manifest.m3u8",
"type": "HLS",
"muxStreams": [
"sd-hls-fmp4",
"audio-hls-fmp4",
"text-vtt-en",
"text-vtt-es"
]
}
],
"output": {
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_OUTPUT_FOLDER /"
}
}
}
'@ | Out-File -FilePath request.json -Encoding utf8
Luego, ejecuta el siguiente comando para enviar tu solicitud de 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
Deberías recibir una respuesta JSON similar a la que se muestra a continuación:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
gcloud
Antes de usar cualquiera de los datos de comando a continuación, haz los siguientes reemplazos:
LOCATION
: Es la ubicación en la que se ejecutará tu trabajo. Usa una de las regiones compatibles .
Mostrar ubicaciones
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
: Es el nombre del bucket de Cloud Storage que creaste.
STORAGE_INPUT_VIDEO
: Es el nombre de un video en tu bucket de Cloud Storage que transcodificas, como my-vid.mp4
.
Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_SUBTITLES_FILE1
: Es el nombre del archivo de subtítulos en el bucket de Cloud Storage, como subtitles-en.srt
para los subtítulos en inglés. Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/subtitles-en.srt
).
STORAGE_SUBTITLES_FILE2
: Es el nombre de otro archivo de subtítulos en tu bucket de Cloud Storage, como subtitles-es.srt
para subtítulos en español. Este campo debe incluir todas las carpetas que creaste en el bucket (por ejemplo, input/subtitles-es.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre de la carpeta de salida del bucket de Cloud Storage en la que deseas guardar los resultados de video codificados.
Nota: No necesitas crear el objeto de carpeta de salida antes de crear el trabajo. Cuando se procesa el trabajo, la API de Transcoder antepone automáticamente el nombre de la carpeta que especificas como parte de los nombres de los objetos guardados en Cloud Storage.
Guarda el siguiente código en un archivo llamado request.json
.
{
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_INPUT_VIDEO "
},
{
"key": "subtitle_input_en",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_SUBTITLES_FILE1 "
},
{
"key": "subtitle_input_es",
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_SUBTITLES_FILE2 "
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0",
"subtitle_input_en",
"subtitle_input_es"
]
}
],
"elementaryStreams": [
{
"key": "video-stream0",
"videoStream": {
"h264": {
"heightPixels": 360,
"widthPixels": 640,
"bitrateBps": 550000,
"frameRate": 60
}
}
},
{
"key": "audio-stream0",
"audioStream": {
"codec": "aac",
"bitrateBps": 64000
}
},
{
"key": "vtt-stream-en",
"textStream": {
"codec": "webvtt",
"languageCode": "en-US",
"displayName": "English",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "subtitle_input_en"
}
]
}
},
{
"key": "vtt-stream-es",
"textStream": {
"codec": "webvtt",
"languageCode": "es-ES",
"displayName": "Spanish",
"mapping": [
{
"atomKey": "atom0",
"inputKey": "subtitle_input_es"
}
]
}
}
],
"muxStreams": [
{
"key": "sd-hls-fmp4",
"container": "fmp4",
"elementaryStreams": [
"video-stream0"
]
},
{
"key": "audio-hls-fmp4",
"container": "fmp4",
"elementaryStreams": [
"audio-stream0"
]
},
{
"key": "text-vtt-en",
"container": "vtt",
"elementaryStreams": [
"vtt-stream-en"
],
"segmentSettings": {
"segmentDuration": "6s",
"individualSegments": true
}
},
{
"key": "text-vtt-es",
"container": "vtt",
"elementaryStreams": [
"vtt-stream-es"
],
"segmentSettings": {
"segmentDuration": "6s",
"individualSegments": true
}
}
],
"manifests": [
{
"fileName": "manifest.m3u8",
"type": "HLS",
"muxStreams": [
"sd-hls-fmp4",
"audio-hls-fmp4",
"text-vtt-en",
"text-vtt-es"
]
}
],
"output": {
"uri": "gs://STORAGE_BUCKET_NAME /STORAGE_OUTPUT_FOLDER /"
}
}
}
Ejecuta el siguiente comando:
Linux, macOS o Cloud Shell
gcloud transcoder jobs create --location=LOCATION --file=request.json
Windows (PowerShell)
gcloud transcoder jobs create --location=LOCATION --file=request.json
Windows (cmd.exe)
gcloud transcoder jobs create --location=LOCATION --file=request.json
Deberías recibir una respuesta similar a la que figura a continuación:
{
"name": "projects/PROJECT_NUMBER /locations/LOCATION /jobs/JOB_ID ",
"config": {
...
},
"state": "PENDING",
"createTime": CREATE_TIME ,
"ttlAfterCompletionDays": 30
}
Go
Antes de probar esta muestra, sigue las instrucciones de configuración Go que se encuentran en la Guía de inicio rápido de la API de Transcoder con bibliotecas cliente .
Para obtener más información, consulta la documentación de referencia de la API de Go de la API de Transcoder .
Para autenticarte en la API de Transcoder, configura las credenciales predeterminadas de la aplicación.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local .
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"
)
// createJobWithStandaloneCaptions creates a job that can use subtitles from a
// standalone file. See https://cloud.google.com/transcoder/docs/how-to/captions-and-subtitles
// for more information.
func createJobWithStandaloneCaptions(w io.Writer, projectID string, location string, inputVideoURI string, inputSubtitles1URI string, inputSubtitles2URI string, outputURI string) error {
// projectID := "my-project-id"
// location := "us-central1"
// inputVideoURI := "gs://my-bucket/my-video-file"
// inputSubtitles1URI := "gs://my-bucket/my-subtitles-file1"
// inputSubtitles2URI := "gs://my-bucket/my-subtitles-file2"
// 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()
// Set up elementary streams. The InputKey field refers to inputs in
// the Inputs array defined the job config.
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,
},
},
},
{
Key: "vtt_stream_en",
ElementaryStream: &transcoderpb.ElementaryStream_TextStream{
TextStream: &transcoderpb.TextStream{
Codec: "webvtt",
LanguageCode: "en-US",
DisplayName: "English",
Mapping: []*transcoderpb.TextStream_TextMapping{
{
AtomKey: "atom0",
InputKey: "subtitle_input_en",
},
},
},
},
},
{
Key: "vtt_stream_es",
ElementaryStream: &transcoderpb.ElementaryStream_TextStream{
TextStream: &transcoderpb.TextStream{
Codec: "webvtt",
LanguageCode: "es-ES",
DisplayName: "Spanish",
Mapping: []*transcoderpb.TextStream_TextMapping{
{
AtomKey: "atom0",
InputKey: "subtitle_input_es",
},
},
},
},
},
}
req := &transcoderpb.CreateJobRequest{
Parent: fmt.Sprintf("projects/%s/locations/%s", projectID, location),
Job: &transcoderpb.Job{
OutputUri: outputURI,
JobConfig: &transcoderpb.Job_Config{
Config: &transcoderpb.JobConfig{
Inputs: []*transcoderpb.Input{
{
Key: "input0",
Uri: inputVideoURI,
},
{
Key: "subtitle_input_en",
Uri: inputSubtitles1URI,
},
{
Key: "subtitle_input_es",
Uri: inputSubtitles2URI,
},
},
EditList: []*transcoderpb.EditAtom{
{
Key: "atom0",
Inputs: []string{"input0", "subtitle_input_en", "subtitle_input_es"},
},
},
ElementaryStreams: elementaryStreams,
MuxStreams: []*transcoderpb.MuxStream{
{
Key: "sd-hls-fmp4",
Container: "fmp4",
ElementaryStreams: []string{"video_stream0"},
},
{
Key: "audio-hls-fmp4",
Container: "fmp4",
ElementaryStreams: []string{"audio_stream0"},
},
{
Key: "text-vtt-en",
Container: "vtt",
ElementaryStreams: []string{"vtt_stream_en"},
SegmentSettings: &transcoderpb.SegmentSettings{
SegmentDuration: &duration.Duration{
Seconds: 6,
},
IndividualSegments: true,
},
},
{
Key: "text-vtt-es",
Container: "vtt",
ElementaryStreams: []string{"vtt_stream_es"},
SegmentSettings: &transcoderpb.SegmentSettings{
SegmentDuration: &duration.Duration{
Seconds: 6,
},
IndividualSegments: true,
},
},
},
Manifests: []*transcoderpb.Manifest{
{
FileName: "manifest.m3u8",
Type: transcoderpb.Manifest_HLS,
MuxStreams: []string{"sd-hls-fmp4", "audio-hls-fmp4", "text-vtt-en", "text-vtt-es"},
},
},
},
},
},
}
// 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("CreateJob: %w", err)
}
fmt.Fprintf(w, "Job: %v", response.GetName())
return nil
}
Node.js
Antes de probar esta muestra, sigue las instrucciones de configuración Node.js que se encuentran en la Guía de inicio rápido de la API de Transcoder con bibliotecas cliente .
Para obtener más información, consulta la documentación de referencia de la API de Node.js de la API de Transcoder .
Para autenticarte en la API de Transcoder, configura las credenciales predeterminadas de la aplicación.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local .
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// projectId = 'my-project-id';
// location = 'us-central1';
// inputVideoUri = 'gs://my-bucket/my-video-file';
// inputSubtitles1Uri = 'gs://my-bucket/my-captions-file1';
// inputSubtitles2Uri = 'gs://my-bucket/my-captions-file2';
// 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 createJobWithStandaloneCaptions() {
// Construct request
const request = {
parent: transcoderServiceClient.locationPath(projectId, location),
job: {
outputUri: outputUri,
config: {
inputs: [
{
key: 'input0',
uri: inputVideoUri,
},
{
key: 'subtitle_input_en',
uri: inputSubtitles1Uri,
},
{
key: 'subtitle_input_es',
uri: inputSubtitles2Uri,
},
],
editList: [
{
key: 'atom0',
inputs: ['input0', 'subtitle_input_en', 'subtitle_input_es'],
},
],
elementaryStreams: [
{
key: 'video-stream0',
videoStream: {
h264: {
heightPixels: 360,
widthPixels: 640,
bitrateBps: 550000,
frameRate: 60,
},
},
},
{
key: 'audio-stream0',
audioStream: {
codec: 'aac',
bitrateBps: 64000,
},
},
{
key: 'vtt-stream-en',
textStream: {
codec: 'webvtt',
languageCode: 'en-US',
displayName: 'English',
mapping: [
{
atomKey: 'atom0',
inputKey: 'subtitle_input_en',
},
],
},
},
{
key: 'vtt-stream-es',
textStream: {
codec: 'webvtt',
languageCode: 'es-ES',
displayName: 'Spanish',
mapping: [
{
atomKey: 'atom0',
inputKey: 'subtitle_input_es',
},
],
},
},
],
muxStreams: [
{
key: 'sd-hls-fmp4',
container: 'fmp4',
elementaryStreams: ['video-stream0'],
},
{
key: 'audio-hls-fmp4',
container: 'fmp4',
elementaryStreams: ['audio-stream0'],
},
{
key: 'text-vtt-en',
container: 'vtt',
elementaryStreams: ['vtt-stream-en'],
segmentSettings: {
segmentDuration: {
seconds: 6,
},
individualSegments: true,
},
},
{
key: 'text-vtt-es',
container: 'vtt',
elementaryStreams: ['vtt-stream-es'],
segmentSettings: {
segmentDuration: {
seconds: 6,
},
individualSegments: true,
},
},
],
manifests: [
{
fileName: 'manifest.m3u8',
type: 'HLS',
muxStreams: [
'sd-hls-fmp4',
'audio-hls-fmp4',
'text-vtt-en',
'text-vtt-es',
],
},
],
},
},
};
// Run request
const [response] = await transcoderServiceClient.createJob(request);
console.log(`Job: ${response.name}`);
}
createJobWithStandaloneCaptions();
Python
Antes de probar esta muestra, sigue las instrucciones de configuración Python que se encuentran en la Guía de inicio rápido de la API de Transcoder con bibliotecas cliente .
Para obtener más información, consulta la documentación de referencia de la API de Python de la API de Transcoder .
Para autenticarte en la API de Transcoder, configura las credenciales predeterminadas de la aplicación.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local .
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_standalone_captions(
project_id: str,
location: str,
input_video_uri: str,
input_subtitles1_uri: str,
input_subtitles2_uri: str,
output_uri: str,
) -> transcoder_v1.types.resources.Job:
"""Creates a job based on an ad-hoc job configuration that can use subtitles from a standalone file.
Args:
project_id (str): The GCP project ID.
location (str): The location to start the job in.
input_video_uri (str): Uri of the input video in the Cloud Storage
bucket.
input_subtitles1_uri (str): Uri of an input subtitles file in the Cloud
Storage bucket.
input_subtitles2_uri (str): Uri of an input subtitles file in the Cloud
Storage bucket.
output_uri (str): 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.output_uri = output_uri
job.config = transcoder_v1.types.JobConfig(
inputs=[
transcoder_v1.types.Input(
key="input0",
uri=input_video_uri,
),
transcoder_v1.types.Input(
key="subtitle-input-en",
uri=input_subtitles1_uri,
),
transcoder_v1.types.Input(
key="subtitle-input-es",
uri=input_subtitles2_uri,
),
],
edit_list=[
transcoder_v1.types.EditAtom(
key="atom0",
inputs=["input0", "subtitle-input-en", "subtitle-input-es"],
),
],
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,
),
),
transcoder_v1.types.ElementaryStream(
key="vtt-stream-en",
text_stream=transcoder_v1.types.TextStream(
codec="webvtt",
language_code="en-US",
display_name="English",
mapping_=[
transcoder_v1.types.TextStream.TextMapping(
atom_key="atom0",
input_key="subtitle-input-en",
),
],
),
),
transcoder_v1.types.ElementaryStream(
key="vtt-stream-es",
text_stream=transcoder_v1.types.TextStream(
codec="webvtt",
language_code="es-ES",
display_name="Spanish",
mapping_=[
transcoder_v1.types.TextStream.TextMapping(
atom_key="atom0",
input_key="subtitle-input-es",
),
],
),
),
],
mux_streams=[
transcoder_v1.types.MuxStream(
key="sd-hls-fmp4",
container="fmp4",
elementary_streams=["video-stream0"],
),
transcoder_v1.types.MuxStream(
key="audio-hls-fmp4",
container="fmp4",
elementary_streams=["audio-stream0"],
),
transcoder_v1.types.MuxStream(
key="text-vtt-en",
container="vtt",
elementary_streams=["vtt-stream-en"],
segment_settings=transcoder_v1.types.SegmentSettings(
segment_duration=duration.Duration(
seconds=6,
),
individual_segments=True,
),
),
transcoder_v1.types.MuxStream(
key="text-vtt-es",
container="vtt",
elementary_streams=["vtt-stream-es"],
segment_settings=transcoder_v1.types.SegmentSettings(
segment_duration=duration.Duration(
seconds=6,
),
individual_segments=True,
),
),
],
manifests=[
transcoder_v1.types.Manifest(
file_name="manifest.m3u8",
type_="HLS",
mux_streams=[
"sd-hls-fmp4",
"audio-hls-fmp4",
"text-vtt-en",
"text-vtt-es",
],
),
],
)
response = client.create_job(parent=parent, job=job)
print(f"Job: {response.name}")
return response
Reproduce el video
Para ver los subtítulos en Windows, reproduce el video en la app de Películas y TV. Asegúrate de seleccionar la pista de subtítulos.
Para ver los subtítulos en macOS o Linux, puedes reproducir el video en el reproductor Shaka . Asegúrate de habilitar los subtítulos en el menú Subtítulos .
Para reproducir el archivo multimedia generado en Shaka Player , sigue estos pasos:
Configura el bucket de Cloud Storage para que sea legible de forma pública .
Para habilitar el uso compartido de recursos entre dominios (CORS) en un bucket de Cloud Storage , haz lo siguiente:
Crea un archivo JSON que contenga la siguiente información:
[
{
"origin": ["https://shaka-player-demo.appspot.com/"],
"responseHeader": ["Content-Type", "Range"],
"method": ["GET", "HEAD"],
"maxAgeSeconds": 3600
}
]
Ejecuta el siguiente comando después de reemplazar JSON_FILE_NAME por el nombre del archivo JSON que creaste en el paso anterior:
gsutil cors set JSON_FILE_NAME .json gs://STORAGE_BUCKET_NAME
Elige uno de los archivos MP4 o de manifiesto que generó el trabajo de transcodificación en el bucket de Cloud Storage.
Haz clic en Copiar URL , en la columna Acceso público del archivo.
Navega a Shaka Player , un reproductor en línea de transmisión en vivo.
Haz clic en Contenido personalizado en la barra de navegación superior.
Haz clic en el botón + .
Pega la URL pública del archivo en la casilla URL del manifiesto .
Escribe un nombre en el cuadro Nombre .
Haz clic en Guardar .
Haz clic en Play! .
Selecciona el botón de puntos suspensivos en la parte inferior derecha del reproductor y habilita los subtítulos.
Nota: No todos los reproductores multimedia admiten subtítulos. Consulta la documentación del reproductor.
Ejemplo
Puedes usar los siguientes archivos para un trabajo de prueba:
El archivo de subtítulos de entrada no debe contener líneas en blanco entre las líneas de texto.