API obrázků a hostitel obrázků
Endpointy obrázků vypisují plakáty, pozadí, loga, profily a záběry titulu jako cesty k souborům. Každý soubor pak načtete z img.amodb.dev v pevné velikosti, bez klíče a s cache na edge na 30 dní. Cesty a JSON odpovídají TMDB v3, takže stávající kód pro obrázky funguje po změně základní URL.
Získání obrázků filmu
GET / vypíše všechny známé obrázky jednoho filmu jako tři pole: backdrops, logos a posters. Každá položka má file_path, rozměry v pixelech a jazykový tag. Samotný soubor v JSON není. Načtete jej z hostitele obrázků druhým krokem.
Příklad si vyžádá anglické obrázky a obrázky bez textu, vybere první anglický plakát a pak načte tento soubor o šířce 500 pixelů.
curl -s "https://api.amodb.dev/3/movie/550/images?include_image_language=en,null" \
-H "Authorization: Bearer $AMODB_KEY"
curl -s -o poster.jpg -w "%{http_code}\n" \
"https://img.amodb.dev/t/p/w500/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg"const url = 'https://api.amodb.dev/3/movie/550/images?include_image_language=en,null';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { posters } = await res.json();
if (posters.length === 0) throw new Error('no posters');
const poster = posters.find((p) => p.iso_639_1 === 'en') ?? posters[0];
const posterUrl = `https://img.amodb.dev/t/p/w500${poster.file_path}`;
const img = await fetch(posterUrl);
console.log(img.status, img.headers.get('content-type'), posterUrl);import os
import requests
r = requests.get(
"https://api.amodb.dev/3/movie/550/images",
params={"include_image_language": "en,null"},
headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
timeout=10,
)
r.raise_for_status()
posters = r.json()["posters"]
if not posters:
raise SystemExit("no posters")
poster = next((p for p in posters if p["iso_639_1"] == "en"), posters[0])
poster_url = "https://img.amodb.dev/t/p/w500" + poster["file_path"]
img = requests.get(poster_url, timeout=10)
print(img.status_code, img.headers.get("content-type"), poster_url)<?php
$url = 'https://api.amodb.dev/3/movie/550/images?include_image_language=en,null';
$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");
}
$posters = json_decode($body, true)['posters'];
if (!$posters) {
throw new RuntimeException('no posters');
}
$poster = $posters[0];
foreach ($posters as $p) {
if ($p['iso_639_1'] === 'en') {
$poster = $p;
break;
}
}
$posterUrl = 'https://img.amodb.dev/t/p/w500' . $poster['file_path'];
$img = curl_init($posterUrl);
curl_setopt_array($img, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]);
curl_exec($img);
echo curl_getinfo($img, CURLINFO_HTTP_CODE), ' ', curl_getinfo($img, CURLINFO_CONTENT_TYPE), ' ', $posterUrl, PHP_EOL;
curl_close($img);package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type Images struct {
Posters []struct {
FilePath string `json:"file_path"`
Language string `json:"iso_639_1"`
} `json:"posters"`
}
func main() {
url := "https://api.amodb.dev/3/movie/550/images?include_image_language=en,null"
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 images Images
if err := json.NewDecoder(res.Body).Decode(&images); err != nil || len(images.Posters) == 0 {
panic("no posters")
}
poster := images.Posters[0]
for _, p := range images.Posters {
if p.Language == "en" {
poster = p
break
}
}
posterURL := "https://img.amodb.dev/t/p/w500" + poster.FilePath
img, err := client.Get(posterURL)
if err != nil {
panic(err)
}
defer img.Body.Close()
fmt.Println(img.StatusCode, img.Header.Get("Content-Type"), posterURL)
}Parametry
movie_idpathpovinnýČíselné ID filmu, například550.api_keyqueryjeden ze dvouVáš klíč. Použijte jej, nebo hlavičkuAuthorization: Bearer.include_image_languagequeryKódy ISO 639-1 oddělené čárkou. Přidejtenull, aby se zahrnuly obrázky bez textu, napříkladen,null. Vrátí se jen uvedené jazyky. Bez něj dostanete všechny jazyky.languagequeryNa tomto endpointu se přijímá, ale ignoruje. Jazyky vybírejte přesinclude_image_language.
Pole odpovědi
| Pole | Typ | Poznámky |
|---|---|---|
id | integer | ID filmu. |
backdrops, logos, posters | array | Jedno pole na druh obrázku, v tomto pořadí klíčů. Každé může být prázdné. |
file_path | string | Začíná lomítkem. Připojte jej k velikosti na hostiteli obrázků. Plakáty a pozadí jsou .jpg, loga .png nebo .svg. |
width, height | integer | Rozměr původního souboru v pixelech. 0, když rozměr není znám. |
aspect_ratio | number | Šířka dělená výškou. Plakáty jsou kolem 0.667, pozadí kolem 1.778. 0, když rozměr není znám. |
iso_639_1 | string nebo null | Jazyk textu na obrázku. null znamená bez textu. |
vote_average, vote_count | number, integer | U obrázků filmů a seriálů vždy 0, takže jimi nelze obrázky řadit. Ponechte pořadí, které API vrací. |
Příklad odpovědi
Zobrazeny jsou dvě položky v každém poli.
{
"id": 550,
"backdrops": [
{
"aspect_ratio": 1.778,
"height": 1440,
"iso_639_1": null,
"file_path": "/c6OLXfKAk5BKeR6broC8pYiCquX.jpg",
"vote_average": 0,
"vote_count": 0,
"width": 2560
},
{
"aspect_ratio": 1.778,
"height": 1080,
"iso_639_1": "en",
"file_path": "/b9HyPoxwxjxkWEUL5ErZdhApQe2.jpg",
"vote_average": 0,
"vote_count": 0,
"width": 1920
}
],
"logos": [
{
"aspect_ratio": 4.638,
"height": 389,
"iso_639_1": "en",
"file_path": "/7Uqhv24pGJs4Ns31NoOPWFJGWNG.png",
"vote_average": 0,
"vote_count": 0,
"width": 1804
},
{
"aspect_ratio": 0.848,
"height": 1295,
"iso_639_1": "en",
"file_path": "/4XkF0Rf7gvSfea8fYLFbU5tmuJw.png",
"vote_average": 0,
"vote_count": 0,
"width": 1098
}
],
"posters": [
{
"aspect_ratio": 0.667,
"height": 3000,
"iso_639_1": "en",
"file_path": "/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg",
"vote_average": 0,
"vote_count": 0,
"width": 2000
},
{
"aspect_ratio": 0,
"height": 0,
"iso_639_1": null,
"file_path": "/qkrH7rjYKU4KOwwIl6wF6H3ISvm.jpg",
"vote_average": 0,
"vote_count": 0,
"width": 0
}
]
}Druhý plakát ukazuje položku, jejíž rozměr není znám. Soubor se přesto načte.
Sestavení URL obrázku
Spojte tři části: https:/, segment velikosti a file_path. Cesta už začíná lomítkem, takže https:/ plus / je úplná URL.
Velikost je w plus šířka v pixelech, h plus výška v pixelech, nebo original pro uložený soubor. Hostitel obsluhuje deset velikostí: w92, w154, w185, w300, w342, w500, w780, w1280, h632 a original. Jakákoli jiná velikost, například w400, odpoví 404. /3/configuration uvádí velikosti, které se hodí pro každý druh obrázku.
| Druh | Pole konfigurace | Velikosti |
|---|---|---|
| Plakát | poster_sizes | w92, w154, w185, w342, w500, w780, original |
| Pozadí | backdrop_sizes | w300, w780, w1280, original |
| Logo | logo_sizes | w92, w154, w185, w300, w500, original |
| Profil | profile_sizes | w185, h632, original |
| Záběr | still_sizes | w92, w185, w300, original |
Hostitel druh nekontroluje, takže se plakát načte i ve velikosti w1280. Držte se velikostí uvedených pro daný druh, aby váš kód odpovídal konfiguraci a jakémukoli klientovi TMDB.
Hostitel obrázků klíč nepotřebuje a edge uchovává každý soubor 30 dní. Protože se neposílá klíč, načítání obrázků nespotřebovává vaše požadavky za minutu. Odpovědi nesou Access-Control-Allow-Origin: *, takže je prohlížeč může načíst z libovolné stránky. Neznámá velikost nebo neznámý soubor odpoví 404 s tělem JSON.
Responzivní obrázky se srcset
Vyberte nejmenší velikost, která stále pokryje zobrazenou šířku krát hustotu obrazovky. Plakát zobrazený o šířce 171 pixelů CSS potřebuje na obrazovce 2x w342. Tato pomocná funkce sestaví srcset z uložené cesty.
const WIDTHS = [185, 342, 500, 780];
function posterSrcset(filePath) {
return WIDTHS.map((w) => `https://img.amodb.dev/t/p/w${w}${filePath} ${w}w`).join(', ');
}
const path = '/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg';
console.log(`<img src="https://img.amodb.dev/t/p/w342${path}" srcset="${posterSrcset(path)}" sizes="(max-width: 600px) 50vw, 342px" alt="Fight Club poster">`);Další endpointy obrázků
Všechny cesty níže používají základ https:/ a vracejí pole uvedená ve druhém sloupci.
| Metoda a cesta | Vrácená pole | Parametry |
|---|---|---|
GET / | backdrops, logos, posters | include_image_language |
GET / | posters, vždy prázdné | žádné |
GET / | stills, jedna položka s width a height nastavenými na 0 | žádné |
GET / | profiles | žádné |
U filmů a seriálů můžete také přidat append_ k volání detailů. include_image_language funguje i tam. Přidaný blok nemá vlastní id.
Profily osob jsou jediné místo, kde vote_average nese skutečné skóre. id v odpovědi sezóny nebo epizody je ID sezóny nebo epizody. Nadřazené záznamy viz osoby a seriály.
amodb nenabízí cesty images pro kolekce, společnosti a sítě. Jejich záznamy už obsahují jedno poster_path, backdrop_path nebo logo_path, popsané na stránkách kolekce a společnosti a televizní sítě.
Endpoint konfigurace
GET /3/configuration vrací blok images s secure_base_url nastaveným na https:/, base_url (prostá forma http) a seznamy velikostí backdrop_sizes, logo_sizes, poster_sizes, profile_sizes a still_sizes. Přečtěte jej jednou při startu, použijte zabezpečenou formu a URL z něj sestavujte místo pevného zadání velikostí. Edge jej cachuje 24 hodin.
Chyby
| HTTP | status_code | Kdy |
|---|---|---|
| 401 | 7 | Klíč chybí nebo je nesprávný při volání JSON. |
| 402 | 36 | Platnost tarifu skončila. |
| 404 | 34 | Osoba, sezóna nebo epizoda s tímto ID neexistuje, nebo neznámá velikost či soubor na hostiteli obrázků. |
| 405 | 37 | Použili jste metodu pro zápis na cestě images. |
| 429 | 25 | Překročili jste počet požadavků za minutu. Počkejte tolik sekund, kolik říká Retry-After. |
ID filmu nebo seriálu, které neexistuje, zde není chyba: cesta images odpoví 200 s prázdnými poli, zatímco cesta detailů odpoví 404. Úplný seznam viz chyby. Požadavky na soubory obrázků jsou prosté načtení HTTP, kontrolujte proto stavový kód odpovědi místo parsování těla JSON.
Praktické poznámky
- Ukládejte
file_pathdo databáze a URL sestavujte při vykreslování. Nová velikost nebo hostitel pak stojí jednu změnu kódu. - Předejte
include_image_languages jazykem zobrazení plusnull, napříkladru,null, aby se neobjevovaly plakáty s cizím textem. - Prázdné pole je běžné 200. Použijte záložní
poster_pathze záznamu detailu filmu. - Pro hero pozadí přes celou šířku použijte
w1280a pro kartyw780.originalje uložený soubor v plném rozlišení a je mnohem větší nežw780. - Kopie na edge žijí 30 dní a jsou sdílené, takže soubor, který vyžádal jeden klient, se dalšímu obslouží z cache.