# 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/ru/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/ru/tv-series/) и [сезоны и серии](https://amodb.dev/ru/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/ru/errors/) и [лимиты запросов](https://amodb.dev/ru/rate-limits/).

## Практические заметки

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

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