> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate and translate AI captions

> Generate and translate AI captions for Gcore-hosted or external MP4 videos with transcription tasks and downloadable VTT files.

## Customer Portal

To generate subtitles from the original audio and translate them into a language of choice, create corresponding tasks for the AI models.

Supported sources: MP4 videos stored on Gcore Video Hosting, or any external MP4 file accessible via HTTP or HTTPS.

**1. Choose the video**

In the [Gcore Customer Portal](https://portal.gcore.com), navigate to **Streaming** > **AI**. The **AI tasks** page opens.

![AI tasks page](https://mintcdn.com/gcore/g8X-owBxoALHKrba/images/docs/streaming/ai-video-service/generate-ai-subtitles-and-add-them-to-video/generate-captions-in-customer-portal/ai-tasks-page.png?fit=max\&auto=format\&n=g8X-owBxoALHKrba\&q=85\&s=0821566c4153855853389c0f193b931b)

In the **Origin URL** field, enter the link to the MP4 video. Two options are available:

* **Paste video origin URL**: provide a URL to the video location. The video must be accessible via HTTP or HTTPS.
* **Select from uploaded videos**: choose a video hosted on Gcore Video Hosting.

**2. Configure and generate captions**

In **Task type**, select **Transcribe & Translate Captions**.Choose the source and target languages:

* **Audio language**: select the language spoken in the video, or keep **Auto-detect** to detect it automatically. For videos with multiple spoken languages, keep **Auto-detect** so all languages are captured correctly.
* **Subtitles language**: select the original video language for transcription only, or a different language to translate the generated captions. To generate captions in multiple target languages, create a separate task for each language.
  Click **Generate task**.

![AI task with generate button highlighted](https://mintcdn.com/gcore/g8X-owBxoALHKrba/images/docs/streaming/ai-video-service/generate-ai-subtitles-and-add-them-to-video/generate-captions-in-customer-portal/generate-task.png?fit=max\&auto=format\&n=g8X-owBxoALHKrba\&q=85\&s=0fe3cf0be2fee0b053ed8d9ecac807b5)

> [!NOTE]
>
> We only charge for the successfully processed translation tasks.

**3. Download captions**

The task appears in the **AI tasks** table. Processing time depends on the video length. While processing, the status may cycle between **Started** and **Pending** as resources are allocated to each processing sub-stage; use the progress percentage to track overall progress. If a task fails, the **Failure** status is shown — create the task again.

![AI tasks table with refresh button highlighted](https://mintcdn.com/gcore/g8X-owBxoALHKrba/images/docs/streaming/ai-video-service/generate-ai-subtitles-and-add-them-to-video/generate-captions-in-customer-portal/tasks-table-refresh-button.png?fit=max\&auto=format\&n=g8X-owBxoALHKrba\&q=85\&s=b77c9dcc791b4be0e9142ad18cc0ddb1)

When the status changes to **Success**, click the task ID and select **Download VTT file** in the **Parsed result** section.

![AI task details dialog](https://mintcdn.com/gcore/g8X-owBxoALHKrba/images/docs/streaming/ai-video-service/generate-ai-subtitles-and-add-them-to-video/generate-captions-in-customer-portal/tasks-details.png?fit=max\&auto=format\&n=g8X-owBxoALHKrba\&q=85\&s=7e1ead09038d25ef5211198d84d62a25)

> [!NOTE]
>
> Task result data is deleted after one month.

## REST API

Two approaches are available. For videos hosted on Gcore Video Streaming, pass `auto_transcribe_audio_language` directly in the video create or subtitle request. For any MP4 file accessible via a public HTTPS URL — including videos outside Gcore — submit a task to `POST /streaming/ai/tasks` and poll for results.

> [!NOTE]
>
> An [API token](https://docs.gcore.com/account-settings/api-tokens.md) is required.

Open a terminal and export the API key:

```bash theme={null}
export GCORE_API_KEY="{YOUR_API_KEY}"
```

## Gcore-hosted videos

### New video

Add `auto_transcribe_audio_language` to the video create request. After the video finishes transcoding, Gcore automatically creates an AI transcription task and attaches the resulting WebVTT subtitles to the video. To translate into additional languages, also set `auto_translate_subtitles_language`.

> [tab] Python SDK
>
> ```python theme={null}
> from gcore import Gcore
>
> client = Gcore()
> result = client.streaming.videos.create(
>     video={
>         "name": "My Video",
>         "origin_url": "https://example.com/video.mp4",
>         "auto_transcribe_audio_language": "auto",
>         # "auto_translate_subtitles_language": "fre,ger,ita",  # optional
>     }
> )
> print(f"Video ID: {result.id}")
> ```

> [tab] Go SDK
>
> ```go theme={null}
> package main
>
> import (
> 	"context"
> 	"fmt"
>
> 	gcore "github.com/G-Core/gcore-go"
> 	"github.com/G-Core/gcore-go/streaming"
> )
>
> func main() {
> 	client := gcore.NewClient()
> 	ctx := context.Background()
>
> 	result, err := client.Streaming.Videos.New(ctx, streaming.VideoNewParams{
> 		Video: streaming.CreateVideoParam{
> 			Name:                       "My Video",
> 			OriginURL:                  gcore.String("https://example.com/video.mp4"),
> 			AutoTranscribeAudioLanguage: streaming.CreateVideoAutoTranscribeAudioLanguageAuto,
> 			// AutoTranslateSubtitlesLanguage: streaming.CreateVideoAutoTranslateSubtitlesLanguage("fre,ger,ita"),
> 		},
> 	})
> 	if err != nil {
> 		panic(err)
> 	}
> 	fmt.Printf("Video ID: %d\n", result.ID)
> }
> ```

> [tab] curl
>
> ```bash theme={null}
> curl -X POST "https://api.gcore.com/streaming/videos" \
>   -H "Authorization: APIKey $GCORE_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "video": {
>       "name": "My Video",
>       "origin_url": "https://example.com/video.mp4",
>       "auto_transcribe_audio_language": "auto"
>     }
>   }'
> ```
>
> The API returns an array with the created video object. The AI transcription task is created automatically after transcoding completes.

### Existing video

Set the ID of the video already in Gcore Video Streaming:

```bash theme={null}
export VIDEO_ID="{YOUR_VIDEO_ID}"
```

Trigger transcription by posting to its subtitles endpoint. The AI task runs automatically and attaches the resulting subtitles to the video.

> [tab] curl
>
> ```bash theme={null}
> curl -X POST "https://api.gcore.com/streaming/videos/$VIDEO_ID/subtitles" \
>   -H "Authorization: APIKey $GCORE_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{"auto_transcribe_audio_language": "auto"}'
> ```
>
> To also translate subtitles, add `auto_translate_subtitles_language`:
>
> ```bash theme={null}
> curl -X POST "https://api.gcore.com/streaming/videos/$VIDEO_ID/subtitles" \
>   -H "Authorization: APIKey $GCORE_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "auto_transcribe_audio_language": "auto",
>     "auto_translate_subtitles_language": "fre,ger,ita,spa"
>   }'
> ```

## External MP4 videos

### Create a transcription task

Send `POST /streaming/ai/tasks` with `task_name: "transcription"` and the URL to an MP4 file. Optionally, specify `audio_language` (ISO-639-2 code, e.g. `"eng"`) and `subtitles_language` to translate subtitles into a different language. For multiple target languages, create a separate task for each.

> [tab] Python SDK
>
> ```python theme={null}
> from gcore import Gcore
>
> client = Gcore()
> task = client.streaming.ai_tasks.create(
>     task_name="transcription",
>     url="https://example.com/video.mp4",
>     # audio_language="eng",      # optional: set source language explicitly
>     # subtitles_language="deu",  # optional: translate to German
> )
> print(f"Task ID: {task.task_id}")
> ```

> [tab] Go SDK
>
> ```go theme={null}
> package main
>
> import (
>     "context"
>     "fmt"
>
>     gcore "github.com/G-Core/gcore-go"
>     "github.com/G-Core/gcore-go/streaming"
>     // To set optional language fields, also import:
>     // "github.com/G-Core/gcore-go/packages/param"
> )
>
> func main() {
>     client := gcore.NewClient()
>     ctx := context.Background()
>
>     task, err := client.Streaming.AITasks.New(ctx, streaming.AITaskNewParams{
>         OfAITranscriptionTaskData: &streaming.AITaskNewParamsBodyAITranscriptionTaskData{
>             TaskName: "transcription",
>             URL:      "https://example.com/video.mp4",
>             // AudioLanguage:     param.NewOpt("eng"),  // optional
>             // SubtitlesLanguage: param.NewOpt("deu"),  // optional: translate to German
>         },
>     })
>     if err != nil {
>         panic(err)
>     }
>     fmt.Printf("Task ID: %s\n", task.TaskID)
> }
> ```

> [tab] curl
>
> ```bash theme={null}
> curl -X POST "https://api.gcore.com/streaming/ai/tasks" \
>      -H "Authorization: APIKey $GCORE_API_KEY" \
>      -H "Content-Type: application/json" \
>      -d '{
>            "task_name": "transcription",
>            "url": "https://example.com/video.mp4"
>          }'
> ```
>
> The API returns:
>
> ```json theme={null}
> {"task_id": "bc35ecac-4ca5-43a5-8faf-b5aa398b963e"}
> ```

Copy the task ID from the response and export it:

```bash theme={null}
export TASK_ID="{YOUR_TASK_ID}"
```

### Get the captions

Use `GET /streaming/ai/tasks/{task_id}` to check the task status. While processing, `status` may cycle between `"STARTED"` and `"PENDING"` as resources are allocated to each sub-stage; use the `progress` field to track overall completion. Poll until `status` is `"SUCCESS"` or `"FAILURE"`. On success, `result.vtt_content` contains the WebVTT subtitle text.

> [tab] Python SDK
>
> ```python theme={null}
> import os
> import time
> from gcore import Gcore
>
> task_id = os.environ["TASK_ID"]
>
> client = Gcore()
> while True:
>     task = client.streaming.ai_tasks.get(task_id)
>     print(f"Status: {task.status}  Progress: {task.progress}%")
>     if task.status in ("SUCCESS", "FAILURE"):
>         break
>     time.sleep(5)
>
> if task.status == "SUCCESS":
>     print(task.result.vtt_content)
> ```

> [tab] Go SDK
>
> ```go theme={null}
> package main
>
> import (
>     "context"
>     "fmt"
>     "os"
>     "time"
>
>     gcore "github.com/G-Core/gcore-go"
> )
>
> func main() {
>     taskID := os.Getenv("TASK_ID")
>     client := gcore.NewClient()
>     ctx := context.Background()
>
>     for {
>         task, err := client.Streaming.AITasks.Get(ctx, taskID)
>         if err != nil {
>             panic(err)
>         }
>         fmt.Printf("Status: %s  Progress: %d%%\n", task.Status, task.Progress)
>         if task.Status == "SUCCESS" || task.Status == "FAILURE" {
>             if task.Status == "SUCCESS" {
>                 fmt.Println(task.Result.VttContent)
>             }
>             break
>         }
>         time.Sleep(5 * time.Second)
>     }
> }
> ```

> [tab] curl
>
> ```bash theme={null}
> curl "https://api.gcore.com/streaming/ai/tasks/$TASK_ID" \
>      -H "Authorization: APIKey $GCORE_API_KEY"
> ```
>
> The API returns:
>
> ```json theme={null}
> {
>   "task_id": "bc35ecac-4ca5-43a5-8faf-b5aa398b963e",
>   "status": "SUCCESS",
>   "progress": 100,
>   "result": {
>     "speech_detected": true,
>     "vttContent": "WEBVTT\n\n1\n00:00:00.031 --> 00:00:03.811\nCome on team...\n\n",
>     "subtitles": [
>       {"start_time": "00:00:00.031", "end_time": "00:00:03.811", "text": "Come on team, we mustn't dilly-dally when there's so much nature to see!"}
>     ],
>     "languages": {"eng": 100.0}
>   }
> }
> ```

### Cancel a running task

To cancel a task that is still processing, send `POST /streaming/ai/tasks/{task_id}/cancel`.

> [tab] Python SDK
>
> ```python theme={null}
> import os
> from gcore import Gcore
>
> task_id = os.environ["TASK_ID"]
>
> client = Gcore()
> client.streaming.ai_tasks.cancel(task_id)
> print(f"Task {task_id} canceled")
> ```

> [tab] Go SDK
>
> ```go theme={null}
> package main
>
> import (
>     "context"
>     "fmt"
>     "os"
>
>     gcore "github.com/G-Core/gcore-go"
> )
>
> func main() {
>     taskID := os.Getenv("TASK_ID")
>     client := gcore.NewClient()
>     ctx := context.Background()
>
>     _, err := client.Streaming.AITasks.Cancel(ctx, taskID)
>     if err != nil {
>         panic(err)
>     }
>     fmt.Printf("Task %s canceled\n", taskID)
> }
> ```

> [tab] curl
>
> ```bash theme={null}
> curl -X POST "https://api.gcore.com/streaming/ai/tasks/$TASK_ID/cancel" \
>      -H "Authorization: APIKey $GCORE_API_KEY"
> ```

## List AI tasks

To retrieve all AI tasks, send `GET /streaming/ai/tasks`. Use the optional `search` query parameter to filter by ID, URL, task type, or status.

> [tab] Python SDK
>
> ```python theme={null}
> from gcore import Gcore
>
> client = Gcore()
> for task in client.streaming.ai_tasks.list():
>     print(f"{task.task_id}  {task.status}  {task.progress}%")
> ```

> [tab] Go SDK
>
> ```go theme={null}
> package main
>
> import (
>     "context"
>     "fmt"
>
>     gcore "github.com/G-Core/gcore-go"
>     "github.com/G-Core/gcore-go/streaming"
> )
>
> func main() {
>     client := gcore.NewClient()
>     ctx := context.Background()
>
>     page, err := client.Streaming.AITasks.List(ctx, streaming.AITaskListParams{})
>     if err != nil {
>         panic(err)
>     }
>     for _, task := range page.Results {
>         fmt.Printf("%s  %s  %d%%\n", task.TaskID, task.Status, task.Progress)
>     }
> }
> ```

> [tab] curl
>
> ```bash theme={null}
> curl "https://api.gcore.com/streaming/ai/tasks" \
>      -H "Authorization: APIKey $GCORE_API_KEY"
> ```
