API sezonów i odcinków seriali

Jeden sezon ze wszystkimi odcinkami odczytasz pod GET /3/tv/{series_id}/season/{season_number}, a pojedynczy odcinek poziom głębiej. JSON odpowiada TMDB v3 z air_date, episode_number, runtime i still_path. Każdy odcinek niesie crew i guest_stars, sezon 0 zawiera odcinki specjalne, a append_to_response dodaje credits, images i videos.

Zaktualizowano Zobacz jako Markdown

Pobieranie sezonu

GET /3/tv/{series_id}/season/{season_number} zwraca jeden sezon i jego pełną tablicę episodes w jednej odpowiedzi. Numery sezonów zaczynają się od 1, a 0 jest zarezerwowane dla odcinków specjalnych. ID serialu i numery sezonów weź z rekordu seriale.

Przykład odczytuje sezon 1 serialu Breaking Bad. Kod wypisuje jeden wiersz na odcinek.

bashjspyphpgo
curl -sSf "https://api.amodb.dev/3/tv/1396/season/1?language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
const url = 'https://api.amodb.dev/3/tv/1396/season/1?language=en-US';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const season = await res.json();
for (const ep of season.episodes) {
  console.log(String(ep.episode_number).padStart(2, '0'), ep.name, ep.air_date, `${ep.runtime ?? '?'} min`);
}
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/tv/1396/season/1",
    params={"language": "en-US"},
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
season = r.json()
for ep in season["episodes"]:
    print(f"{ep['episode_number']:02d}", ep["name"], ep["air_date"], ep["runtime"] or "?")
<?php
$url = 'https://api.amodb.dev/3/tv/1396/season/1?language=en-US';
$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");
}
$season = json_decode($body, true);
foreach ($season['episodes'] as $ep) {
    printf("%02d %s %s\n", $ep['episode_number'], $ep['name'], $ep['air_date']);
}
package main

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

type Season struct {
	Name     string `json:"name"`
	Episodes []struct {
		EpisodeNumber int    `json:"episode_number"`
		Name          string `json:"name"`
		AirDate       string `json:"air_date"`
		Runtime       int    `json:"runtime"`
	} `json:"episodes"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/tv/1396/season/1?language=en-US", 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 s Season
	if err := json.NewDecoder(res.Body).Decode(&s); err != nil {
		panic(err)
	}
	for _, e := range s.Episodes {
		fmt.Printf("%02d %s %s %d min\n", e.EpisodeNumber, e.Name, e.AirDate, e.Runtime)
	}
}

Parametry

  • series_idpathwymagany
    Numeryczne ID serialu, na przykład 1396.
  • season_numberpathwymagany
    Całkowity numer sezonu. 0 zwraca odcinki specjalne.
  • api_keyqueryjeden z dwóch
    Twój klucz. Użyj go albo nagłówka Authorization: Bearer.
  • languagequery
    Tag TMDB, na przykład en-US lub fr-FR. Obsługiwanych jest 14 języków bazowych. Domyślnie en-US.
  • append_to_responsequery
    Wartości na poziomie sezonu: credits, external_ids, images, videos. Inne nazwy są ignorowane.

Pola odpowiedzi

PoleTypUwagi
id, season_numberintegerID sezonu i jego numer w serialu.
name, overviewstringTekst zlokalizowany, pusty, gdy tłumaczenie nie istnieje.
air_datestring lub nullData pierwszego odcinka, YYYY-MM-DD.
poster_pathstring lub nullDołącz do https://img.amodb.dev/t/p/{size}.
vote_averagenumberZbiorcza ocena użytkowników dla sezonu.
episodesarrayKażdy odcinek, z polami wymienionymi w następnej sekcji.

Przykładowa odpowiedź

GET /3/tv/1396/season/1?language=en-US. Sezon ma 7 odcinków, więc episodes jest przycięte do jednej pozycji, a tablice crew i guest_stars tej pozycji pominięto:

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 of lung cancer, he decides to...",
      "production_code": "",
      "runtime": 59,
      "season_number": 1,
      "show_id": 1396,
      "still_path": "/ydlY3iPfeOAvu8gVqrxPoMvzNCn.jpg",
      "vote_average": 0,
      "vote_count": 0
    }
  ],
  "name": "Season 1",
  "overview": "High school chemistry teacher Walter White's life is suddenly transformed by a dire medical diagnosis. Stre...",
  "id": 3572,
  "poster_path": "/91EIXdWxmp2mHNRsSuDW3WyDJLj.jpg",
  "season_number": 1,
  "vote_average": 0
}

Każdy odcinek w odpowiedzi sezonu niesie też tablice crew i guest_stars o kształcie pozycji opisanym na stronie obsada i ekipa. runtime może mieć wartość null dla jeszcze niewyemitowanego odcinka.

Pobieranie odcinka

GET /3/tv/{series_id}/season/{season_number}/episode/{episode_number} zwraca jeden odcinek. Odpowiedź sezonu zawiera już każdy odcinek z crew i guest_stars, więc użyj tego endpointu, by odświeżyć jeden rekord bez ponownego ładowania sezonu. Przyjmuje language i append_to_response z credits, external_ids, images, translations i videos. Żądanie takie jak /3/tv/1396/season/1/episode/1?append_to_response=credits kosztuje jedno żądanie.

PoleTypUwagi
idintegerID odcinka.
show_idintegerID serialu. Obecne w odpowiedzi sezonu i we wskaźnikach serialu, nie w odpowiedzi pojedynczego odcinka.
season_number, episode_numberintegerPozycja w serialu. Użyj ich do zbudowania ścieżki żądania.
name, overviewstringTekst zlokalizowany.
air_datestring lub nullTylko data, bez godziny i strefy czasowej. Null, gdy niezaplanowany.
episode_typestringstandard dla zwykłych odcinków. Aby rozpoznać finał, porównaj episode_number z episode_count tego sezonu w rekordzie serialu.
runtimeinteger lub nullMinuty.
production_codestringKod studia, często pusty.
still_pathstring lub nullKadr odcinka. Użyj w300 lub original z https://img.amodb.dev/t/p/{size}.
vote_average, vote_countnumber, integerZbiorcza ocena użytkowników.
crew, guest_starsarrayRole w tym odcinku, zobacz obsada i ekipa.

Następny i ostatni odcinek w rekordzie serialu

Endpoint serialu zwraca next_episode_to_air i last_episode_to_air. Każdy to podsumowanie odcinka z powyższymi polami, plus show_id i bez crew i guest_stars. Następny ma wartość null dla zakończonych seriali i dla seriali powracających bez potwierdzonej daty. Przykład odczytuje South Park, serial powracający.

JavaScript
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };
const res = await fetch('https://api.amodb.dev/3/tv/2190', { headers });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const next = (await res.json()).next_episode_to_air;
console.log(next ? `Next: S${next.season_number}E${next.episode_number} on ${next.air_date}` : 'No upcoming episode');

Do odliczania porównaj air_date z lokalną datą widza. Wartość nie niesie pory dnia, więc pokaż datę, a nie godzinę na zegarze.

Podzasoby sezonów i odcinków

Ścieżki sezonów i odcinków mają własne podzasoby. Kilka z nich zwraca dziś puste dane.

Metoda i ścieżkaZwraca
GET /tv/{series_id}/season/{season_number}/creditsid, cast i crew sezonu
GET /tv/{series_id}/season/{season_number}/imagesid i pusta tablica posters
GET /tv/{series_id}/season/{season_number}/videosid i pusta tablica results
GET /tv/{series_id}/season/{season_number}/external_idsid plus tvdb_id, wikidata_id i inne ID, wszystkie null
GET /tv/{series_id}/season/{season_number}/translationsid i pusta tablica translations
GET .../episode/{episode_number}/creditsid, pusta cast, crew i guest_stars
GET .../episode/{episode_number}/imagesid i tablica stills z kadrem odcinka
GET .../episode/{episode_number}/videosid i pusta tablica results
GET .../episode/{episode_number}/external_idsid plus imdb_id, tvdb_id i inne ID, wszystkie null
GET .../episode/{episode_number}/translationsid i tablica translations z nazwą i opisem dla każdego języka

Obsadę sezonów i odcinków omawia strona obsada i ekipa, a kadry strona obrazy. amodb nie udostępnia ścieżek changes z TMDB ani endpointu dla odcinków jednej grupy odcinków.

Błędy

HTTPstatus_codeKiedy
4017Brakuje klucza lub jest błędny.
40236Okres planu dobiegł końca.
40434Serial, sezon lub odcinek nie istnieje, na przykład sezon 0 w serialu bez odcinków specjalnych, albo ścieżka nie jest udostępniana.
40537Wywołano metodę zapisu.
42925Przekroczono limit żądań na minutę. Poczekaj tyle sekund, ile podaje Retry-After.

Pełny format treści zobacz w błędy, a okna w limity żądań.

Praktyczne uwagi

  • Sezony i odcinki są w cache przez 6 godzin. Bieżący sezon odczytuj ponownie raz lub dwa razy dziennie, gdy serial jest emitowany.
  • Serial z 10 sezonami wymaga 10 wywołań sezonów. W planie z 20 żądaniami na minutę zużywa to połowę limitu jednej minuty, a powtórny przebieg w ciągu 6 godzin jest obsługiwany z cache na edge.
  • Niewyemitowany odcinek może mieć air_date null, runtime null i pusty overview. Wyrenderuj tekst zastępczy zamiast kończyć się błędem.
  • Kadry to szerokie klatki, a nie plakaty. Dla list żądaj w300, a original tylko wtedy, gdy potrzebujesz widoku w pełnym rozmiarze.