API videí a trailerů

Endpointy videí vypisují trailery, teasery, klipy a featurety připojené k filmu nebo seriálu. Každá položka udává název hostitele, klíč videa, typ, příznak official, velikost a datum zveřejnění. Cesty sezón a epizod existují, ale žádná videa nevracejí. Podle jazyka a typu filtrujte ve vlastním kódu.

Aktualizováno Zobrazit jako Markdown

Získání videí filmu

GET /3/movie/{movie_id}/videos vrací záznamy videí připojené k jednomu filmu. Záznam jsou jen metadata: název, hostitel, který video poskytuje, klíč videa u tohoto hostitele, typ a několik příznaků. amodb videosoubory nevrací.

Příklad vypíše první oficiální anglický trailer a jako zálohu vezme libovolný anglický trailer.

bashjspyphpgo
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")
}

Parametry

  • movie_idpathpovinný
    Číselné ID filmu, například 550.
  • api_keyqueryjeden ze dvou
    Váš klíč. Použijte jej, nebo hlavičku Authorization: Bearer.
  • language, include_video_languagequery
    Přijímají se, ale ignorují. Odpověď vždy obsahuje všechna videa titulu. Filtrujte podle iso_639_1 ve svém kódu.

Pole odpovědi

PoleTypPoznámky
idintegerID filmu.
resultsarrayZáznamy videí, neřazené podle typu ani data. Prázdné, když žádné nejsou známé.
results[].iso_639_1, results[].iso_3166_1stringJazyk a země videa, například en a US.
results[].namestringNázev videa, například #TBT Trailer.
results[].keystringID videa u daného hostitele.
results[].sitestringNázev hostitele videa. Dnes vždy YouTube.
results[].sizeintegerSvislé rozlišení. Dnes vždy 1080.
results[].typestringTrailer, Teaser, Clip, Featurette, Behind the Scenes, Bloopers, Opening Credits nebo Recap.
results[].officialbooleanTrue, když video zveřejnilo studio nebo držitel práv.
results[].published_atstringČasové razítko ISO 8601, s milisekundami nebo bez nich.
results[].idstringID záznamu videa. Rovná se key.

Příklad odpovědi

Zobrazeny jsou tři z 19 záznamů filmu 550.

JSON
{
  "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"
    }
  ]
}

Typy videí

Pole type říká, co video je. Porovnávejte přesně, s uvedenými velkými písmeny.

TypK čemu ho použít
TrailerHlavní upoutávka. Zobrazte ji na stránce detailu.
TeaserKrátké oznámení před trailerem.
ClipScéna z hotového filmu nebo epizody.
FeaturetteKrátký příspěvek o tom, jak titul vznikal.
Behind the ScenesZáběry z natáčení a rozhovory.
BloopersZkažené záběry a sestřihy gagů.
Opening CreditsÚvodní znělka seriálu.
RecapShrnutí předchozích epizod.

Časem se mohou objevit další hodnoty, neznámý type proto berte jako obecný bonus a nenechte na něm kód selhat.

Výběr správného videa

Pro každý titul používejte stejné pořadí. Zkoušejte své jazyky podle pořadí. Uvnitř jednoho jazyka jdou první oficiální trailery, pak libovolný trailer, pak teasery a pak klipy. V rámci skupiny řaďte podle published_at: vzestupně dá první trailer, sestupně nejnovější.

JavaScript
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']);

Jazyky

language a include_video_language odpověď nemění, takže jedno volání dá každé video titulu. Každý záznam nese iso_639_1 a iso_3166_1. Film 550 má videa označená fr, en, es, pt, it, cs, pl a ru. Filtrujte podle iso_639_1 ve svém kódu, jak je ukázáno výše, a pak uživateli ukažte, v jakém jazyce video uslyší. Titul nemusí mít video v jazyce, který chcete, mějte proto zálohu v angličtině nebo v libovolném jazyce. Všech 14 podporovaných jazyků je uvedeno na stránce jazyky.

Další endpointy videí

Cesty níže vracejí stejný tvar id a results.

Metoda a cestaVrací
GET /tv/{series_id}/videosVidea seriálu.
GET /tv/{series_id}/season/{season_number}/videosVždy prázdné pole results.
GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/videosVždy prázdné pole results.

K volání detailů filmu nebo seriálu můžete také přidat append_to_response=videos. Přidaný blok obsahuje results a žádné id. Stránky seriálů a sezón popisují seriály a sezóny a epizody.

Chyby

HTTPstatus_codeKdy
4017Klíč chybí nebo je nesprávný.
40236Platnost tarifu skončila.
40434Sezóna ani epizoda s tímto ID neexistuje, nebo ID není číslo.
40537Použili jste metodu pro zápis na cestě videí.
42925Překročili jste počet požadavků za minutu. Počkejte tolik sekund, kolik říká Retry-After.

ID filmu nebo seriálu, které neexistuje, zde není chyba: cesta videí odpoví 200 s "results": [], stejně jako u známého titulu bez videí. Cesta detailů odpoví u neznámého ID 404. Více viz chyby a limity požadavků.

Praktické poznámky

  • Ukládejte u titulu vybraný site a key, ne celou adresu, abyste mohli později změnit přehrávač.
  • Seznamy videí sledují cache detailů, 6 hodin na edge. Cache u klienta na několik hodin tomu odpovídá.
  • size je dnes u každého záznamu 1080, takže nepoví, které video je lehké. Kvalitu nechte vybrat přehrávač.
  • Nespoléhejte na to, že trailer existuje. Tlačítko přehrání skryjte, když vaše funkce výběru vrátí null.
  • Pořadí results nic neznamená. Řaďte ve svém kódu.
  • Soubory plakátů a pozadí viz obrázky. Pohled na případ užití viz API trailerů filmů.