Pósters de películas desde un host de imágenes que no necesita clave

La URL de un póster es https://img.amodb.dev/t/p/{size}/{file}. La parte del archivo es la cadena poster_path de cualquier respuesta de película, búsqueda o lista, y empieza con una barra. La parte del tamaño es un nombre como w342. Las imágenes no necesitan clave, así que navegadores y aplicaciones pueden cargarlas directamente. El JSON que te da el nombre del archivo sí necesita tu clave, y amodb es una API independiente que habla el protocolo TMDB v3, por lo que el código de imágenes que ya tienes sigue funcionando después de cambiar de host.

Qué obtienes:

  • Pósters, imágenes de fondo (backdrop), logotipos, fotos de perfil y fotogramas de episodio en un solo host.
  • Diez nombres de tamaño, de w92 a original.
  • Listas de pósters por título, con idioma, ancho y alto en cada elemento.
  • Una caché perimetral de 30 días para las imágenes.

Qué datos obtienes

ImagenEl nombre del archivo sale deTamaños habituales
Póster de películaposter_path en /3/movie/{movie_id} y en las listasw92, w154, w185, w342, w500, w780, original
Imagen de fondo (backdrop)backdrop_pathw300, w780, w1280, original
Foto de personaprofile_path en /3/person/{person_id}w185, h632, original
Logotipo de productora o cadena de TVlogo_pathw92, w154, w185, w300, w500, original
Fotograma de episodiostill_pathw92, w185, w300, original
Todos los pósters de un títuloGET /3/movie/{movie_id}/imagesLista posters

Las series de TV, las temporadas y las colecciones también incluyen poster_path. Lee una sola vez al iniciar las listas exactas de tamaños del bloque images de GET /3/configuration en lugar de fijarlas en el código. La referencia de imágenes está en imágenes.

Empieza en 3 pasos

  1. Elige un plan en precios. Define la velocidad de las llamadas JSON: 20, 40 o 120 solicitudes por minuto.
  2. Crea una clave en el panel de tu cuenta.
  3. Lee poster_path en una llamada de detalles o de lista y colócalo detrás del host de imágenes y un nombre de tamaño.

Ejemplo de solicitud

El programa en Go lista los pósters de The Matrix (id de película 603) en inglés y sin texto, elige el más ancho, imprime un srcset listo para usar y guarda el archivo w342. La clave va solo en la llamada 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)
}

Una respuesta de imágenes recortada para include_image_language=en,null: 3 de los 145 pósters, uno en inglés, el más ancho en inglés y uno sin texto. La respuesta también contiene backdrops y logos, que aquí se omiten.

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
    }
  ]
}

Elige un tamaño

El número de un tamaño w es el ancho de la imagen en píxeles, y h632 es una altura. Los nombres pequeños ahorran ancho de banda, los grandes conservan el detalle en pantallas densas.

TamañoUso habitual
w92Sugerencias de búsqueda y filas de lista muy pequeñas
w154, w185Listas densas y tarjetas
w342Mosaicos de cuadrícula en teléfonos
w500Página de detalle
w780Pantallas grandes y pantallas 2x
originalArchivo o impresión, el archivo sin escalar

Ofrece al navegador varios anchos y deja que elija. El programa en Go de arriba imprime un srcset con candidatos de 185w, 342w, 500w y 780w. Combínalo con un atributo sizes que coincida con tu diseño, por ejemplo sizes="(max-width: 600px) 45vw, 185px" en el elemento img.

Idiomas de los pósters

Cada elemento de posters tiene un valor iso_639_1, que es un código de idioma o null para las ilustraciones sin texto. El parámetro include_image_language acepta una lista de códigos separados por comas.

ValorDevuelve
enPósters marcados como inglés
en,nullPósters en inglés y pósters sin texto
nullSolo pósters sin texto

Un buen orden de respaldo es el póster en el idioma de tu usuario, luego uno sin texto y después el inglés. Dentro de cada grupo, ordena por width y conserva el primero en caso de empate. vote_average y vote_count valen 0 en las imágenes de películas y series, así que no sirven para ordenar nada. Los idiomas de los pósters describen el texto impreso en la ilustración, por lo que no siguen los 14 idiomas de la interfaz. Revisa iso_639_1 en lo que recibas, porque el conjunto depende del título.

Almacenamiento y caché de los pósters

  • Guarda poster_path, no la URL completa. Con él puedes construir cualquier tamaño más adelante.
  • La caché perimetral conserva las imágenes 30 días. Los detalles se guardan 6 horas, así que vuelve a leer poster_path pasado ese tiempo para ver si cambió.
  • Mantén la clave en tu servidor. Envía al navegador solo las URL de las imágenes.
  • Cuando poster_path es null, muestra un marcador de posición en lugar de una imagen rota.

Cómo se compara

CapacidadHacer scraping de imágenes en las páginasAlojar tus propias copiasHost de imágenes de amodb
Clave necesariaNinguna, se aplican los términos de cada sitioNingunaSin clave para las imágenes
Variantes de tamañoEl tamaño que sirva la páginaTú generas y guardas cada unaNombres de tamaño fijos en la URL, de w92 a original
Encontrar el archivoAnalizar el HTMLTu propia base de datosposter_path en cada respuesta
Idiomas de las ilustracionesPágina por páginaLo que hayas reunidoinclude_image_language en los endpoints de imágenes
Almacenamiento y ancho de bandaTuyos, más los de la fuenteTuyosEl navegador carga desde img.amodb.dev
CachéTuyaTuya30 días en el perímetro

Precios

Las descargas de imágenes no llevan clave. Tu plan limita solo las llamadas JSON que te dan los nombres de archivo, y las respuestas de lista ya incluyen poster_path de cada elemento, así que una llamada de lista alimenta toda una cuadrícula. Elige 20, 40 o 120 solicitudes por minuto en precios. El acceso es prepago por 1, 3, 6, 12 o 24 meses con un 0, 10, 20, 30 y 40 por ciento de descuento, nada se renueva solo y no hay nivel gratuito.