Pósters de películas desde un host de imágenes que no necesita clave
La URL de un póster es https:/. 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
w92aoriginal. - 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
| Imagen | El nombre del archivo sale de | Tamaños habituales |
|---|---|---|
| Póster de película | poster_path en /3/movie/{movie_id} y en las listas | w92, w154, w185, w342, w500, w780, original |
| Imagen de fondo (backdrop) | backdrop_path | w300, w780, w1280, original |
| Foto de persona | profile_path en /3/person/{person_id} | w185, h632, original |
| Logotipo de productora o cadena de TV | logo_path | w92, w154, w185, w300, w500, original |
| Fotograma de episodio | still_path | w92, w185, w300, original |
| Todos los pósters de un título | GET / | Lista 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
- Elige un plan en precios. Define la velocidad de las llamadas JSON: 20, 40 o 120 solicitudes por minuto.
- Crea una clave en el panel de tu cuenta.
- Lee
poster_pathen 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.
# 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_: 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.
{
"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ño | Uso habitual |
|---|---|
w92 | Sugerencias de búsqueda y filas de lista muy pequeñas |
w154, w185 | Listas densas y tarjetas |
w342 | Mosaicos de cuadrícula en teléfonos |
w500 | Página de detalle |
w780 | Pantallas grandes y pantallas 2x |
original | Archivo 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= 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.
| Valor | Devuelve |
|---|---|
en | Pósters marcados como inglés |
en,null | Pósters en inglés y pósters sin texto |
null | Solo 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_pathpasado 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_pathes null, muestra un marcador de posición en lugar de una imagen rota.
Cómo se compara
| Capacidad | Hacer scraping de imágenes en las páginas | Alojar tus propias copias | Host de imágenes de amodb |
|---|---|---|---|
| Clave necesaria | Ninguna, se aplican los términos de cada sitio | Ninguna | Sin clave para las imágenes |
| Variantes de tamaño | El tamaño que sirva la página | Tú generas y guardas cada una | Nombres de tamaño fijos en la URL, de w92 a original |
| Encontrar el archivo | Analizar el HTML | Tu propia base de datos | poster_path en cada respuesta |
| Idiomas de las ilustraciones | Página por página | Lo que hayas reunido | include_image_language en los endpoints de imágenes |
| Almacenamiento y ancho de banda | Tuyos, más los de la fuente | Tuyos | El navegador carga desde img.amodb.dev |
| Caché | Tuya | Tuya | 30 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.