# API відэа і трэйлераў

> Эндпоінты відэа пералічваюць трэйлеры, тызеры, кліпы і фічарэты, прывязаныя да фільма або серыяла. Кожны запіс дае назву хоста, ключ відэа, тып, прыкмету афіцыйнасці, памер і дату публікацыі. Шляхі сезонаў і эпізодаў існуюць, але відэа не вяртаюць. Фільтруйце па мове і тыпе ў сваім кодзе.

## Эндпоінт

`GET /3/movie/{movie_id}/videos`

```bash
curl "https://api.amodb.dev/3/movie/550/videos" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Адказ:

```json
{
  "id": 550,
  "results": [
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "Theatrical Trailer (HD Fan Remaster)",
      "key": "6JnN1DmbqoU",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": false,
      "published_at": "2015-02-26T03:19:25Z",
      "id": "6JnN1DmbqoU"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "#TBT Trailer",
      "key": "BdJKm16Co6M",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2014-10-02T19:20:22Z",
      "id": "BdJKm16Co6M"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "20th Anniversary Trailer",
      "key": "dfeUzm6KF4g",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2019-10-15T18:59:47Z",
      "id": "dfeUzm6KF4g"
    }
  ]
}
```

## Атрыманне відэа фільма

`GET /3/movie/{movie_id}/videos` вяртае запісы відэа, прывязаныя да аднаго фільма. Запіс уяўляе сабой толькі метаданыя: назву, хост, які аддае відэа, ключ відэа на гэтым хосце, тып і некалькі прыкмет. amodb не вяртае відэафайлы.

У прыкладзе друкуецца першы афіцыйны англійскі трэйлер, а калі яго няма, любы англійскі трэйлер.

```bash
curl -s "https://api.amodb.dev/3/movie/550/videos" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const url = 'https://api.amodb.dev/3/movie/550/videos';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results } = await res.json();
const trailers = results.filter((v) => v.type === 'Trailer' && v.iso_639_1 === 'en');
const pick = trailers.find((v) => v.official) ?? trailers[0];
console.log(pick ? `${pick.name} (${pick.site}, key ${pick.key})` : 'no trailer');
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/videos",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
trailers = [v for v in r.json()["results"] if v["type"] == "Trailer" and v["iso_639_1"] == "en"]
official = [v for v in trailers if v["official"]]
pick = (official or trailers or [None])[0]
print(f"{pick['name']} ({pick['site']}, key {pick['key']})" if pick else "no trailer")
```

```php
<?php
$url = 'https://api.amodb.dev/3/movie/550/videos';
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$trailers = array_values(array_filter(
    json_decode($body, true)['results'],
    fn($v) => $v['type'] === 'Trailer' && $v['iso_639_1'] === 'en'
));
$official = array_values(array_filter($trailers, fn($v) => $v['official']));
$pick = $official[0] ?? $trailers[0] ?? null;
echo $pick ? "{$pick['name']} ({$pick['site']}, key {$pick['key']})" : 'no trailer', PHP_EOL;
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
)

type Videos struct {
	Results []struct {
		Name     string `json:"name"`
		Key      string `json:"key"`
		Site     string `json:"site"`
		Type     string `json:"type"`
		Language string `json:"iso_639_1"`
		Official bool   `json:"official"`
	} `json:"results"`
}

func main() {
	url := "https://api.amodb.dev/3/movie/550/videos"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var v Videos
	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
		panic(err)
	}
	for _, r := range v.Results {
		if r.Type == "Trailer" && r.Language == "en" && r.Official {
			fmt.Printf("%s (%s, key %s)\n", r.Name, r.Site, r.Key)
			return
		}
	}
	fmt.Println("no official trailer")
}
```

### Параметры

| Параметр                             | Дзе   | Абавязковы   | Апісанне                                                                                                      |
| ------------------------------------ | ----- | ------------ | ------------------------------------------------------------------------------------------------------------- |
| `movie_id`                           | шлях  | так          | Лікавы id фільма, напрыклад `550`.                                                                            |
| `api_key`                            | запыт | адзін з двух | Ваш ключ. Выкарыстоўвайце яго або загаловак `Authorization: Bearer`.                                          |
| `language`, `include_video_language` | запыт | не           | Прымаюцца, але ігнаруюцца. Адказ заўсёды змяшчае кожнае відэа назвы. Фільтруйце па `iso_639_1` у сваім кодзе. |

### Палі адказу

| Поле                                          | Тып               | Заўвагі                                                                                                    |
| --------------------------------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------- |
| `id`                                          | цэлы лік          | Id фільма.                                                                                                 |
| `results`                                     | масіў             | Запісы відэа, не адсартаваныя па тыпе або даце. Пусты, калі нічога невядома.                               |
| `results[].iso_639_1`, `results[].iso_3166_1` | радок             | Мова і краіна відэа, напрыклад `en` і `US`.                                                                |
| `results[].name`                              | радок             | Назва відэа, напрыклад `#TBT Trailer`.                                                                     |
| `results[].key`                               | радок             | Id відэа на гэтым хосце.                                                                                   |
| `results[].site`                              | радок             | Назва хоста відэа. Сёння заўсёды `YouTube`.                                                                |
| `results[].size`                              | цэлы лік          | Вертыкальнае разрозненне. Сёння заўсёды `1080`.                                                            |
| `results[].type`                              | радок             | `Trailer`, `Teaser`, `Clip`, `Featurette`, `Behind the Scenes`, `Bloopers`, `Opening Credits` або `Recap`. |
| `results[].official`                          | лагічнае значэнне | True, калі студыя або праваўладальнік апублікавалі яго.                                                    |
| `results[].published_at`                      | радок             | Часовая пазнака ISO 8601, з мілісекундамі або без іх.                                                      |
| `results[].id`                                | радок             | Id запісу відэа. Роўны `key`.                                                                              |

### Прыклад адказу

Паказаны тры з 19 запісаў фільма 550.

```json
{
  "id": 550,
  "results": [
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "Theatrical Trailer (HD Fan Remaster)",
      "key": "6JnN1DmbqoU",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": false,
      "published_at": "2015-02-26T03:19:25Z",
      "id": "6JnN1DmbqoU"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "#TBT Trailer",
      "key": "BdJKm16Co6M",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2014-10-02T19:20:22Z",
      "id": "BdJKm16Co6M"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "Mark Kermode introduces Fight Club | Film4 Interview",
      "key": "tiWCNtGDGEY",
      "site": "YouTube",
      "size": 1080,
      "type": "Featurette",
      "official": true,
      "published_at": "2015-05-08T15:59:05Z",
      "id": "tiWCNtGDGEY"
    }
  ]
}
```

## Тыпы відэа

Поле `type` кажа, што гэта за відэа. Параўноўвайце яго дакладна, з вялікімі літарамі, як паказана.

| Тып                 | Для чаго выкарыстоўваць                                        |
| ------------------- | -------------------------------------------------------------- |
| `Trailer`           | Асноўны рэкламны ролік. Паказвайце яго на старонцы з дэталямі. |
| `Teaser`            | Кароткі анонс, які выходзіць перад трэйлерам.                  |
| `Clip`              | Сцэна з гатовага фільма або эпізода.                           |
| `Featurette`        | Кароткі матэрыял пра тое, як рабілі назву.                     |
| `Behind the Scenes` | Кадры з пляцоўкі і інтэрв’ю.                                   |
| `Bloopers`          | Выразаныя дублі і зборнікі жартаў.                             |
| `Opening Credits`   | Застаўка серыяла.                                              |
| `Recap`             | Падсумаванне папярэдніх эпізодаў.                              |

З часам могуць з’явіцца іншыя значэнні, таму лічыце невядомы `type` агульным дадаткам і не падайце з памылкай.

## Як выбраць патрэбнае відэа

Выкарыстоўвайце той жа парадак для кожнай назвы. Спрабуйце вашы мовы па чарзе. Унутры адной мовы першымі ідуць афіцыйныя трэйлеры, потым любы трэйлер, потым тызеры, потым кліпы. Унутры групы сартуйце па `published_at`: па ўзрастанні дае першы трэйлер, па змяншэнні апошні.

```js
function pickVideo(results, langs = ['en']) {
  const order = ['Trailer', 'Teaser', 'Clip'];
  for (const lang of langs) {
    for (const type of order) {
      const group = results
        .filter((v) => v.iso_639_1 === lang && v.type === type)
        .sort((a, b) => Number(b.official) - Number(a.official) || Date.parse(a.published_at) - Date.parse(b.published_at));
      if (group.length > 0) return group[0];
    }
  }
  return null;
}

// Russian first, English as the fallback.
// const video = pickVideo(results, ['ru', 'en']);
```

## Мовы

`language` і `include_video_language` не змяняюць адказ, таму адзін выклік дае кожнае відэа назвы. Кожны запіс нясе `iso_639_1` і `iso_3166_1`. У фільма 550 ёсць відэа з пазнакамі `fr`, `en`, `es`, `pt`, `it`, `cs`, `pl` і `ru`. Фільтруйце па `iso_639_1` у сваім кодзе, як паказана вышэй, а потым скажыце карыстальніку, на якой мове ён збіраецца слухаць. У назвы можа не быць відэа на патрэбнай вам мове, таму трымайце запасны варыянт на англійскай або любой мове. 14 падтрымліваных моў пералічаны на старонцы [мовы](https://amodb.dev/be/languages/).

## Іншыя эндпоінты відэа

Шляхі ніжэй вяртаюць тую ж форму з `id` і `results`.

| Метад і шлях                                                                 | Што вяртае                     |
| ---------------------------------------------------------------------------- | ------------------------------ |
| `GET /tv/{series_id}/videos`                                                 | Відэа серыяла.                 |
| `GET /tv/{series_id}/season/{season_number}/videos`                          | Заўсёды пусты масіў `results`. |
| `GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/videos` | Заўсёды пусты масіў `results`. |

Таксама можна дадаць `append_to_response=videos` да выкліку дэталяў фільма або серыяла. Далучаны блок змяшчае `results` і не мае `id`. Старонкі серыялаў і сезонаў апісаны ў [серыялы](https://amodb.dev/be/tv-series/) і [сезоны і эпізоды](https://amodb.dev/be/tv-seasons-episodes/).

## Памылкі

| HTTP | status_code | Калі                                                                   |
| ---- | ----------- | ---------------------------------------------------------------------- |
| 401  | 7           | Ключ адсутнічае або няправільны.                                       |
| 402  | 36          | Тэрмін дзеяння плана скончыўся.                                        |
| 404  | 34          | Няма сезона або эпізода з гэтым id, або id не з’яўляецца лікам.        |
| 405  | 37          | Вы выкарысталі метад запісу на шляху відэа.                            |
| 429  | 25          | Вы перавысілі ліміт запытаў у хвіліну. Пачакайце `Retry-After` секунд. |

Id фільма або серыяла, якога не існуе, тут не памылка: шлях відэа адказвае 200 з `"results": []`, гэтак жа, як і для вядомай назвы без відэа. Шлях дэталяў на невядомы id адказвае 404. Больш на старонках [памылкі](https://amodb.dev/be/errors/) і [ліміты запытаў](https://amodb.dev/be/rate-limits/).

## Практычныя заўвагі

- Захоўвайце абраныя `site` і `key` разам з назвай, а не поўны адрас, каб потым можна было змяніць прайгравальнік.
- Спісы відэа выконваюць кэш дэталяў на edge у 6 гадзін. Кліенцкі кэш на некалькі гадзін адпавядае яму.
- `size` сёння роўны 1080 для кожнага запісу, таму па ім нельга ўбачыць, які ролік лёгкі. Дазвольце прайгравальніку выбіраць якасць.
- Не спадзявайцеся, што трэйлер заўсёды існуе. Хавайце кнопку прайгравання, калі ваша функцыя выбару вяртае null.
- Парадак `results` нічога не азначае. Сартуйце ў сваім кодзе.
- Файлы постэраў і фонавых выяў гл. на старонцы [выявы](https://amodb.dev/be/images-api/). Погляд з боку выпадку выкарыстання гл. на старонцы [API трэйлераў фільмаў](https://amodb.dev/be/movie-trailer-api/).

## Пытанні і адказы

### Як атрымаць толькі афіцыйны трэйлер?

Адфільтруйце масіў results, дзе type роўны Trailer і official роўны true. Калі застаецца некалькі, адсартуйце па published_at, каб узяць самы ранні або самы позні.

### Як атрымаць відэа на маёй мове?

Эндпоінт вяртае кожнае відэа назвы і ігнаруе language і include_video_language. Фільтруйце results па iso_639_1 у сваім кодзе, напрыклад спачатку ru, а en як запасны варыянт. У многіх назваў няма відэа на пэўнай мове.

### Як прайграць відэа з адказу?

Выкарыстоўвайце поле site, каб выбраць прайгравальнік, і поле key як id відэа на гэтым хосце. У даных, якія аддаюцца сёння, site заўсёды YouTube. Складзіце адрас убудавання або прагляду па ўласным шаблоне хоста. amodb вяртае метаданыя, а не відэафайлы.

### Ці маюць эпізоды і сезоны ўласныя відэа?

Не. Шляхі відэа сезонаў і эпізодаў адказваюць 200 з пустым масівам results. Запісы відэа нясуць толькі фільмы і серыялы.

## Звязаныя старонкі

- [API дэталяў фільма](https://amodb.dev/be/movies/): API дэталяў фільма з тымі ж шляхамі і JSON, што ў TMDB v3. Адзін фільм па id, а акцёры, рэйтынгі і настрой праз append_to_response, на 14 мовах.
- [API серыялаў](https://amodb.dev/be/tv-series/): API серыялаў з тымі ж шляхамі і JSON, што ў TMDB v3. Серыял па id з сезонамі, тэлеканаламі і наступным эпізодам, плюс узроставыя рэйтынгі і сэрвісы прагляду.
- [API сезонаў і эпізодаў серыялаў](https://amodb.dev/be/tv-seasons-episodes/): API сезонаў і эпізодаў з тымі ж шляхамі і JSON, што ў TMDB v3. Чытайце сезон з усімі эпізодамі або адзін эпізод з датай эфіру, працягласцю і кадрам.
- [API трэйлераў фільмаў](https://amodb.dev/be/movie-trailer-api/): API трэйлераў на эндпоінце відэа TMDB v3. Ранжыруйце трэйлеры, тызеры і кліпы па тыпе, афіцыйнасці і мове, з адным запытам на фільм або серыял.
- [API выяў і хост выяў](https://amodb.dev/be/images-api/): API выяў фільмаў з шляхамі TMDB v3: спісы постэраў, фонавых выяў, лагатыпаў і кадраў назвы, а потым загрузка з img.amodb.dev у 10 памерах без ключа.
- [Хуткі старт](https://amodb.dev/be/quickstart/): Першы выклік да amodb: атрымайце ключ, запытайце дэталі фільма ў curl, JavaScript, Python, PHP або Go і загрузіце постэр з img.amodb.dev. Менш за 2 хвіліны.

Абноўлена: 2026-10-18. Source: https://amodb.dev/be/videos-trailers/
