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 дзён і агульныя, таму файл, які запытаў адзін кліент, аддаецца з кэшу наступнаму.