API imagini și gazdă de imagini

Endpoint-urile de imagini listează posterele, imaginile de fundal, logourile, profilurile și cadrele unui titlu ca căi de fișiere. Apoi încarci fiecare fișier de la img.amodb.dev într-o dimensiune fixă, fără cheie și cu cache la margine de 30 de zile. Căile și JSON-ul se potrivesc cu TMDB v3, deci codul existent pentru imagini funcționează după schimbarea URL-ului de bază.

Actualizat Vezi ca Markdown

Obține imaginile unui film

GET /3/movie/{movie_id}/images listează fiecare imagine cunoscută a unui film în trei array-uri: backdrops, logos și posters. Fiecare intrare are un file_path, dimensiunea în pixeli și o etichetă de limbă. Fișierul în sine nu se află în JSON. Îl încarci de la gazda de imagini într-un al doilea pas.

Exemplul cere imagini în engleză și fără text, alege primul poster în engleză și apoi preia acel fișier la 500 de pixeli lățime.

bashjspyphpgo
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)
}

Parametri

  • movie_idcaleobligatoriu
    ID numeric de film, de exemplu 550.
  • api_keyinterogareuna dintre cele două
    Cheia ta. Folosește-o pe aceasta sau antetul Authorization: Bearer.
  • include_image_languageinterogare
    Coduri ISO 639-1 separate prin virgulă. Adaugă null ca să incluzi imaginile fără text, de exemplu en,null. Revin doar limbile listate. Fără el primești toate limbile.
  • languageinterogare
    Acceptat, dar ignorat pe acest endpoint. Folosește include_image_language ca să alegi limbile.

Câmpurile răspunsului

CâmpTipObservații
idnumăr întregID-ul filmului.
backdrops, logos, postersarrayCâte un array pentru fiecare fel de imagine, în această ordine a cheilor. Fiecare poate fi gol.
file_pathșirÎncepe cu o bară oblică. Adaugă-l la o dimensiune de pe gazda de imagini. Posterele și imaginile de fundal sunt .jpg, logourile sunt .png sau .svg.
width, heightnumăr întregDimensiunea în pixeli a fișierului original. 0 când dimensiunea nu se cunoaște.
aspect_rationumărLățimea împărțită la înălțime. Posterele sunt aproape de 0.667, imaginile de fundal aproape de 1.778. 0 când dimensiunea nu se cunoaște.
iso_639_1șir sau nullLimba textului de pe imagine. null înseamnă fără text.
vote_average, vote_countnumăr, număr întregMereu 0 la imaginile de film și de serial, deci nu pot ordona imaginile. Păstrează ordinea întoarsă de API.

Exemplu de răspuns

Sunt arătate două intrări pe array.

JSON
{
  "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
    }
  ]
}

Al doilea poster arată o intrare a cărei dimensiune nu se cunoaște. Fișierul se încarcă totuși.

Construiește un URL de imagine

Îmbină trei părți: https://img.amodb.dev/t/p/, un segment de dimensiune și file_path. Calea începe deja cu o bară oblică, deci https://img.amodb.dev/t/p/w500 plus /jSziioSwPVrOy9Yow3XhWIBDjq1.jpg este un URL complet.

O dimensiune este w plus o lățime în pixeli, h plus o înălțime în pixeli sau original pentru fișierul stocat. Gazda servește zece dimensiuni: w92, w154, w185, w300, w342, w500, w780, w1280, h632 și original. Orice altă dimensiune, precum w400, răspunde 404. /3/configuration listează dimensiunile care se potrivesc fiecărui fel de imagine.

FelCâmp de configurareDimensiuni
Posterposter_sizesw92, w154, w185, w342, w500, w780, original
Imagine de fundalbackdrop_sizesw300, w780, w1280, original
Logologo_sizesw92, w154, w185, w300, w500, original
Profilprofile_sizesw185, h632, original
Cadrustill_sizesw92, w185, w300, original

Gazda nu verifică felul, deci un poster se încarcă și la w1280. Rămâi la dimensiunile listate pentru fiecare fel, ca să se potrivească codul tău cu configurația și cu orice client TMDB.

Gazda de imagini nu cere cheie, iar marginea ține fiecare fișier 30 de zile. Pentru că nu se trimite nicio cheie, încărcările de imagini nu consumă cererile tale pe minut. Răspunsurile poartă Access-Control-Allow-Origin: *, deci un browser le poate încărca de pe orice pagină. O dimensiune necunoscută sau un fișier necunoscut răspunde 404 cu un corp JSON.

Imagini responsive cu srcset

Alege cea mai mică dimensiune care acoperă totuși lățimea afișată înmulțită cu densitatea ecranului. Un poster afișat la 171 de pixeli CSS lățime are nevoie de w342 pe un ecran 2x. Acest helper construiește un srcset dintr-o cale stocată.

JavaScript
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">`);

Alte endpoint-uri de imagini

Toate căile de mai jos folosesc baza https://api.amodb.dev/3 și întorc array-urile numite în a doua coloană.

Metodă și caleArray-uri întoarseParametri
GET /tv/{series_id}/imagesbackdrops, logos, postersinclude_image_language
GET /tv/{series_id}/season/{season_number}/imagesposters, mereu golniciunul
GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/imagesstills, o intrare cu width și height setate la 0niciunul
GET /person/{person_id}/imagesprofilesniciunul

Pentru filme și seriale poți adăuga și append_to_response=images la un apel de detalii. include_image_language funcționează și acolo. Blocul atașat nu are un id propriu.

Profilurile persoanelor sunt singurul loc în care vote_average poartă un scor real. id din răspunsul unui sezon sau episod este ID-ul sezonului sau episodului. Vezi persoane și seriale TV pentru înregistrările părinte.

amodb nu oferă căi de imagini pentru colecții, companii și rețele. Înregistrările lor conțin deja un singur poster_path, backdrop_path sau logo_path, descrise la colecții și companii și rețele.

Endpoint-ul de configurare

GET /3/configuration întoarce un bloc images cu secure_base_url setat la https://img.amodb.dev/t/p/, base_url (forma http simplă) și listele de dimensiuni backdrop_sizes, logo_sizes, poster_sizes, profile_sizes și still_sizes. Citește-l o dată la pornire, folosește forma securizată și construiește URL-urile din el în loc să scrii fix dimensiunile. Marginea îl ține în cache 24 de ore.

Erori

HTTPstatus_codeCând
4017Cheia lipsește sau este greșită la un apel JSON.
40236Perioada planului s-a încheiat.
40434Nu există o persoană, un sezon sau un episod cu acel ID, sau o dimensiune ori un fișier necunoscut pe gazda de imagini.
40537Ai folosit o metodă de scriere pe o cale de imagini.
42925Ai depășit cererile pe minut. Așteaptă numărul de secunde din Retry-After.

Un ID de film sau de serial care nu există nu este aici o eroare: calea de imagini răspunde 200 cu array-uri goale, în timp ce calea de detalii răspunde 404. Vezi erori pentru lista completă. Cererile de fișiere de imagine sunt încărcări HTTP simple, deci verifică codul de stare al răspunsului în loc să parsezi un corp JSON.

Note practice

  • Stochează file_path în baza ta de date și construiește URL-ul în momentul afișării. O dimensiune sau o gazdă nouă costă atunci o singură schimbare de cod.
  • Transmite include_image_language cu limba ta de afișare plus null, de exemplu ru,null, ca să nu apară postere cu text străin.
  • Un array gol este un 200 normal. Revino la poster_path din fișa de detalii film.
  • Folosește w1280 pentru imaginile de fundal pe toată lățimea și w780 pentru carduri. original este fișierul stocat la rezoluție completă și este mult mai mare decât w780.
  • Copiile de la margine trăiesc 30 de zile și sunt partajate, deci un fișier cerut de un client este servit din cache următorului.