新增隱藏式輔助字幕和字幕

本頁說明如何在輸出影片中加入隱藏式輔助字幕和一般字幕。

隱藏式輔助字幕 (或簡稱字幕) 是以文字呈現影片的語音內容。隱藏式輔助字幕通常與音訊語言相同,並包含背景音效和說話者變化。

字幕通常用於將影片對白翻譯成其他語言。字幕通常不會顯示背景音效和說話者變更。

本頁面使用「輸入字幕檔」一詞,指內含隱藏式輔助字幕或字幕的文字檔。您會將這個檔案提供給工作做為輸入內容。

在工作設定中新增字幕

如要瞭解支援的輸入字幕檔案格式,請參閱支援的輸入和輸出。我們提供範例影片檔和範例輸入字幕檔,供您測試設定。

請使用下列各節中的資訊,在工作設定中新增說明文字和字幕。本頁面假設您熟悉基本的 JobConfig。如要進一步瞭解如何建立轉碼工作,請參閱建立及管理工作

新增字幕

如要建立工作,將字幕嵌入輸出影片檔案容器,請執行下列操作:

  1. 在工作設定開頭新增 inputs 陣列。

  2. Input 物件新增至 inputs 陣列,定義相關聯輸入影片的鍵和 URI。

  3. 新增另一個 Input 物件,其中包含輸入字幕檔的路徑。

  4. 在工作設定中新增 editList 陣列。這個陣列用於將輸入內容新增至輸出影片時間軸。

  5. EditAtom 物件新增至 editList 陣列。這個 EditAtom 物件必須參照您在 inputs 陣列中新增的輸入影片和字幕金鑰。您可以指定 startTimeOffsetendTimeOffset,藉此剪輯輸入影片。

  6. textStream 物件新增至 elementaryStreams 陣列,即可將說明文字新增至輸出容器。系統僅支援一個內嵌文字串流,並會將其新增至所有輸出影片 (因為只有一個輸出時間軸)。

  7. textStream 設定物件中使用 mapping 陣列,參照 EditAtom 物件鍵。

以下範例設定會在影片中嵌入 CEA-608 隱藏式輔助字幕。

您可以將這項設定新增至工作範本,或納入臨時工作設定

REST

使用任何要求資料之前,請先替換以下項目:

  • PROJECT_IDIAM 設定中列出的 Google Cloud 專案 ID。
  • LOCATION:工作執行的位置。使用支援的地區
    顯示地區
    • 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
    • me-west1
    • me-central1
    • me-central2
  • STORAGE_BUCKET_NAME:您建立的 Cloud Storage bucket 名稱。
  • STORAGE_INPUT_VIDEO:Cloud Storage 值區中要轉碼的影片名稱,例如 my-vid.mp4。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/my-vid.mp4)。
  • STORAGE_CAPTIONS_FILE:Cloud Storage 值區中字幕檔案的名稱,例如 captions.srt。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/captions.srt)。
  • STORAGE_OUTPUT_FOLDER:Cloud Storage bucket 中輸出資料夾的名稱,您要將編碼後的影片輸出內容儲存至該資料夾。

如要傳送要求,請展開以下其中一個選項:

您應該會收到如下的 JSON 回應:

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

gcloud

使用下列任何指令資料之前,請先替換以下項目:

  • LOCATION:工作執行的位置。使用支援的地區
    顯示地區
    • 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
    • me-west1
    • me-central1
    • me-central2
  • STORAGE_BUCKET_NAME:您建立的 Cloud Storage bucket 名稱。
  • STORAGE_INPUT_VIDEO:Cloud Storage 值區中要轉碼的影片名稱,例如 my-vid.mp4。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/my-vid.mp4)。
  • STORAGE_CAPTIONS_FILE:Cloud Storage 值區中字幕檔案的名稱,例如 captions.srt。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/captions.srt)。
  • STORAGE_OUTPUT_FOLDER:Cloud Storage bucket 中輸出資料夾的名稱,您要將編碼後的影片輸出內容儲存至該資料夾。

將下列內容儲存到名為 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/"     }   } }

執行下列指令:

Linux、macOS 或 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

您應該會收到類似以下的回應:

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

Go

在試用這個範例之前,請先按照Go使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Go API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

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 } 

Java

在試用這個範例之前,請先按照Java使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Java API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

 import com.google.cloud.video.transcoder.v1.AudioStream; import com.google.cloud.video.transcoder.v1.CreateJobRequest; import com.google.cloud.video.transcoder.v1.EditAtom; import com.google.cloud.video.transcoder.v1.ElementaryStream; import com.google.cloud.video.transcoder.v1.Input; import com.google.cloud.video.transcoder.v1.Job; import com.google.cloud.video.transcoder.v1.JobConfig; import com.google.cloud.video.transcoder.v1.LocationName; import com.google.cloud.video.transcoder.v1.Manifest; import com.google.cloud.video.transcoder.v1.Manifest.ManifestType; import com.google.cloud.video.transcoder.v1.MuxStream; import com.google.cloud.video.transcoder.v1.Output; import com.google.cloud.video.transcoder.v1.TextStream; import com.google.cloud.video.transcoder.v1.TextStream.TextMapping; import com.google.cloud.video.transcoder.v1.TranscoderServiceClient; import com.google.cloud.video.transcoder.v1.VideoStream; import java.io.IOException;  public class CreateJobWithEmbeddedCaptions {    public static void main(String[] args) throws IOException {     // TODO(developer): Replace these variables before running the sample.     String projectId = "my-project-id";     String location = "us-central1";     String inputVideoUri = "gs://my-bucket/my-video-file";     String inputCaptionsUri = "gs://my-bucket/my-captions-file";     String outputUri = "gs://my-bucket/my-output-folder/";      createJobWithEmbeddedCaptions(projectId, location, inputVideoUri, inputCaptionsUri, outputUri);   }    // Creates a job from an ad-hoc configuration that embeds captions in the output video.   public static void createJobWithEmbeddedCaptions(       String projectId,       String location,       String inputVideoUri,       String inputCaptionsUri,       String outputUri)       throws IOException {     // Initialize client that will be used to send requests. This client only needs to be created     // once, and can be reused for multiple requests.     try (TranscoderServiceClient transcoderServiceClient = TranscoderServiceClient.create()) {        VideoStream videoStream0 =           VideoStream.newBuilder()               .setH264(                   VideoStream.H264CodecSettings.newBuilder()                       .setBitrateBps(550000)                       .setFrameRate(60)                       .setHeightPixels(360)                       .setWidthPixels(640))               .build();        AudioStream audioStream0 =           AudioStream.newBuilder().setCodec("aac").setBitrateBps(64000).build();        TextStream textStream0 =           TextStream.newBuilder()               .setCodec("cea608")               .addMapping(                   0,                   TextMapping.newBuilder()                       .setAtomKey("atom0")                       .setInputKey("caption_input0")                       .setInputTrack(0)                       .build())               .build();        JobConfig config =           JobConfig.newBuilder()               .addInputs(Input.newBuilder().setKey("input0").setUri(inputVideoUri))               .addInputs(Input.newBuilder().setKey("caption_input0").setUri(inputCaptionsUri))               .addEditList(                   0, // Index in the edit list                   EditAtom.newBuilder()                       .setKey("atom0")                       .addInputs("input0")                       .addInputs("caption_input0")                       .build())               .setOutput(Output.newBuilder().setUri(outputUri))               .addElementaryStreams(                   ElementaryStream.newBuilder()                       .setKey("video_stream0")                       .setVideoStream(videoStream0))               .addElementaryStreams(                   ElementaryStream.newBuilder()                       .setKey("audio_stream0")                       .setAudioStream(audioStream0))               .addElementaryStreams(                   ElementaryStream.newBuilder().setKey("cea_stream0").setTextStream(textStream0))               .addMuxStreams(                   0,                   MuxStream.newBuilder()                       .setKey("sd")                       .setContainer("mp4")                       .addElementaryStreams("video_stream0")                       .addElementaryStreams("audio_stream0")                       .build())               .addMuxStreams(                   1,                   MuxStream.newBuilder()                       .setKey("sd_hls")                       .setContainer("ts")                       .addElementaryStreams("video_stream0")                       .addElementaryStreams("audio_stream0")                       .build())               .addMuxStreams(                   2,                   MuxStream.newBuilder()                       .setKey("sd_dash")                       .setContainer("fmp4")                       .addElementaryStreams("video_stream0")                       .build())               .addMuxStreams(                   3,                   MuxStream.newBuilder()                       .setKey("audio_dash")                       .setContainer("fmp4")                       .addElementaryStreams("audio_stream0")                       .build())               .addManifests(                   0,                   Manifest.newBuilder()                       .setFileName("manifest.m3u8")                       .setType(ManifestType.HLS)                       .addMuxStreams("sd_hls")                       .build())               .addManifests(                   1,                   Manifest.newBuilder()                       .setFileName("manifest.mpd")                       .setType(ManifestType.DASH)                       .addMuxStreams("sd_dash")                       .addMuxStreams("audio_dash")                       .build())               .build();        CreateJobRequest createJobRequest =           CreateJobRequest.newBuilder()               .setJob(Job.newBuilder().setOutputUri(outputUri).setConfig(config).build())               .setParent(LocationName.of(projectId, location).toString())               .build();        // Send the job creation request and process the response.       Job job = transcoderServiceClient.createJob(createJobRequest);       System.out.println("Job: " + job.getName());     }   } }

Node.js

在試用這個範例之前,請先按照Node.js使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Node.js API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

/**  * 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

在試用這個範例之前,請先按照Python使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Python API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

 import argparse  from google.cloud.video import transcoder_v1 from google.cloud.video.transcoder_v1.services.transcoder_service import (     TranscoderServiceClient, )   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  

新增字幕

如要建立工作,產生可從資訊清單播放的多語言字幕檔案,請按照下列步驟操作:

  1. 在工作設定中新增 inputs 陣列。

  2. Input 物件新增至 inputs 陣列,定義相關聯輸入影片的鍵和 URI。

  3. 新增另一個 Input 物件,定義輸入說明文字檔案的 URI。

  4. 在設定中新增 editList 陣列。這個陣列用於將輸入內容新增至輸出影片時間軸。

  5. EditAtom 物件新增至 editList 陣列,該陣列會依鍵參照 inputs 陣列中的物件。您可以指定 startTimeOffsetendTimeOffset,藉此剪輯輸入影片。

  6. textStream 物件新增至 elementaryStreams 陣列,即可將說明文字新增至輸出容器。

  7. 如果是獨立字幕檔,請在 muxStream 陣列中指定容器;請參閱下列設定中含有 text-vtt-entext-vtt-es 鍵的物件。如要使用內嵌字幕,只需要基本串流即可。

下列設定會產生多個 WebVTT 檔案,分別是英文和西班牙文字幕。WebVTT 檔案中的 DASH 字幕是以 fMP4 容器格式建立。

您可以將這項設定新增至工作範本,或納入臨時工作設定

REST

使用任何要求資料之前,請先替換以下項目:

  • PROJECT_IDIAM 設定中列出的 Google Cloud 專案 ID。
  • LOCATION:工作執行的位置。使用支援的地區
    顯示地區
    • 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
    • me-west1
    • me-central1
    • me-central2
  • STORAGE_BUCKET_NAME:您建立的 Cloud Storage bucket 名稱。
  • STORAGE_INPUT_VIDEO:Cloud Storage 值區中要轉碼的影片名稱,例如 my-vid.mp4。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/my-vid.mp4)。
  • STORAGE_SUBTITLES_FILE1:Cloud Storage 值區中的字幕檔案名稱,例如 subtitles-en.srt 代表英文字幕。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/subtitles-en.srt)。
  • STORAGE_SUBTITLES_FILE2:Cloud Storage 值區中其他字幕檔案的名稱,例如 subtitles-es.srt,代表西班牙文的字幕。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/subtitles-es.srt)。
  • STORAGE_OUTPUT_FOLDER:Cloud Storage bucket 中輸出資料夾的名稱,您要將編碼後的影片輸出內容儲存至該資料夾。

如要傳送要求,請展開以下其中一個選項:

您應該會收到如下的 JSON 回應:

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

gcloud

使用下列任何指令資料之前,請先替換以下項目:

  • LOCATION:工作執行的位置。使用支援的地區
    顯示地區
    • 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
    • me-west1
    • me-central1
    • me-central2
  • STORAGE_BUCKET_NAME:您建立的 Cloud Storage bucket 名稱。
  • STORAGE_INPUT_VIDEO:Cloud Storage 值區中要轉碼的影片名稱,例如 my-vid.mp4。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/my-vid.mp4)。
  • STORAGE_SUBTITLES_FILE1:Cloud Storage 值區中的字幕檔案名稱,例如 subtitles-en.srt 代表英文字幕。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/subtitles-en.srt)。
  • STORAGE_SUBTITLES_FILE2:Cloud Storage 值區中其他字幕檔案的名稱,例如 subtitles-es.srt,代表西班牙文的字幕。這個欄位應考量您在 bucket 中建立的任何資料夾 (例如 input/subtitles-es.srt)。
  • STORAGE_OUTPUT_FOLDER:Cloud Storage bucket 中輸出資料夾的名稱,您要將編碼後的影片輸出內容儲存至該資料夾。

將下列內容儲存到名為 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/"     }   } }

執行下列指令:

Linux、macOS 或 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

您應該會收到類似以下的回應:

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

Go

在試用這個範例之前,請先按照Go使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Go API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

import ( 	"context" 	"fmt" 	"io"  	"github.com/golang/protobuf/ptypes/duration"  	transcoder "cloud.google.com/go/video/transcoder/apiv1" 	"cloud.google.com/go/video/transcoder/apiv1/transcoderpb" )  // 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 } 

Java

在試用這個範例之前,請先按照Java使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Java API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

 import com.google.cloud.video.transcoder.v1.AudioStream; import com.google.cloud.video.transcoder.v1.CreateJobRequest; import com.google.cloud.video.transcoder.v1.EditAtom; import com.google.cloud.video.transcoder.v1.ElementaryStream; import com.google.cloud.video.transcoder.v1.Input; import com.google.cloud.video.transcoder.v1.Job; import com.google.cloud.video.transcoder.v1.JobConfig; import com.google.cloud.video.transcoder.v1.LocationName; import com.google.cloud.video.transcoder.v1.Manifest; import com.google.cloud.video.transcoder.v1.Manifest.ManifestType; import com.google.cloud.video.transcoder.v1.MuxStream; import com.google.cloud.video.transcoder.v1.Output; import com.google.cloud.video.transcoder.v1.SegmentSettings; import com.google.cloud.video.transcoder.v1.TextStream; import com.google.cloud.video.transcoder.v1.TextStream.TextMapping; import com.google.cloud.video.transcoder.v1.TranscoderServiceClient; import com.google.cloud.video.transcoder.v1.VideoStream; import com.google.protobuf.Duration; import java.io.IOException;  public class CreateJobWithStandaloneCaptions {    public static void main(String[] args) throws IOException {     // TODO(developer): Replace these variables before running the sample.     String projectId = "my-project-id";     String location = "us-central1";     String inputVideoUri = "gs://my-bucket/my-video-file";     String inputCaptionsUri = "gs://my-bucket/my-captions-file";     String outputUri = "gs://my-bucket/my-output-folder/";      createJobWithStandaloneCaptions(         projectId, location, inputVideoUri, inputCaptionsUri, outputUri);   }    // Creates a job from an ad-hoc configuration that can use captions from a standalone file.   public static void createJobWithStandaloneCaptions(       String projectId,       String location,       String inputVideoUri,       String inputCaptionsUri,       String outputUri)       throws IOException {     // Initialize client that will be used to send requests. This client only needs to be created     // once, and can be reused for multiple requests.     try (TranscoderServiceClient transcoderServiceClient = TranscoderServiceClient.create()) {        VideoStream videoStream0 =           VideoStream.newBuilder()               .setH264(                   VideoStream.H264CodecSettings.newBuilder()                       .setBitrateBps(550000)                       .setFrameRate(60)                       .setHeightPixels(360)                       .setWidthPixels(640))               .build();        AudioStream audioStream0 =           AudioStream.newBuilder().setCodec("aac").setBitrateBps(64000).build();        TextStream textStream0 =           TextStream.newBuilder()               .setCodec("webvtt")               .addMapping(                   0,                   TextMapping.newBuilder()                       .setAtomKey("atom0")                       .setInputKey("caption_input0")                       .setInputTrack(0)                       .build())               .build();        JobConfig config =           JobConfig.newBuilder()               .addInputs(Input.newBuilder().setKey("input0").setUri(inputVideoUri))               .addInputs(Input.newBuilder().setKey("caption_input0").setUri(inputCaptionsUri))               .addEditList(                   0, // Index in the edit list                   EditAtom.newBuilder()                       .setKey("atom0")                       .addInputs("input0")                       .addInputs("caption_input0")                       .build())               .setOutput(Output.newBuilder().setUri(outputUri))               .addElementaryStreams(                   ElementaryStream.newBuilder()                       .setKey("video_stream0")                       .setVideoStream(videoStream0))               .addElementaryStreams(                   ElementaryStream.newBuilder()                       .setKey("audio_stream0")                       .setAudioStream(audioStream0))               .addElementaryStreams(                   ElementaryStream.newBuilder().setKey("vtt_stream0").setTextStream(textStream0))               .addMuxStreams(                   0,                   MuxStream.newBuilder()                       .setKey("sd_hls_fmp4")                       .setContainer("fmp4")                       .addElementaryStreams("video_stream0")                       .build())               .addMuxStreams(                   1,                   MuxStream.newBuilder()                       .setKey("audio_hls_fmp4")                       .setContainer("fmp4")                       .addElementaryStreams("audio_stream0")                       .build())               .addMuxStreams(                   2,                   MuxStream.newBuilder()                       .setKey("text_vtt")                       .setContainer("vtt")                       .addElementaryStreams("vtt_stream0")                       .setSegmentSettings(                           SegmentSettings.newBuilder()                               .setSegmentDuration(Duration.newBuilder().setSeconds(6).build())                               .setIndividualSegments(true)                               .build())                       .build())               .addManifests(                   0,                   Manifest.newBuilder()                       .setFileName("manifest.m3u8")                       .setType(ManifestType.HLS)                       .addMuxStreams("sd_hls_fmp4")                       .addMuxStreams("audio_hls_fmp4")                       .addMuxStreams("text_vtt")                       .build())               .build();        CreateJobRequest createJobRequest =           CreateJobRequest.newBuilder()               .setJob(Job.newBuilder().setOutputUri(outputUri).setConfig(config).build())               .setParent(LocationName.of(projectId, location).toString())               .build();        // Send the job creation request and process the response.       Job job = transcoderServiceClient.createJob(createJobRequest);       System.out.println("Job: " + job.getName());     }   } }

Node.js

在試用這個範例之前,請先按照Node.js使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Node.js API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

/**  * 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

在試用這個範例之前,請先按照Python使用用戶端程式庫的 Transcoder API 快速入門中的設定說明操作。詳情請參閱 Transcoder API Python API 參考說明文件

如要向 Transcoder API 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

 import argparse  from google.cloud.video import transcoder_v1 from google.cloud.video.transcoder_v1.services.transcoder_service import (     TranscoderServiceClient, ) from google.protobuf import duration_pb2 as duration   def create_job_with_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  

播放影片

如要在 Windows 上查看隱藏式輔助字幕或字幕,請在「電影與電視」應用程式中播放影片,並選取字幕軌。

如要在 macOS 或 Linux 上查看字幕,請在 Shaka Player 中播放影片。請務必從「字幕」選單啟用隱藏式輔助字幕或字幕。

如要在 Shaka Player 中播放產生的媒體檔案,請完成下列步驟:

  1. 將您建立的 Cloud Storage bucket 設為可公開讀取
  2. 如要在 Cloud Storage bucket 上啟用跨源資源共享 (CORS),請按照下列步驟操作:
    1. 建立包含下列內容的 JSON 檔案:
      [   {     "origin": ["https://shaka-player-demo.appspot.com/"],     "responseHeader": ["Content-Type", "Range"],     "method": ["GET", "HEAD"],     "maxAgeSeconds": 3600   } ]
    2. 執行下列指令,並將 JSON_FILE_NAME 替換為您在上一個步驟中建立的 JSON 檔案名稱:
      gcloud storage buckets update gs://STORAGE_BUCKET_NAME --cors-file=JSON_FILE_NAME.json
  3. 從 Cloud Storage 值區中,挑選轉碼作業產生的其中一個 MP4 或資訊清單檔案。在該檔案的「Public access」(公開存取權) 資料欄中,按一下「Copy URL」(複製網址)
  4. 前往 Shaka Player (這是一個線上即時串流播放器)。
  5. 按一下頂端導覽列中的「Custom Content」(自訂內容)
  6. 按一下「+」按鈕。
  7. 將檔案的公開網址貼到「Manifest URL」(資訊清單網址) 方塊中。

    在 Shaka Player 中輸入檔案網址。

  8. 在「Name」(名稱) 方塊中輸入名稱。

  9. 按一下「Save」(儲存)

  10. 按一下「Play」(播放)

  11. 選取播放器右下方的省略號按鈕,然後啟用字幕。

範例

您可以使用下列檔案進行測試工作:

輸入的說明文字檔案不得在文字行之間包含空白行。