API des vidéos et bandes-annonces
Les points de terminaison de vidéos listent les bandes-annonces, teasers, extraits et making of d'un film ou d'une série. Chaque entrée donne un hébergeur, une clé de vidéo, un type, un indicateur officiel, une taille et une date de publication. Les chemins de saisons et d'épisodes existent mais ne renvoient aucune vidéo. Filtrez par langue et type dans votre code.
Obtenir les vidéos d'un film
GET / renvoie les fiches vidéo associées à un film. Une fiche ne contient que des métadonnées : un nom, l'hébergeur qui sert la vidéo, la clé de la vidéo chez cet hébergeur, un type et quelques indicateurs. amodb ne renvoie pas de fichiers vidéo.
L'exemple affiche la première bande-annonce officielle en anglais, en se repliant sur n'importe quelle bande-annonce en anglais.
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")
}Paramètres
movie_idcheminobligatoireIdentifiant numérique du film, par exemple550.api_keyrequêtel'un des deuxVotre clé. Utilisez-la ou l'en-têteAuthorization: Bearer.language,include_video_languagerequêteAcceptés mais ignorés. La réponse contient toujours toutes les vidéos du titre. Filtrez pariso_639_1dans votre code.
Champs de la réponse
| Champ | Type | Remarques |
|---|---|---|
id | entier | Identifiant du film. |
results | tableau | Fiches vidéo, non triées par type ni par date. Vide quand aucune n'est connue. |
results[].iso_639_1, results[].iso_3166_1 | chaîne | Langue et pays de la vidéo, par exemple en et US. |
results[].name | chaîne | Titre de la vidéo, par exemple #TBT Trailer. |
results[].key | chaîne | Identifiant de la vidéo chez cet hébergeur. |
results[].site | chaîne | Nom de l'hébergeur de la vidéo. Toujours YouTube aujourd'hui. |
results[].size | entier | Résolution verticale. Toujours 1080 aujourd'hui. |
results[].type | chaîne | Trailer, Teaser, Clip, Featurette, Behind the Scenes, Bloopers, Opening Credits ou Recap. |
results[].official | booléen | Vrai quand le studio ou l'ayant droit l'a publiée. |
results[].published_at | chaîne | Horodatage ISO 8601, avec ou sans millisecondes. |
results[].id | chaîne | Identifiant de la fiche vidéo. Égal à key. |
Exemple de réponse
Trois des 19 fiches du film 550 sont montrées.
{
"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"
}
]
}Types de vidéos
Le champ type indique ce qu'est une vidéo. Faites la correspondance exacte, avec les majuscules indiquées.
| Type | À utiliser pour |
|---|---|
Trailer | La promo principale. À montrer sur une page de détails. |
Teaser | Une courte annonce qui précède la bande-annonce. |
Clip | Une scène tirée du film ou de l'épisode terminé. |
Featurette | Un court sujet sur la fabrication du titre. |
Behind the Scenes | Images de tournage et entretiens. |
Bloopers | Prises ratées et bêtisiers. |
Opening Credits | Le générique d'ouverture d'une série. |
Recap | Un résumé des épisodes précédents. |
D'autres valeurs peuvent apparaître avec le temps : traitez donc un type inconnu comme un extra générique et ne faites pas échouer le code.
Choisir la bonne vidéo
Utilisez le même ordre pour chaque titre. Essayez vos langues dans l'ordre. Dans une même langue, les bandes-annonces officielles viennent d'abord, puis n'importe quelle bande-annonce, puis les teasers, puis les extraits. Dans un groupe, triez par published_at : l'ordre croissant donne la première bande-annonce, l'ordre décroissant la plus récente.
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']);Langues
language et include_video_language ne changent pas la réponse : un seul appel donne donc toutes les vidéos du titre. Chaque fiche porte iso_639_1 et iso_3166_1. Le film 550 a des vidéos étiquetées fr, en, es, pt, it, cs, pl et ru. Filtrez par iso_639_1 dans votre code comme montré plus haut, puis indiquez à l'utilisateur dans quelle langue il va entendre la vidéo. Un titre peut n'avoir aucune vidéo dans la langue voulue : gardez donc un repli en anglais ou dans n'importe quelle langue. Les 14 langues servies sont listées sur langues.
Autres points de terminaison de vidéos
Les chemins ci-dessous renvoient la même forme id et results.
| Méthode et chemin | Renvoie |
|---|---|
GET / | Vidéos d'une série. |
GET / | Toujours un tableau results vide. |
GET / | Toujours un tableau results vide. |
Vous pouvez aussi ajouter append_ à un appel de détails de film ou de série. Le bloc ajouté contient results et pas d'id. Les pages de séries et de saisons sont décrites dans séries TV et saisons et épisodes.
Erreurs
| HTTP | status_code | Quand |
|---|---|---|
| 401 | 7 | La clé est absente ou fausse. |
| 402 | 36 | La période de l'offre est terminée. |
| 404 | 34 | Aucune saison ni aucun épisode avec cet identifiant, ou un identifiant qui n'est pas un nombre. |
| 405 | 37 | Vous avez utilisé une méthode d'écriture sur un chemin de vidéos. |
| 429 | 25 | Vous avez dépassé vos requêtes par minute. Attendez les secondes de Retry-After. |
Un identifiant de film ou de série qui n'existe pas n'est pas une erreur ici : le chemin de vidéos répond 200 avec "results": [], comme pour un titre connu sans vidéo. Le chemin de détails répond 404 pour un identifiant inconnu. Plus d'informations sur erreurs et limites de débit.
Remarques pratiques
- Stockez le
siteet lakeychoisis avec le titre, pas une adresse complète, afin de pouvoir changer de lecteur plus tard. - Les listes de vidéos suivent le cache de détails de 6 heures en périphérie. Un cache client de quelques heures y correspond.
sizevaut 1080 pour chaque fiche aujourd'hui : il ne vous dit donc pas quel extrait est léger. Laissez le lecteur choisir la qualité.- Ne comptez pas sur l'existence d'une seule bande-annonce. Masquez le bouton de lecture quand votre fonction de choix renvoie null.
- L'ordre de
resultsn'a aucun sens. Triez dans votre code. - Pour les fichiers d'affiches et d'images de fond, voir images. Pour la vue par cas d'usage, voir l'API de bandes-annonces.