En esta página se explica cómo agregar subtítulos a un video de salida.
Los subtítulos (también conocidos como subtítulos ) son la representación visual del audio de un video. Cerradas
los subtítulos suelen estar en el mismo idioma que el audio y, además, incluyen un fondo
los sonidos y las bocinas.
Los subtítulos suelen usarse para traducir el diálogo de un video en una
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 referirse a un archivo de texto que contiene
subtítulos. Este archivo se proporciona como una entrada para un trabajo.
Agregar subtítulos a una configuración de trabajo
Consulta las
entradas y salidas admitidas
para conocer los formatos de archivo de subtítulos de entrada compatibles. 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 un trabajo.
configuración. En esta página, se da por sentado que conoces
JobConfig . Más información
sobre la creación de 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:
lo siguiente:
Agrega un
Array inputs
hasta el inicio de la configuración del trabajo.
Agrega un objeto Input
.
al array inputs
que define la clave y el URI para la entrada asociada
video.
Agregar otra Input
que incluye 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
editList
a la configuración del trabajo. Este array se usa para agregar entradas al
línea de tiempo de salida de video.
Agrega un elemento EditAtom
objeto al array editList
. Esta
Objeto EditAtom
debe hacer referencia a las teclas del video de entrada y los subtítulos que agregaste en la
Array inputs
. Puedes designar un startTimeOffset
y un endTimeOffset
como
cortar el video de entrada.
Agrega las leyendas a los contenedores de salida con una
textStream
el objeto de escucha
elementaryStreams
. Solo se admite una transmisión de texto incorporada y se agrega a todos
videos de salida (ya que hay un único cronograma de salida).
Usa el
mapping
en la
textStream
de configuración para hacer referencia al
objeto EditAtom
.
El siguiente ejemplo de configuración incorpora subtítulos CEA-608 en un video.
Puedes agregar esta configuración a un
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
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-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 estás transcodificando, como my-vid.mp4
.
Este campo debe tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_CAPTIONS_FILE
: Es el nombre de los subtítulos.
de tu bucket de Cloud Storage, como captions.srt
.
Este campo debe tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/captions.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre del
de salida del bucket de Cloud Storage en la que quieres guardar las salidas de video codificadas.
Nota: No necesitas crear el objeto de carpeta de salida antes
creando el trabajo. Cuando procesa el trabajo, la API de Transcoder antepone automáticamente el
nombre de la carpeta que especifiques 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)
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, realiza 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
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-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 estás transcodificando, como my-vid.mp4
.
Este campo debe tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_CAPTIONS_FILE
: Es el nombre de los subtítulos.
de tu bucket de Cloud Storage, como captions.srt
.
Este campo debe tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/captions.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre del
de salida del bucket de Cloud Storage en la que quieres guardar las salidas de video codificadas.
Nota: No necesitas crear el objeto de carpeta de salida antes
creando el trabajo. Cuando procesa el trabajo, la API de Transcoder antepone automáticamente el
nombre de la carpeta que especifiques 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 de Go que se encuentran en el
Guía de inicio rápido de la API de Transcoder con
bibliotecas cliente .
Para obtener más información, consulta la
API de Go de la API de Transcoder
documentación de referencia .
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 de Node.js que se encuentran en el
Guía de inicio rápido de la API de Transcoder con
bibliotecas cliente .
Para obtener más información, consulta la
API de Node.js de la API de Transcoder
documentación de referencia .
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 de Python que se encuentran en el
Guía de inicio rápido de la API de Transcoder con
bibliotecas cliente .
Para obtener más información, consulta la
API de Python de la API de Transcoder
documentación de referencia .
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:
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 para la entrada asociada
video.
Agregar otra Input
que define el URI para el archivo de subtítulos de entrada.
Agrega un
editList
a la configuración. Este array se usa para agregar las entradas al
línea de tiempo de salida de video.
Agrega un elemento EditAtom
objeto al array editList
que hace referencia a los objetos en inputs
array por clave. Puedes designar un startTimeOffset
y un endTimeOffset
como
cortar el video de entrada.
Agrega las leyendas a los contenedores de salida con una
textStream
el objeto de escucha
elementaryStreams
.
Para el archivo de subtítulos independiente, especifica el contenedor en la
muxStream
array;
consulta los objetos con claves text-vtt-en
y text-vtt-es
en la siguiente
configuración. En el caso de los subtítulos incorporados , solo necesitas los
de flujo elemental.
La siguiente configuración genera varios archivos WebVTT, uno para inglés
y otra para subtítulos en español.
Nota: Los subtítulos solo se admiten en manifiestos de HLS. No se admiten los subtítulos
en manifiestos de DASH o archivos MP4.
Puedes agregar esta configuración a un
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
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-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 estás transcodificando, como my-vid.mp4
.
Este campo debe tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_SUBTITLES_FILE1
: Es el nombre del
archivo de subtítulos en tu bucket de Cloud Storage, como subtitles-en.srt
para subtítulos en inglés. Este campo debe tener en cuenta todas las carpetas que hayas creado en la
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 tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/subtitles-es.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre del
de salida del bucket de Cloud Storage en la que quieres guardar las salidas de video codificadas.
Nota: No necesitas crear el objeto de carpeta de salida antes
creando el trabajo. Cuando procesa el trabajo, la API de Transcoder antepone automáticamente el
nombre de la carpeta que especifiques 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)
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, realiza 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
northamerica-northeast1
asia-east1
asia-northeast1
asia-northeast3
asia-south1
asia-southeast1
australia-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 estás transcodificando, como my-vid.mp4
.
Este campo debe tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/my-vid.mp4
).
STORAGE_SUBTITLES_FILE1
: Es el nombre del
archivo de subtítulos en tu bucket de Cloud Storage, como subtitles-en.srt
para subtítulos en inglés. Este campo debe tener en cuenta todas las carpetas que hayas creado en la
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 tener en cuenta todas las carpetas que hayas creado en la
bucket (por ejemplo, input/subtitles-es.srt
).
STORAGE_OUTPUT_FOLDER
: Es el nombre del
de salida del bucket de Cloud Storage en la que quieres guardar las salidas de video codificadas.
Nota: No necesitas crear el objeto de carpeta de salida antes
creando el trabajo. Cuando procesa el trabajo, la API de Transcoder antepone automáticamente el
nombre de la carpeta que especifiques 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 de Go que se encuentran en el
Guía de inicio rápido de la API de Transcoder con
bibliotecas cliente .
Para obtener más información, consulta la
API de Go de la API de Transcoder
documentación de referencia .
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 de Node.js que se encuentran en el
Guía de inicio rápido de la API de Transcoder con
bibliotecas cliente .
Para obtener más información, consulta la
API de Node.js de la API de Transcoder
documentación de referencia .
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 de Python que se encuentran en el
Guía de inicio rápido de la API de Transcoder con
bibliotecas cliente .
Para obtener más información, consulta la
API de Python de la API de Transcoder
documentación de referencia .
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 títulos o subtítulos en Windows, reproduce el video en la pestaña Movies & app para TVs. Marca
asegúrate de seleccionar la pista de subtítulos.
Para ver los subtítulos en MacOS o Linux, puedes reproducir el video en
Shaka Player . Asegúrate de
habilita los subtítulos desde 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 multiorigen (CORS) en un depósito de Cloud Storage , haz lo siguiente:
Crea un archivo JSON que contenga lo siguiente:
[
{
"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:
gcloud storage buckets update gs://STORAGE_BUCKET_NAME --cors-file=JSON_FILE_NAME .json
Elige uno de los archivos de manifiesto o MP4 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 habilítalo
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 líneas de texto.