Des affiches de films depuis un hôte d'images sans clé

L'URL d'une affiche est https://img.amodb.dev/t/p/{size}/{file}. La partie file est la chaîne poster_path de n'importe quelle réponse de film, de recherche ou de liste, et elle commence par une barre oblique. La partie taille est un nom comme w342. Les images n'exigent aucune clé, donc les navigateurs et les applications peuvent les charger directement. Le JSON qui vous donne le nom du fichier exige toujours votre clé, et amodb est une API indépendante qui parle le protocole TMDB v3 : le code d'images existant continue de fonctionner après un changement d'hôte.

Ce que vous obtenez :

  • Des affiches, des images de fond, des logos, des photos de profil et des images d'épisodes sur un seul hôte.
  • Dix noms de taille, de w92 à original.
  • Des listes d'affiches par titre, avec la langue, la largeur et la hauteur de chaque élément.
  • Un cache de périphérie de 30 jours pour les images.

Les données obtenues

ImageLe nom du fichier vient deTailles courantes
Affiche de filmposter_path sur /3/movie/{movie_id} et dans les listesw92, w154, w185, w342, w500, w780, original
Image de fondbackdrop_pathw300, w780, w1280, original
Photo de personneprofile_path sur /3/person/{person_id}w185, h632, original
Logo de société ou de chaînelogo_pathw92, w154, w185, w300, w500, original
Image d'épisodestill_pathw92, w185, w300, original
Toutes les affiches d'un titreGET /3/movie/{movie_id}/imagesTableau posters

Les séries, les saisons et les collections portent aussi poster_path. Lisez une fois au démarrage les listes de tailles exactes dans le bloc images de GET /3/configuration au lieu de les écrire en dur. La référence des images est sur images.

Démarrer en 3 étapes

  1. Choisissez une offre sur les tarifs. Elle fixe le débit des appels JSON : 20, 40 ou 120 requêtes par minute.
  2. Créez une clé dans le tableau de bord de votre compte.
  3. Lisez poster_path dans un appel de détails ou de liste, puis placez-le derrière l'hôte d'images et un nom de taille.

Exemple de requête

Le programme Go liste les affiches de The Matrix (id de film 603) en anglais et sans texte, choisit la plus large, affiche un srcset prêt à l'emploi et enregistre le fichier w342. La clé ne sert qu'à l'appel JSON.

bashgo
# the JSON call needs the key
curl -s "https://api.amodb.dev/3/movie/603/images?include_image_language=en,null" \
  -H "Authorization: Bearer $AMODB_KEY"

# the image call does not
curl -s -o poster.jpg "https://img.amodb.dev/t/p/w342/aOIuZAjPaRIE6CMzbazvcHuHXDc.jpg"
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

const imgBase = "https://img.amodb.dev/t/p/"

type poster struct {
	FilePath string  `json:"file_path"`
	Lang     *string `json:"iso_639_1"`
	Width    int     `json:"width"`
}

type images struct {
	Posters []poster `json:"posters"`
}

func srcset(file string) string {
	var parts []string
	for _, w := range []int{185, 342, 500, 780} {
		parts = append(parts, fmt.Sprintf("%sw%d%s %dw", imgBase, w, file, w))
	}
	return strings.Join(parts, ", ")
}

func main() {
	client := &http.Client{Timeout: 10 * time.Second}

	url := "https://api.amodb.dev/3/movie/603/images?include_image_language=en,null"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}

	var imgs images
	if err := json.NewDecoder(res.Body).Decode(&imgs); err != nil {
		panic(err)
	}
	if len(imgs.Posters) == 0 {
		fmt.Println("no posters")
		return
	}

	best := imgs.Posters[0]
	for _, p := range imgs.Posters {
		if p.Width > best.Width {
			best = p
		}
	}
	lang := "none"
	if best.Lang != nil {
		lang = *best.Lang
	}
	fmt.Println("best poster:", best.FilePath, "language:", lang, "width:", best.Width)
	fmt.Println("srcset:", srcset(best.FilePath))

	// Image requests carry no key.
	pic, err := client.Get(imgBase + "w342" + best.FilePath)
	if err != nil {
		panic(err)
	}
	defer pic.Body.Close()
	if pic.StatusCode != http.StatusOK {
		panic(pic.Status)
	}
	out, err := os.Create("poster.jpg")
	if err != nil {
		panic(err)
	}
	defer out.Close()
	io.Copy(out, pic.Body)
}

Une réponse d'images abrégée pour include_image_language=en,null : 3 des 145 affiches, une anglaise, la plus large des anglaises et une sans texte. La réponse contient aussi backdrops et logos, omis ici.

JSON
{
  "id": 603,
  "posters": [
    {
      "aspect_ratio": 0.667,
      "height": 2250,
      "iso_639_1": "en",
      "file_path": "/dXNAPwY7VrqMAo51EKhhCJfaGb5.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1500
    },
    {
      "aspect_ratio": 0.667,
      "height": 3000,
      "iso_639_1": "en",
      "file_path": "/aOIuZAjPaRIE6CMzbazvcHuHXDc.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 2000
    },
    {
      "aspect_ratio": 0.701,
      "height": 1426,
      "iso_639_1": null,
      "file_path": "/iLWzJxatuwwMT76dtMuwh3FEp2X.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1000
    }
  ]
}

Choisir une taille

Le nombre dans une taille w est la largeur de l'image en pixels, et h632 est une hauteur. Les petits noms économisent de la bande passante, les grands gardent le détail sur les écrans denses.

TailleUsage typique
w92Suggestions de recherche et toutes petites lignes de liste
w154, w185Listes denses et cartes
w342Vignettes de grille sur téléphone
w500Page de détails
w780Grands écrans et écrans 2x
originalArchive ou impression, le fichier sans redimensionnement

Donnez plusieurs largeurs au navigateur et laissez-le choisir. Le programme Go ci-dessus affiche un srcset avec des candidats 185w, 342w, 500w et 780w. Associez-le à un attribut sizes qui correspond à votre mise en page, par exemple sizes="(max-width: 600px) 45vw, 185px" sur l'élément img.

Langues des affiches

Chaque élément de posters a une valeur iso_639_1, soit un code de langue, soit null pour un visuel sans texte. Le paramètre include_image_language accepte une liste de codes séparés par des virgules.

ValeurRenvoie
enLes affiches marquées en anglais
en,nullLes affiches en anglais et les affiches sans texte
nullUniquement les affiches sans texte

Un bon ordre de repli est l'affiche dans la langue de l'utilisateur, puis une affiche sans texte, puis l'anglais. Dans chaque groupe, triez par width et gardez la première en cas d'égalité. vote_average et vote_count valent 0 sur les images de films et de séries, donc ils ne classent rien. Les langues des affiches décrivent le texte imprimé sur le visuel et ne suivent donc pas les 14 langues d'interface. Vérifiez iso_639_1 sur ce qui revient, car l'ensemble dépend du titre.

Stocker et mettre en cache les affiches

  • Enregistrez poster_path et non l'URL complète. Toute taille peut en être construite plus tard.
  • La périphérie met les images en cache 30 jours. Les détails sont mis en cache 6 heures : relisez donc poster_path après ce délai pour voir s'il a changé.
  • Gardez la clé sur votre serveur. N'envoyez au navigateur que les URL d'images.
  • Quand poster_path est null, affichez une image de remplacement plutôt qu'une image cassée.

Comparaison

CapacitéExtraire les images des pagesHéberger vos propres copiesHôte d'images amodb
Clé nécessaireAucune, les conditions de chaque site s'appliquentAucuneAucune clé pour les images
Variantes de tailleLa taille que sert la pageVous générez et stockez chacuneNoms de taille fixes dans l'URL, de w92 à original
Trouver le fichierAnalyser le HTMLVotre propre base de donnéesposter_path dans chaque réponse
Langues des visuelsPage par pageCe que vous avez collectéinclude_image_language sur les points de terminaison d'images
Stockage et bande passanteLes vôtres, plus ceux de la sourceLes vôtresLe navigateur charge depuis img.amodb.dev
CacheLe vôtreLe vôtre30 jours en périphérie

Tarifs

Le téléchargement des images ne demande aucune clé. Votre offre ne limite que les appels JSON qui vous donnent les noms de fichiers, et les réponses de liste incluent déjà poster_path pour chaque élément : un seul appel de liste alimente donc toute une grille. Choisissez 20, 40 ou 120 requêtes par minute sur les tarifs. L'accès est prépayé pour 1, 3, 6, 12 ou 24 mois avec 0, 10, 20, 30 et 40 pour cent de réduction, rien ne se renouvelle tout seul, et il n'y a pas d'offre gratuite.