API dei video e dei trailer
Gli endpoint dei video elencano trailer, teaser, clip e featurette collegati a un film o a una serie. Ogni voce dà il nome dell'host, una chiave del video, un tipo, un flag ufficiale, una dimensione e una data di pubblicazione. I percorsi di stagioni ed episodi esistono ma non restituiscono video. Filtra per lingua e tipo nel tuo codice.
Ottenere i video di un film
GET / restituisce i record video collegati a un film. Un record contiene solo metadati: un nome, l'host che serve il video, la chiave del video su quell'host, un tipo e qualche flag. amodb non restituisce file video.
L'esempio stampa il primo trailer ufficiale in inglese, ripiegando su un qualsiasi trailer in inglese.
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")
}Parametri
movie_idpercorsoobbligatorioID numerico del film, per esempio550.api_keyqueryuno dei dueLa tua chiave. Usa questa o l'headerAuthorization: Bearer.language,include_video_languagequeryAccettati ma ignorati. La risposta contiene sempre tutti i video del titolo. Filtra periso_639_1nel tuo codice.
Campi della risposta
| Campo | Tipo | Note |
|---|---|---|
id | intero | ID del film. |
results | array | Record video, non ordinati per tipo o data. Vuoto quando non se ne conosce nessuno. |
results[].iso_639_1, results[].iso_3166_1 | stringa | Lingua e paese del video, per esempio en e US. |
results[].name | stringa | Titolo del video, per esempio #TBT Trailer. |
results[].key | stringa | ID del video su quell'host. |
results[].site | stringa | Nome dell'host del video. Oggi sempre YouTube. |
results[].size | intero | Risoluzione verticale. Oggi sempre 1080. |
results[].type | stringa | Trailer, Teaser, Clip, Featurette, Behind the Scenes, Bloopers, Opening Credits o Recap. |
results[].official | booleano | Vero quando lo studio o il titolare dei diritti l'ha pubblicato. |
results[].published_at | stringa | Timestamp ISO 8601, con o senza millisecondi. |
results[].id | stringa | ID del record video. Uguale a key. |
Risposta di esempio
Sono mostrati tre dei 19 record del film 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"
}
]
}Tipi di video
Il campo type ti dice cos'è un video. Confrontalo in modo esatto, con le maiuscole indicate.
| Tipo | Da usare per |
|---|---|
Trailer | La promo principale. Mostralo in una pagina di dettaglio. |
Teaser | Un breve annuncio che precede il trailer. |
Clip | Una scena presa dal film o dall'episodio finito. |
Featurette | Un breve pezzo su come è stato realizzato il titolo. |
Behind the Scenes | Riprese sul set e interviste. |
Bloopers | Scene fuori onda e gag. |
Opening Credits | La sigla di apertura di una serie. |
Recap | Un riassunto degli episodi precedenti. |
Col tempo possono comparire altri valori, quindi tratta un type sconosciuto come un extra generico e non far fallire il codice.
Scegliere il video giusto
Usa lo stesso ordine per ogni titolo. Prova le tue lingue in ordine. All'interno di una lingua vengono prima i trailer ufficiali, poi un trailer qualsiasi, poi i teaser, poi le clip. All'interno di un gruppo ordina per published_at: crescente dà il primo trailer, decrescente dà il più recente.
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']);Lingue
language e include_video_language non cambiano la risposta, quindi una sola chiamata dà tutti i video del titolo. Ogni record porta iso_639_1 e iso_3166_1. Il film 550 ha video etichettati fr, en, es, pt, it, cs, pl e ru. Filtra per iso_639_1 nel tuo codice come mostrato sopra, poi indica all'utente in che lingua sta per ascoltare. Un titolo può non avere alcun video nella lingua che vuoi, quindi tieni un ripiego sull'inglese o su una lingua qualsiasi. Le 14 lingue servite sono elencate nella pagina lingue.
Altri endpoint dei video
I percorsi qui sotto restituiscono la stessa struttura id e results.
| Metodo e percorso | Restituisce |
|---|---|
GET / | Video di una serie. |
GET / | Sempre un array results vuoto. |
GET / | Sempre un array results vuoto. |
Puoi anche aggiungere append_ a una chiamata di dettagli di film o serie. Il blocco aggiunto contiene results e nessun id. Le pagine di serie e stagioni sono descritte in serie TV e stagioni ed episodi.
Errori
| HTTP | status_code | Quando |
|---|---|---|
| 401 | 7 | La chiave manca o è sbagliata. |
| 402 | 36 | Il periodo del piano è terminato. |
| 404 | 34 | Nessuna stagione o episodio con quell'ID, o un ID che non è un numero. |
| 405 | 37 | Hai usato un metodo di scrittura su un percorso di video. |
| 429 | 25 | Hai superato le richieste al minuto. Attendi i secondi di Retry-After. |
Un ID di film o serie che non esiste non è un errore qui: il percorso dei video risponde 200 con "results": [], come per un titolo noto senza video. Il percorso dei dettagli risponde 404 per un ID sconosciuto. Altro nelle pagine errori e limiti di richieste.
Note pratiche
- Salva
siteekeyscelti insieme al titolo, non un indirizzo completo, così potrai cambiare player più avanti. - Le liste dei video seguono la cache dei dettagli di 6 ore sull'edge. Una cache client di poche ore corrisponde.
sizeoggi è 1080 per ogni record, quindi non ti dice quale clip sia leggera. Lascia che sia il player a scegliere la qualità.- Non contare sull'esistenza di un solo trailer. Nascondi il pulsante di riproduzione quando la tua funzione di scelta restituisce null.
- L'ordine di
resultsnon ha alcun significato. Ordina nel tuo codice. - Per i file di locandine e sfondi vedi immagini. Per la vista per caso d'uso, vedi l'API per i trailer.