API за изображения и хост за изображения
Ендпойнтите за изображения изброяват постерите, фоновите изображения, логата, профилите и кадрите на заглавие като пътища до файлове. После зареждате всеки файл от img.amodb.dev във фиксиран размер, без ключ и с 30-дневен edge кеш. Пътищата и JSON съвпадат с TMDB v3, така че съществуващ код за изображения работи след смяна на базовия URL.
Вземане на изображения за филм
GET / изброява всяко известно изображение на един филм в три масива: backdrops, logos и posters. Всеки запис има file_path, размер в пиксели и таг за език. Самият файл не е в JSON. Зареждате го от хоста за изображения с втора стъпка.
Примерът иска английски изображения и такива без текст, избира първия английски постер и после изтегля този файл с ширина 500 пиксела.
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)
}Параметри
movie_idпътзадължителенЧислов id на филма, например550.api_keyзаявкаедин от дватаВашият ключ. Ползвайте него или заглавкатаAuthorization: Bearer.include_image_languageзаявкаКодове по ISO 639-1, разделени със запетая. Добаветеnull, за да включите изображения без текст, напримерen,null. Връщат се само изброените езици. Без него получавате всеки език.languageзаявкаПриема се, но на този ендпойнт се игнорира. За избор на езици ползвайтеinclude_image_language.
Полета на отговора
| Поле | Тип | Бележки |
|---|---|---|
id | цяло число | Id на филма. |
backdrops, logos, posters | масив | По един масив за вид изображение, в този ред на ключовете. Всеки може да е празен. |
file_path | низ | Започва с наклонена черта. Добавя се към размер на хоста за изображения. Постерите и фоновете са .jpg, логата са .png или .svg. |
width, height | цяло число | Размер на оригиналния файл в пиксели. 0, когато размерът не е известен. |
aspect_ratio | число | Ширина, разделена на височина. Постерите са около 0.667, фоновете около 1.778. 0, когато размерът не е известен. |
iso_639_1 | низ или null | Език на текста върху изображението. null означава, че няма текст. |
vote_average, vote_count | число, цяло число | Винаги 0 за изображения на филми и сериали, така че не могат да класират изображения. Запазете реда, който връща API. |
Примерен отговор
Показани са по два записа във всеки масив.
{
"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
}
]
}Вторият постер показва запис с неизвестен размер. Файлът пак се зарежда.
Как да построите URL на изображение
Съединете три части: https:/, сегмент за размер и file_path. Пътят вече започва с наклонена черта, така че https:/ плюс / е пълен URL адрес.
Размерът е w плюс ширина в пиксели, h плюс височина в пиксели или original за съхранения файл. Хостът обслужва десет размера: w92, w154, w185, w300, w342, w500, w780, w1280, h632 и original. Всеки друг размер, например w400, отговаря с 404. /3/configuration изброява размерите, които пасват на всеки вид изображение.
| Вид | Поле в конфигурацията | Размери |
|---|---|---|
| Постер | poster_sizes | w92, w154, w185, w342, w500, w780, original |
| Фоново изображение | backdrop_sizes | w300, w780, w1280, original |
| Лого | logo_sizes | w92, w154, w185, w300, w500, original |
| Профил | profile_sizes | w185, h632, original |
| Кадър | still_sizes | w92, w185, w300, original |
Хостът не проверява вида, така че постер се зарежда и в w1280. Останете при размерите, изброени за вида, за да съвпада кодът ви с конфигурацията и с всеки клиент на TMDB.
Хостът за изображения не иска ключ, а edge държи всеки файл 30 дни. Тъй като не се изпраща ключ, зареждането на изображения не харчи заявките ви в минута. Отговорите носят Access-Control-Allow-Origin: *, така че браузърът може да ги зарежда от всяка страница. Непознат размер или непознат файл отговаря с 404 и тяло JSON.
Адаптивни изображения със srcset
Изберете най-малкия размер, който все още покрива показваната ширина, умножена по плътността на екрана. Постер, показан с ширина 171 CSS пиксела, се нуждае от w342 на екран 2x. Тази помощна функция гради srcset от запазен път.
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">`);Други ендпойнти за изображения
Всички пътища по-долу ползват основата https:/ и връщат масивите, назовани във втората колона.
| Метод и път | Върнати масиви | Параметри |
|---|---|---|
GET / | backdrops, logos, posters | include_image_language |
GET / | posters, винаги празен | няма |
GET / | stills, един запис с width и height със стойност 0 | няма |
GET / | profiles | няма |
За филми и сериали можете да добавите и append_ към извикване за детайли. include_image_language работи и там. Добавеният блок няма собствен id.
Профилите на личности са единственото място, където vote_average носи истинска оценка. id в отговор за сезон или епизод е id на сезона или епизода. Вижте личности и сериали за родителските записи.
amodb не предлага пътища за изображения за колекции, компании и мрежи. Записите им вече съдържат по един poster_path, backdrop_path или logo_path, описани на страниците колекции и компании и мрежи.
Ендпойнтът за конфигурация
GET /3/configuration връща блок images с secure_base_url, равен на https:/, base_url (обикновената http форма) и списъците с размери backdrop_sizes, logo_sizes, poster_sizes, profile_sizes и still_sizes. Четете го веднъж при старт, ползвайте защитената форма и градете URL адреси от него, вместо да вписвате размери в кода. Edge го кешира за 24 часа.
Грешки
| HTTP | status_code | Кога |
|---|---|---|
| 401 | 7 | Ключът липсва или е грешен при JSON извикване. |
| 402 | 36 | Периодът на плана е изтекъл. |
| 404 | 34 | Няма личност, сезон или епизод с това id, или непознат размер или файл на хоста за изображения. |
| 405 | 37 | Ползвали сте метод за запис на път за изображения. |
| 429 | 25 | Надхвърлили сте лимита на заявки в минута. Изчакайте Retry-After секунди. |
Id на филм или сериал, което не съществува, тук не е грешка: пътят за изображения отговаря със 200 и празни масиви, докато пътят за детайли отговаря с 404. Вижте грешки за пълния списък. Заявките за файлове с изображения са обикновени HTTP зареждания, затова проверявайте статус кода на отговора, вместо да разчитате тяло JSON.
Практически бележки
- Пазете
file_pathв базата си и градете URL адреса при показване. Тогава нов размер или хост струва една промяна в кода. - Подайте
include_image_languageс езика си за показване плюсnull, напримерru,null, за да не се появяват постери с чужд текст. - Празен масив е нормален 200. Върнете се към
poster_pathв записа с детайли за филм. - Ползвайте
w1280за фонове на цяла ширина иw780за карти.originalе съхраненият файл в пълна резолюция и е доста по-голям отw780. - Копията на edge живеят 30 дни и са споделени, така че файл, поискан от един клиент, се обслужва от кеша на следващия.