API відео та трейлерів
Ендпоінти відео перелічують трейлери, тизери, кліпи й фічерети, прив'язані до фільму чи серіалу. Кожен запис дає назву хостингу, ключ відео, тип, прапорець офіційності, розмір і дату публікації. Шляхи сезонів і серій існують, але відео не повертають. Фільтруйте за мовою й типом у власному коді.
Отримання відео фільму
GET / повертає записи відео, прив'язані до одного фільму. Запис це лише метадані: назва, хостинг, що віддає відео, ключ відео на ньому, тип і кілька прапорців. amodb не повертає відеофайли.
Приклад виводить перший офіційний англійський трейлер, а за його відсутності будь-який англійський.
curl -s "https://api.amodb.dev/3/movie/550/videos" \
-H "Authorization: Bearer $AMODB_KEY"const url = 'https://api.amodb.dev/3/movie/550/videos';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results } = await res.json();
const trailers = results.filter((v) => v.type === 'Trailer' && v.iso_639_1 === 'en');
const pick = trailers.find((v) => v.official) ?? trailers[0];
console.log(pick ? `${pick.name} (${pick.site}, key ${pick.key})` : 'no trailer');import os
import requests
r = requests.get(
"https://api.amodb.dev/3/movie/550/videos",
headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
timeout=10,
)
r.raise_for_status()
trailers = [v for v in r.json()["results"] if v["type"] == "Trailer" and v["iso_639_1"] == "en"]
official = [v for v in trailers if v["official"]]
pick = (official or trailers or [None])[0]
print(f"{pick['name']} ({pick['site']}, key {pick['key']})" if pick else "no trailer")<?php
$url = 'https://api.amodb.dev/3/movie/550/videos';
$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");
}
$trailers = array_values(array_filter(
json_decode($body, true)['results'],
fn($v) => $v['type'] === 'Trailer' && $v['iso_639_1'] === 'en'
));
$official = array_values(array_filter($trailers, fn($v) => $v['official']));
$pick = $official[0] ?? $trailers[0] ?? null;
echo $pick ? "{$pick['name']} ({$pick['site']}, key {$pick['key']})" : 'no trailer', PHP_EOL;package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type Videos struct {
Results []struct {
Name string `json:"name"`
Key string `json:"key"`
Site string `json:"site"`
Type string `json:"type"`
Language string `json:"iso_639_1"`
Official bool `json:"official"`
} `json:"results"`
}
func main() {
url := "https://api.amodb.dev/3/movie/550/videos"
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 v Videos
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
panic(err)
}
for _, r := range v.Results {
if r.Type == "Trailer" && r.Language == "en" && r.Official {
fmt.Printf("%s (%s, key %s)\n", r.Name, r.Site, r.Key)
return
}
}
fmt.Println("no official trailer")
}Параметри
movie_idшляхобов'язковийЧисловий id фільму, наприклад550.api_keyqueryодин із двохВаш ключ. Використовуйте його або заголовокAuthorization: Bearer.language,include_video_languagequeryПриймаються, але ігноруються. Відповідь завжди містить усі відео назви. Фільтруйте заiso_639_1у своєму коді.
Поля відповіді
| Поле | Тип | Примітки |
|---|---|---|
id | ціле число | ID фільму. |
results | масив | Записи відео, не відсортовані за типом чи датою. Порожній, коли відео невідомі. |
results[].iso_639_1, results[].iso_3166_1 | рядок | Мова й країна відео, наприклад en і US. |
results[].name | рядок | Назва відео, наприклад #TBT Trailer. |
results[].key | рядок | ID відео на цьому хостингу. |
results[].site | рядок | Назва відеохостингу. Наразі завжди YouTube. |
results[].size | ціле число | Вертикальна роздільна здатність. Наразі завжди 1080. |
results[].type | рядок | Trailer, Teaser, Clip, Featurette, Behind the Scenes, Bloopers, Opening Credits або Recap. |
results[].official | булеве значення | True, коли відео опублікувала студія або правовласник. |
results[].published_at | рядок | Часова мітка ISO 8601 з мілісекундами або без них. |
results[].id | рядок | ID запису відео. Дорівнює key. |
Приклад відповіді
Показано три з 19 записів фільму 550.
{
"id": 550,
"results": [
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Theatrical Trailer (HD Fan Remaster)",
"key": "6JnN1DmbqoU",
"site": "YouTube",
"size": 1080,
"type": "Trailer",
"official": false,
"published_at": "2015-02-26T03:19:25Z",
"id": "6JnN1DmbqoU"
},
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "#TBT Trailer",
"key": "BdJKm16Co6M",
"site": "YouTube",
"size": 1080,
"type": "Trailer",
"official": true,
"published_at": "2014-10-02T19:20:22Z",
"id": "BdJKm16Co6M"
},
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Mark Kermode introduces Fight Club | Film4 Interview",
"key": "tiWCNtGDGEY",
"site": "YouTube",
"size": 1080,
"type": "Featurette",
"official": true,
"published_at": "2015-05-08T15:59:05Z",
"id": "tiWCNtGDGEY"
}
]
}Типи відео
Поле type вказує, що це за відео. Порівнюйте його точно, з великими літерами, як показано.
| Тип | Для чого використовувати |
|---|---|
Trailer | Головний промо-ролик. Показуйте його на сторінці деталей. |
Teaser | Короткий анонс, що виходить перед трейлером. |
Clip | Сцена з готового фільму чи серії. |
Featurette | Короткий матеріал про те, як створювали назву. |
Behind the Scenes | Кадри зі знімального майданчика та інтерв'ю. |
Bloopers | Невдалі дублі та добірки смішних моментів. |
Opening Credits | Заставка серіалу. |
Recap | Підсумок попередніх серій. |
З часом можуть з'явитися інші значення, тож сприймайте невідомий type як загальний додатковий матеріал і не допускайте збою через нього.
Вибір потрібного відео
Використовуйте однаковий порядок для кожної назви. Перебирайте ваші мови по черзі. У межах однієї мови спершу йдуть офіційні трейлери, потім будь-який трейлер, потім тизери, потім кліпи. У межах групи сортуйте за published_at: за зростанням дає перший трейлер, за спаданням найновіший.
function pickVideo(results, langs = ['en']) {
const order = ['Trailer', 'Teaser', 'Clip'];
for (const lang of langs) {
for (const type of order) {
const group = results
.filter((v) => v.iso_639_1 === lang && v.type === type)
.sort((a, b) => Number(b.official) - Number(a.official) || Date.parse(a.published_at) - Date.parse(b.published_at));
if (group.length > 0) return group[0];
}
}
return null;
}
// Russian first, English as the fallback.
// const video = pickVideo(results, ['ru', 'en']);Мови
language та include_video_language не змінюють відповідь, тож один виклик дає всі відео назви. Кожен запис містить iso_639_1 та iso_3166_1. Фільм 550 має відео з тегами fr, en, es, pt, it, cs, pl і ru. Фільтруйте за iso_639_1 у своєму коді, як показано вище, а потім покажіть користувачеві, якою мовою він зараз почує відео. У назви може не бути відео потрібною мовою, тому залиште запасний варіант: англійську або будь-яку мову. 14 обслуговуваних мов перелічено в розділі мови.
Інші ендпоінти відео
Шляхи нижче повертають ту саму структуру з id та results.
| Метод і шлях | Повертає |
|---|---|
GET / | Відео серіалу. |
GET / | Завжди порожній масив results. |
GET / | Завжди порожній масив results. |
Також можна додати append_ до виклику деталей фільму чи серіалу. Доданий блок містить results і не має id. Сторінки серіалів і сезонів описано в розділах серіали та сезони та серії.
Помилки
| HTTP | status_code | Коли |
|---|---|---|
| 401 | 7 | Ключ відсутній або хибний. |
| 402 | 36 | Термін дії тарифу закінчився. |
| 404 | 34 | Немає сезону чи серії з таким id або id не є числом. |
| 405 | 37 | Ви використали метод запису на шляху відео. |
| 429 | 25 | Ви перевищили ліміт запитів на хвилину. Зачекайте стільки секунд, скільки вказано в Retry-After. |
Неіснуючий id фільму чи серіалу тут не помилка: шлях відео відповідає 200 із "results": [], так само як для відомої назви без відео. Шлях деталей відповідає 404 для невідомого id. Докладніше про помилки та ліміти запитів.
Практичні нотатки
- Зберігайте обрані
siteіkeyразом із назвою, а не повну адресу, щоб пізніше можна було змінити плеєр. - Списки відео підпорядковуються кешу деталей: 6 годин на edge. Клієнтський кеш на кілька годин цьому відповідає.
sizeсьогодні дорівнює 1080 для кожного запису, тому за ним не можна визначити, який ролик легший. Дозвольте плеєру обирати якість.- Не покладайтеся на те, що трейлер існує. Ховайте кнопку відтворення, коли ваша функція вибору повертає null.
- Порядок
resultsне несе змісту. Сортуйте у своєму коді. - Файли постерів і фонів (backdrop) дивіться в розділі API зображень. Огляд сценарію використання дивіться в API трейлерів фільмів.