# 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.

## Endpoint

`GET /3/movie/{movie_id}/videos`

```bash
curl "https://api.amodb.dev/3/movie/550/videos" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Odpověď:

```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": "20th Anniversary Trailer",
      "key": "dfeUzm6KF4g",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2019-10-15T18:59:47Z",
      "id": "dfeUzm6KF4g"
    }
  ]
}
```

## 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.

```bash
curl -s "https://api.amodb.dev/3/movie/550/videos" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
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');
```

```python
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
<?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;
```

```go
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

| Parametr                             | Kde   | Povinný       | Popis                                                                                                             |
| ------------------------------------ | ----- | ------------- | ----------------------------------------------------------------------------------------------------------------- |
| `movie_id`                           | path  | ano           | Číselné ID filmu, například `550`.                                                                                |
| `api_key`                            | query | jeden ze dvou | Váš klíč. Použijte jej, nebo hlavičku `Authorization: Bearer`.                                                    |
| `language`, `include_video_language` | query | ne            | 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

| Pole                                          | Typ     | Poznámky                                                                                                    |
| --------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
| `id`                                          | integer | ID filmu.                                                                                                   |
| `results`                                     | array   | Záznamy videí, neřazené podle typu ani data. Prázdné, když žádné nejsou známé.                              |
| `results[].iso_639_1`, `results[].iso_3166_1` | string  | Jazyk a země videa, například `en` a `US`.                                                                  |
| `results[].name`                              | string  | Název videa, například `#TBT Trailer`.                                                                      |
| `results[].key`                               | string  | ID videa u daného hostitele.                                                                                |
| `results[].site`                              | string  | Název hostitele videa. Dnes vždy `YouTube`.                                                                 |
| `results[].size`                              | integer | Svislé rozlišení. Dnes vždy `1080`.                                                                         |
| `results[].type`                              | string  | `Trailer`, `Teaser`, `Clip`, `Featurette`, `Behind the Scenes`, `Bloopers`, `Opening Credits` nebo `Recap`. |
| `results[].official`                          | boolean | True, když video zveřejnilo studio nebo držitel práv.                                                       |
| `results[].published_at`                      | string  | Časové razítko ISO 8601, s milisekundami nebo bez nich.                                                     |
| `results[].id`                                | string  | ID 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.

| Typ                 | K čemu ho použít                                  |
| ------------------- | ------------------------------------------------- |
| `Trailer`           | Hlavní upoutávka. Zobrazte ji na stránce detailu. |
| `Teaser`            | Krátké oznámení před trailerem.                   |
| `Clip`              | Scéna z hotového filmu nebo epizody.              |
| `Featurette`        | Krátký příspěvek o tom, jak titul vznikal.        |
| `Behind the Scenes` | Záběry z natáčení a rozhovory.                    |
| `Bloopers`          | Zkažené záběry a sestřihy gagů.                   |
| `Opening Credits`   | Úvodní znělka seriálu.                            |
| `Recap`             | Shrnutí 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ší.

```js
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](https://amodb.dev/cs/languages/).

## Další endpointy videí

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

| Metoda a cesta                                                               | Vrací                        |
| ---------------------------------------------------------------------------- | ---------------------------- |
| `GET /tv/{series_id}/videos`                                                 | Videa seriálu.               |
| `GET /tv/{series_id}/season/{season_number}/videos`                          | Vždy prázdné pole `results`. |
| `GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/videos` | Vž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](https://amodb.dev/cs/tv-series/) a [sezóny a epizody](https://amodb.dev/cs/tv-seasons-episodes/).

## Chyby

| HTTP | status_code | Kdy                                                                                         |
| ---- | ----------- | ------------------------------------------------------------------------------------------- |
| 401  | 7           | Klíč chybí nebo je nesprávný.                                                               |
| 402  | 36          | Platnost tarifu skončila.                                                                   |
| 404  | 34          | Sezóna ani epizoda s tímto ID neexistuje, nebo ID není číslo.                               |
| 405  | 37          | Použili jste metodu pro zápis na cestě videí.                                               |
| 429  | 25          | Př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](https://amodb.dev/cs/errors/) a [limity požadavků](https://amodb.dev/cs/rate-limits/).

## 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](https://amodb.dev/cs/images-api/). Pohled na případ užití viz [API trailerů filmů](https://amodb.dev/cs/movie-trailer-api/).

## Otázky a odpovědi

### Jak získám jen oficiální trailer?

Vyfiltrujte pole results, kde type je Trailer a official je true. Pokud zůstane více položek, seřaďte je podle published_at a vezměte nejstarší nebo nejnovější.

### Jak získám videa ve svém jazyce?

Endpoint vrací všechna videa titulu a ignoruje language i include_video_language. Filtrujte results podle iso_639_1 ve svém kódu, například nejdřív ru a en jako zálohu. Mnoho titulů nemá video v daném jazyce.

### Jak přehraji video z odpovědi?

Pole site použijte k volbě přehrávače a pole key jako ID videa na daném hostiteli. V dnes poskytovaných datech je site vždy YouTube. Adresu pro vložení nebo sledování sestavte podle vzoru daného hostitele. amodb vrací metadata, ne videosoubory.

### Mají epizody a sezóny vlastní videa?

Ne. Cesty videí sezón a epizod odpovídají 200 s prázdným polem results. Záznamy videí nesou jen filmy a seriály.

## Související stránky

- [API detailu filmu](https://amodb.dev/cs/movies/): API detailu filmu se stejnými cestami a JSON jako TMDB v3. Načtěte film podle ID, přidejte obsazení, hodnocení a nálady přes append_to_response, 14 jazyků.
- [API detailu seriálu](https://amodb.dev/cs/tv-series/): API detailu seriálu se stejnými cestami a JSON jako TMDB v3. Seriál podle ID se sezónami, sítěmi, věkovým hodnocením a poskytovateli streamování.
- [API sezón a epizod seriálů](https://amodb.dev/cs/tv-seasons-episodes/): API sezón a epizod seriálů se stejnými cestami a JSON jako TMDB v3. Načtěte sezónu se všemi epizodami nebo jednu epizodu s datem vysílání, délkou a záběrem.
- [API trailerů filmů](https://amodb.dev/cs/movie-trailer-api/): API trailerů filmů na endpointu videos TMDB v3. Řaďte trailery, teasery a klipy podle typu, příznaku official a kódu jazyka, jeden požadavek na titul.
- [API obrázků a hostitel obrázků](https://amodb.dev/cs/images-api/): API obrázků filmů s cestami TMDB v3: vypište plakáty, pozadí, loga a záběry každého titulu a načtěte je z img.amodb.dev v 10 velikostech bez klíče.
- [Rychlý start](https://amodb.dev/cs/quickstart/): První volání amodb: získejte klíč, vyžádejte detail filmu v curl, JavaScriptu, Pythonu, PHP nebo Go a načtěte plakát z img.amodb.dev. Za méně než 2 minuty.

Aktualizováno: 2026-10-18. Source: https://amodb.dev/cs/videos-trailers/
