Все серии сезона

GET /3/tv/{tv_id}/season/{season_number} возвращает сезон с полным массивом episodes. У каждой серии есть episode_number, name, overview, air_date, runtime и still_path. Идентификаторы: числовые id, которые использует TMDB, например 1396 для Breaking Bad.

Вы получаете сезоны, серии с датами и длительностью, кадры, следующую и последнюю вышедшую серию сериала и список альтернативных порядков серий. Текстовые поля следуют параметру language, а описание остается пустым, если перевода нет.

Какие данные вы получаете

ЭндпоинтЧто возвращает
GET /3/tv/{tv_id}Сводка seasons, number_of_seasons, status, next_episode_to_air, last_episode_to_air
GET /3/tv/{tv_id}/season/{season_number}Один сезон со всеми episodes
GET /3/tv/{tv_id}/season/{season_number}/episode/{episode_number}Одна серия с crew и guest_stars
GET /3/tv/{tv_id}/episode_groupsНазвание, type и число серий каждого альтернативного порядка, заданного для сериала

Поля серии:

ПолеТипПримечания
id, show_idцелое числоId серии и id сериала. show_id есть в списках сезона и в next_episode_to_air, но не на пути одной серии
episode_number, season_numberцелое числоПозиция в сезоне
episode_typeстрокаНапример, standard
name, overviewстрокаЛокализуются через language
air_dateстрока или nullYYYY-MM-DD, пусто или null, если дата не анонсирована
runtimeцелое число или nullМинуты
still_pathстрока или nullПрисоединяется к https://img.amodb.dev/t/p/{size}
vote_average, vote_countчисло, целое числоСейчас 0 у серий
production_codeстрокаКод студии, часто пуст
crew, guest_starsмассивЛюди, указанные в титрах серии, с теми же полями, что у участника актерского состава

Начало работы в 3 шага

  1. Выберите тариф на странице цены. Все тарифы возвращают одни и те же данные о сериях, различается только число запросов в минуту.
  2. Создайте ключ в личном кабинете и сохраните его в переменной окружения.
  3. Запросите /3/tv/{tv_id}/season/1, передав ключ в заголовке Bearer или в api_key.

Пример запроса

Пример получает сезон 1 сериала Breaking Bad (id сериала 1396) на английском. Программа на Go декодирует ответ в типизированные структуры и выводит по строке на серию с датой выхода, длительностью и URL кадра.

bashgo
curl -s "https://api.amodb.dev/3/tv/1396/season/1?language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
package main

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

type Episode struct {
	EpisodeNumber int     `json:"episode_number"`
	Name          string  `json:"name"`
	AirDate       string  `json:"air_date"`
	Runtime       int     `json:"runtime"`
	StillPath     *string `json:"still_path"`
}

type Season struct {
	Name         string    `json:"name"`
	SeasonNumber int       `json:"season_number"`
	Episodes     []Episode `json:"episodes"`
}

func main() {
	client := &http.Client{Timeout: 10 * time.Second}
	url := "https://api.amodb.dev/3/tv/1396/season/1?language=en-US"
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(fmt.Sprintf("amodb returned %s", res.Status))
	}
	var season Season
	if err := json.NewDecoder(res.Body).Decode(&season); err != nil {
		panic(err)
	}
	fmt.Println(season.Name)
	for _, e := range season.Episodes {
		still := "no still"
		if e.StillPath != nil {
			still = "https://img.amodb.dev/t/p/w300" + *e.StillPath
		}
		fmt.Printf("S%02dE%02d  %s  %3d min  %s  %s\n",
			season.SeasonNumber, e.EpisodeNumber, e.AirDate, e.Runtime, e.Name, still)
	}
}

Сокращенный ответ: 2 из 7 серий, в каждой один член съемочной группы и один приглашенный актер.

JSON
{
  "air_date": "2008-01-20",
  "episodes": [
    {
      "air_date": "2008-01-20",
      "episode_number": 1,
      "episode_type": "standard",
      "id": 62085,
      "name": "Pilot",
      "overview": "When an unassuming high school chemistry teacher discovers he has a rare form...",
      "production_code": "",
      "runtime": 59,
      "season_number": 1,
      "show_id": 1396,
      "still_path": "/ydlY3iPfeOAvu8gVqrxPoMvzNCn.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "crew": [
        {
          "department": "Camera",
          "job": "Director of Photography",
          "credit_id": "52b7029219c29533d00dd2c1",
          "adult": false,
          "gender": 2,
          "id": 2483,
          "known_for_department": "Camera",
          "name": "约翰·托尔",
          "original_name": "约翰·托尔",
          "popularity": 1.1957,
          "profile_path": "/cfL9A6tC7L5Ps5fq1o3WpVKGMb1.jpg"
        }
      ],
      "guest_stars": [
        {
          "character": "Steven Gomez",
          "credit_id": "5271b489760ee35b3e0881a7",
          "order": 8,
          "adult": false,
          "gender": 2,
          "id": 61535,
          "known_for_department": "Acting",
          "name": "史蒂文·迈克尔·奎扎达",
          "original_name": "史蒂文·迈克尔·奎扎达",
          "popularity": 1.7511,
          "profile_path": "/pVYrDkwI6GWvCNL2kJhpDJfBFyd.jpg"
        }
      ]
    },
    {
      "air_date": "2008-01-27",
      "episode_number": 2,
      "episode_type": "standard",
      "id": 62086,
      "name": "Cat's in the Bag...",
      "overview": "Walt and Jesse attempt to tie up loose ends. The desperate situation gets mor...",
      "production_code": "",
      "runtime": 49,
      "season_number": 1,
      "show_id": 1396,
      "still_path": "/AbMoecO0ZZio0LcgeLxlzdyGs6X.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "crew": [
        {
          "department": "Camera",
          "job": "Director of Photography",
          "credit_id": "52b7049c19c2953b63015013",
          "adult": false,
          "gender": 2,
          "id": 17948,
          "known_for_department": "Camera",
          "name": "Reynaldo Villalobos",
          "original_name": "Reynaldo Villalobos",
          "popularity": 0.904,
          "profile_path": "/4YlfhHDRZWhbRgeqT2Bwl1u5p9j.jpg"
        }
      ],
      "guest_stars": [
        {
          "character": "Krazy-8",
          "credit_id": "52725845760ee3046b09426e",
          "order": 504,
          "adult": false,
          "gender": 2,
          "id": 1046460,
          "known_for_department": "Acting",
          "name": "Max Arciniega",
          "original_name": "Max Arciniega",
          "popularity": 1.4399,
          "profile_path": "/eqKAJKPpt41KpsLIkkBnAY4HMAL.jpg"
        }
      ]
    }
  ],
  "name": "Season 1",
  "overview": "High school chemistry teacher Walter White's life is suddenly transformed by...",
  "id": 3572,
  "poster_path": "/91EIXdWxmp2mHNRsSuDW3WyDJLj.jpg",
  "season_number": 1,
  "vote_average": 0
}

Загрузка всего сериала

amodb не принимает значения вида season/1 в append_to_response, поэтому вызовы сезонов остаются отдельными. Сначала прочитайте number_of_seasons и список seasons из данных сериала, затем запросите каждый сезон в цикле.

JavaScript
const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };

async function get(path) {
  const res = await fetch(base + path, { headers });
  if (!res.ok) throw new Error(`amodb returned ${res.status} for ${path}`);
  return res.json();
}

const show = await get('/tv/1396');
for (const { season_number } of show.seasons) {
  const season = await get(`/tv/1396/season/${season_number}`);
  console.log(season.name, season.episodes.length);
}

seasons включает сезон 0, если у сериала есть спецвыпуски, поэтому Breaking Bad стоит 1 вызов данных плюс 6 вызовов сезонов. Сериал из 10 сезонов стоит 11 запросов. Данные хранятся в edge-кэше 6 часов, поэтому сохраняйте результат и обновляйте его по расписанию.

Даты выхода и что дальше

GET /3/tv/{tv_id} содержит next_episode_to_air и last_episode_to_air, полные объекты серий с name, air_date, season_number, episode_number, runtime и still_path. next_episode_to_air равен null, если ничего не анонсировано. Сочетайте его с status (например Returning Series, Ended или Canceled), чтобы решить, показывать ли обратный отсчет.

air_date задает календарную дату без времени суток. Сравнивайте ее с сегодняшней датой, чтобы отмечать новые серии. Для расписания эфира списки airing_today и on_the_air на странице списки трендов кэшируются на 30 минут.

Кадры и длительность

Используйте w185 или w300 для строк списка и original для полного размера. Размеры кадров: w92, w185, w300 и original. У серии может не быть кадра, поэтому показывайте заглушку, когда still_path равен null. Хосту изображений ключ не нужен, см. API изображений.

runtime задается в минутах и может быть null. Чтобы показать время просмотра сезона подряд, сложите runtime по episodes и считайте null как 0. Добавьте append_to_response=credits,images к пути одной серии, чтобы получить объект credits и список stills. Массив cast у серии пуст, а люди находятся в crew и guest_stars. Подробности на страницах сезоны и серии и актеры и съемочная группа.

Альтернативные порядки и группы серий

Некоторые сериалы смотрят в ином порядке, чем они выходили в эфир. GET /3/tv/{tv_id}/episode_groups перечисляет порядки, заданные для сериала. У каждой записи есть id, name, description, type, episode_count, group_count и network. Массив results пуст, если порядков нет.

typeПорядок
1Исходная дата выхода
2Сквозной
3DVD
4Цифровой
5Сюжетная арка
6Производственный
7ТВ

amodb возвращает только этот список. Эндпоинта GET /3/tv/episode_group/{id} нет, поэтому серии внутри группы недоступны. Данные серий берите из эндпоинтов сезонов.

Сравнение

ВозможностьПарсинг страниц серийAPI метаданных с бесплатным тарифомamodb
Сезон целикомОдин запрос страницы на сезонСмотрите их документациюОдин вызов, массив episodes включен
Сериал целикомОбход каждого сезонаСмотрите их документациюОдин вызов на сезон, список в seasons
Даты выходаРазбор текстаСмотрите их документациюair_date и next_episode_to_air
КадрыСкачивание и изменение размераСмотрите их документациюФиксированные размеры на img.amodb.dev, без ключа
Другие порядки серийНедоступноСмотрите их документациюСписок episode_groups, содержимое групп не отдается
ЯзыкиОдна локаль на сайтСмотрите их документацию14 языков через language

Цены

Тарифы оплачиваются заранее на 1, 3, 6, 12 или 24 месяца, со скидкой 0, 10, 20, 30 или 40 процентов за более длинные периоды, и сами не продлеваются. Тарифы на 20, 40 и 120 запросов в минуту возвращают все эндпоинты этой страницы. Обновление сериала стоит один запрос на данные и по одному на каждый сезон. Бесплатного тарифа нет. Выберите тариф на странице цены.