API wideo i zwiastunów
Endpointy wideo wypisują zwiastuny, teasery, klipy i featurette przypisane do filmu lub serialu. Każda pozycja podaje nazwę hosta, klucz wideo, typ, flagę official, rozmiar i datę publikacji. Ścieżki sezonów i odcinków istnieją, ale nie zwracają żadnych wideo. Według języka i typu filtruj we własnym kodzie.
Pobieranie wideo filmu
GET / zwraca rekordy wideo powiązane z jednym filmem. Rekord to wyłącznie metadane: nazwa, host, który udostępnia wideo, klucz wideo u tego hosta, typ i kilka flag. amodb nie zwraca plików wideo.
Przykład wypisuje pierwszy oficjalny angielski zwiastun, a jako zapas bierze dowolny angielski zwiastun.
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")
}Parametry
movie_idpathwymaganyNumeryczne ID filmu, na przykład550.api_keyqueryjeden z dwóchTwój klucz. Użyj go albo nagłówkaAuthorization: Bearer.language,include_video_languagequeryPrzyjmowane, ale ignorowane. Odpowiedź zawsze zawiera wszystkie wideo tytułu. Filtruj poiso_639_1w swoim kodzie.
Pola odpowiedzi
| Pole | Typ | Uwagi |
|---|---|---|
id | integer | ID filmu. |
results | array | Rekordy wideo, nieposortowane według typu ani daty. Puste, gdy żadne nie są znane. |
results[].iso_639_1, results[].iso_3166_1 | string | Język i kraj wideo, na przykład en i US. |
results[].name | string | Tytuł wideo, na przykład #TBT Trailer. |
results[].key | string | ID wideo u tego hosta. |
results[].site | string | Nazwa hosta wideo. Dziś zawsze YouTube. |
results[].size | integer | Rozdzielczość pionowa. Dziś zawsze 1080. |
results[].type | string | Trailer, Teaser, Clip, Featurette, Behind the Scenes, Bloopers, Opening Credits lub Recap. |
results[].official | boolean | True, gdy opublikowało je studio lub właściciel praw. |
results[].published_at | string | Znacznik czasu ISO 8601, z milisekundami lub bez. |
results[].id | string | ID rekordu wideo. Równe key. |
Przykładowa odpowiedź
Pokazano trzy z 19 rekordów filmu 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"
}
]
}Typy wideo
Pole type mówi, czym jest wideo. Dopasowuj dokładnie, z pokazanymi wielkimi literami.
| Typ | Do czego go użyć |
|---|---|
Trailer | Główna zapowiedź. Pokaż ją na stronie szczegółów. |
Teaser | Krótkie ogłoszenie poprzedzające zwiastun. |
Clip | Scena z gotowego filmu lub odcinka. |
Featurette | Krótki materiał o tym, jak powstawał tytuł. |
Behind the Scenes | Materiały z planu i wywiady. |
Bloopers | Wpadki i zestawy gagów. |
Opening Credits | Czołówka serialu. |
Recap | Podsumowanie wcześniejszych odcinków. |
Z czasem mogą pojawić się inne wartości, więc nieznany type traktuj jako ogólny dodatek i nie pozwól, by kod na nim zawiódł.
Wybór właściwego wideo
Używaj tej samej kolejności dla każdego tytułu. Próbuj swoich języków po kolei. W obrębie jednego języka najpierw idą oficjalne zwiastuny, potem dowolny zwiastun, potem teasery, a potem klipy. W grupie sortuj według published_at: rosnąco daje pierwszy zwiastun, malejąco najnowszy.
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']);Języki
language i include_video_language nie zmieniają odpowiedzi, więc jedno wywołanie daje każde wideo tytułu. Każdy rekord niesie iso_639_1 i iso_3166_1. Film 550 ma wideo oznaczone fr, en, es, pt, it, cs, pl i ru. Filtruj po iso_639_1 w swoim kodzie, jak pokazano wyżej, a potem pokaż użytkownikowi, w jakim języku usłyszy wideo. Tytuł może nie mieć wideo w języku, którego chcesz, więc miej zapas po angielsku lub w dowolnym języku. 14 obsługiwanych języków jest wymienionych na stronie języki.
Inne endpointy wideo
Poniższe ścieżki zwracają ten sam kształt id i results.
| Metoda i ścieżka | Zwraca |
|---|---|
GET / | Wideo serialu. |
GET / | Zawsze pusta tablica results. |
GET / | Zawsze pusta tablica results. |
Do wywołania szczegółów filmu lub serialu możesz też dodać append_. Dołączony blok zawiera results i nie ma id. Strony seriali i sezonów opisują seriale i sezony i odcinki.
Błędy
| HTTP | status_code | Kiedy |
|---|---|---|
| 401 | 7 | Brakuje klucza lub jest błędny. |
| 402 | 36 | Okres planu dobiegł końca. |
| 404 | 34 | Brak sezonu lub odcinka o tym ID albo ID nie jest liczbą. |
| 405 | 37 | Użyto metody zapisu na ścieżce wideo. |
| 429 | 25 | Przekroczono limit żądań na minutę. Poczekaj tyle sekund, ile podaje Retry-After. |
Nieistniejące ID filmu lub serialu nie jest tu błędem: ścieżka wideo odpowiada 200 z "results": [], tak samo jak znany tytuł bez wideo. Ścieżka szczegółów dla nieznanego ID odpowiada 404. Więcej w błędy i limity żądań.
Praktyczne uwagi
- Zapisuj przy tytule wybrane
siteikey, a nie pełny adres, aby móc później zmienić odtwarzacz. - Listy wideo podążają za cache szczegółów, 6 godzin na edge. Cache klienta na kilka godzin temu odpowiada.
sizewynosi dziś 1080 dla każdego rekordu, więc nie powie, które wideo jest lekkie. Jakość pozostaw odtwarzaczowi.- Nie polegaj na tym, że zwiastun istnieje. Ukryj przycisk odtwarzania, gdy twoja funkcja wyboru zwróci null.
- Kolejność
resultsnic nie znaczy. Sortuj w swoim kodzie. - Pliki plakatów i teł zobacz w obrazy. Widok zastosowania zobacz w API zwiastunów filmowych.