# 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`                            | query | один із двох | Ваш ключ. Використовуйте його або заголовок `Authorization: Bearer`.                                             |
| `language`, `include_video_language` | query | ні           | Приймаються, але ігноруються. Відповідь завжди містить усі відео назви. Фільтруйте за `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/uk/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/uk/tv-series/) та [сезони та серії](https://amodb.dev/uk/tv-seasons-episodes/).

## Помилки

| HTTP | status_code | Коли                                                                                               |
| ---- | ----------- | -------------------------------------------------------------------------------------------------- |
| 401  | 7           | Ключ відсутній або хибний.                                                                         |
| 402  | 36          | Термін дії тарифу закінчився.                                                                      |
| 404  | 34          | Немає сезону чи серії з таким id або id не є числом.                                               |
| 405  | 37          | Ви використали метод запису на шляху відео.                                                        |
| 429  | 25          | Ви перевищили ліміт запитів на хвилину. Зачекайте стільки секунд, скільки вказано в `Retry-After`. |

Неіснуючий id фільму чи серіалу тут не помилка: шлях відео відповідає 200 із `"results": []`, так само як для відомої назви без відео. Шлях деталей відповідає 404 для невідомого id. Докладніше про [помилки](https://amodb.dev/uk/errors/) та [ліміти запитів](https://amodb.dev/uk/rate-limits/).

## Практичні нотатки

- Зберігайте обрані `site` і `key` разом із назвою, а не повну адресу, щоб пізніше можна було змінити плеєр.
- Списки відео підпорядковуються кешу деталей: 6 годин на edge. Клієнтський кеш на кілька годин цьому відповідає.
- `size` сьогодні дорівнює 1080 для кожного запису, тому за ним не можна визначити, який ролик легший. Дозвольте плеєру обирати якість.
- Не покладайтеся на те, що трейлер існує. Ховайте кнопку відтворення, коли ваша функція вибору повертає null.
- Порядок `results` не несе змісту. Сортуйте у своєму коді.
- Файли постерів і фонів (backdrop) дивіться в розділі [API зображень](https://amodb.dev/uk/images-api/). Огляд сценарію використання дивіться в [API трейлерів фільмів](https://amodb.dev/uk/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/uk/movies/): API деталей фільму з тими самими шляхами та JSON, що в TMDB v3. Отримайте фільм за id, додайте акторів, рейтинги й настрої через append_to_response, 14 мовами.
- [API серіалів](https://amodb.dev/uk/tv-series/): API серіалів з тими самими шляхами та JSON, що в TMDB v3. Отримайте серіал за id із сезонами, телемережами й наступною серією, плюс вікові рейтинги.
- [API сезонів і серій серіалів](https://amodb.dev/uk/tv-seasons-episodes/): API сезонів і серій серіалів з тими самими шляхами та JSON, що в TMDB v3. Читайте сезон з усіма серіями або одну серію з датою виходу, тривалістю та кадром.
- [API трейлерів фільмів](https://amodb.dev/uk/movie-trailer-api/): API трейлерів фільмів на ендпоінті videos TMDB v3. Ранжуйте трейлери, тизери й кліпи за типом, прапорцем official і кодом мови одним запитом на тайтл.
- [API зображень і хост зображень](https://amodb.dev/uk/images-api/): API зображень фільмів зі шляхами TMDB v3: списки постерів, фонів, логотипів і кадрів проєкту, а потім завантаження з img.amodb.dev у 10 розмірах без ключа.
- [Швидкий старт](https://amodb.dev/uk/quickstart/): Перший виклик amodb: отримайте ключ, запросіть деталі фільму в curl, JavaScript, Python, PHP чи Go і завантажте постер з img.amodb.dev. Менш ніж за 2 хвилини.

Оновлено: 2026-10-18. Source: https://amodb.dev/uk/videos-trailers/
