# API wideo i zwiastunów

> Endpointy wideo wypisują zwiastuny, teasery, klipy i featurette przypisane do filmu lub serialu. Każda pozycja podaje nazwę hosta, klucz wideo, typ, flagę official, rozmiar i datę publikacji. Ścieżki sezonów i odcinków istnieją, ale nie zwracają żadnych wideo. Według języka i typu filtruj we własnym kodzie.

## Endpoint

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

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

Odpowiedź:

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

## Pobieranie wideo filmu

`GET /3/movie/{movie_id}/videos` zwraca rekordy wideo powiązane z jednym filmem. Rekord to wyłącznie metadane: nazwa, host, który udostępnia wideo, klucz wideo u tego hosta, typ i kilka flag. amodb nie zwraca plików wideo.

Przykład wypisuje pierwszy oficjalny angielski zwiastun, a jako zapas bierze dowolny angielski zwiastun.

```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                             | Gdzie | Wymagany      | Opis                                                                                                                 |
| ------------------------------------ | ----- | ------------- | -------------------------------------------------------------------------------------------------------------------- |
| `movie_id`                           | path  | tak           | Numeryczne ID filmu, na przykład `550`.                                                                              |
| `api_key`                            | query | jeden z dwóch | Twój klucz. Użyj go albo nagłówka `Authorization: Bearer`.                                                           |
| `language`, `include_video_language` | query | nie           | Przyjmowane, ale ignorowane. Odpowiedź zawsze zawiera wszystkie wideo tytułu. Filtruj po `iso_639_1` w swoim kodzie. |

### Pola odpowiedzi

| Pole                                          | Typ     | Uwagi                                                                                                      |
| --------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------- |
| `id`                                          | integer | ID filmu.                                                                                                  |
| `results`                                     | array   | Rekordy wideo, nieposortowane według typu ani daty. Puste, gdy żadne nie są znane.                         |
| `results[].iso_639_1`, `results[].iso_3166_1` | string  | Język i kraj wideo, na przykład `en` i `US`.                                                               |
| `results[].name`                              | string  | Tytuł wideo, na przykład `#TBT Trailer`.                                                                   |
| `results[].key`                               | string  | ID wideo u tego hosta.                                                                                     |
| `results[].site`                              | string  | Nazwa hosta wideo. Dziś zawsze `YouTube`.                                                                  |
| `results[].size`                              | integer | Rozdzielczość pionowa. Dziś zawsze `1080`.                                                                 |
| `results[].type`                              | string  | `Trailer`, `Teaser`, `Clip`, `Featurette`, `Behind the Scenes`, `Bloopers`, `Opening Credits` lub `Recap`. |
| `results[].official`                          | boolean | True, gdy opublikowało je studio lub właściciel praw.                                                      |
| `results[].published_at`                      | string  | Znacznik czasu ISO 8601, z milisekundami lub bez.                                                          |
| `results[].id`                                | string  | ID rekordu wideo. Równe `key`.                                                                             |

### Przykładowa odpowiedź

Pokazano trzy z 19 rekordów 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 wideo

Pole `type` mówi, czym jest wideo. Dopasowuj dokładnie, z pokazanymi wielkimi literami.

| Typ                 | Do czego go użyć                                  |
| ------------------- | ------------------------------------------------- |
| `Trailer`           | Główna zapowiedź. Pokaż ją na stronie szczegółów. |
| `Teaser`            | Krótkie ogłoszenie poprzedzające zwiastun.        |
| `Clip`              | Scena z gotowego filmu lub odcinka.               |
| `Featurette`        | Krótki materiał o tym, jak powstawał tytuł.       |
| `Behind the Scenes` | Materiały z planu i wywiady.                      |
| `Bloopers`          | Wpadki i zestawy gagów.                           |
| `Opening Credits`   | Czołówka serialu.                                 |
| `Recap`             | Podsumowanie wcześniejszych odcinków.             |

Z czasem mogą pojawić się inne wartości, więc nieznany `type` traktuj jako ogólny dodatek i nie pozwól, by kod na nim zawiódł.

## Wybór właściwego wideo

Używaj tej samej kolejności dla każdego tytułu. Próbuj swoich języków po kolei. W obrębie jednego języka najpierw idą oficjalne zwiastuny, potem dowolny zwiastun, potem teasery, a potem klipy. W grupie sortuj według `published_at`: rosnąco daje pierwszy zwiastun, malejąco najnowszy.

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

## Języki

`language` i `include_video_language` nie zmieniają odpowiedzi, więc jedno wywołanie daje każde wideo tytułu. Każdy rekord niesie `iso_639_1` i `iso_3166_1`. Film 550 ma wideo oznaczone `fr`, `en`, `es`, `pt`, `it`, `cs`, `pl` i `ru`. Filtruj po `iso_639_1` w swoim kodzie, jak pokazano wyżej, a potem pokaż użytkownikowi, w jakim języku usłyszy wideo. Tytuł może nie mieć wideo w języku, którego chcesz, więc miej zapas po angielsku lub w dowolnym języku. 14 obsługiwanych języków jest wymienionych na stronie [języki](https://amodb.dev/pl/languages/).

## Inne endpointy wideo

Poniższe ścieżki zwracają ten sam kształt `id` i `results`.

| Metoda i ścieżka                                                             | Zwraca                          |
| ---------------------------------------------------------------------------- | ------------------------------- |
| `GET /tv/{series_id}/videos`                                                 | Wideo serialu.                  |
| `GET /tv/{series_id}/season/{season_number}/videos`                          | Zawsze pusta tablica `results`. |
| `GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/videos` | Zawsze pusta tablica `results`. |

Do wywołania szczegółów filmu lub serialu możesz też dodać `append_to_response=videos`. Dołączony blok zawiera `results` i nie ma `id`. Strony seriali i sezonów opisują [seriale](https://amodb.dev/pl/tv-series/) i [sezony i odcinki](https://amodb.dev/pl/tv-seasons-episodes/).

## Błędy

| HTTP | status_code | Kiedy                                                                               |
| ---- | ----------- | ----------------------------------------------------------------------------------- |
| 401  | 7           | Brakuje klucza lub jest błędny.                                                     |
| 402  | 36          | Okres planu dobiegł końca.                                                          |
| 404  | 34          | Brak sezonu lub odcinka o tym ID albo ID nie jest liczbą.                           |
| 405  | 37          | Użyto metody zapisu na ścieżce wideo.                                               |
| 429  | 25          | Przekroczono limit żądań na minutę. Poczekaj tyle sekund, ile podaje `Retry-After`. |

Nieistniejące ID filmu lub serialu nie jest tu błędem: ścieżka wideo odpowiada 200 z `"results": []`, tak samo jak znany tytuł bez wideo. Ścieżka szczegółów dla nieznanego ID odpowiada 404. Więcej w [błędy](https://amodb.dev/pl/errors/) i [limity żądań](https://amodb.dev/pl/rate-limits/).

## Praktyczne uwagi

- Zapisuj przy tytule wybrane `site` i `key`, a nie pełny adres, aby móc później zmienić odtwarzacz.
- Listy wideo podążają za cache szczegółów, 6 godzin na edge. Cache klienta na kilka godzin temu odpowiada.
- `size` wynosi dziś 1080 dla każdego rekordu, więc nie powie, które wideo jest lekkie. Jakość pozostaw odtwarzaczowi.
- Nie polegaj na tym, że zwiastun istnieje. Ukryj przycisk odtwarzania, gdy twoja funkcja wyboru zwróci null.
- Kolejność `results` nic nie znaczy. Sortuj w swoim kodzie.
- Pliki plakatów i teł zobacz w [obrazy](https://amodb.dev/pl/images-api/). Widok zastosowania zobacz w [API zwiastunów filmowych](https://amodb.dev/pl/movie-trailer-api/).

## Pytania i odpowiedzi

### Jak dostać tylko oficjalny zwiastun?

Przefiltruj tablicę results, wybierając type równe Trailer i official równe true. Jeśli zostanie kilka, posortuj według published_at, by wziąć najwcześniejszy lub najnowszy.

### Jak dostać wideo w moim języku?

Endpoint zwraca wszystkie wideo tytułu i ignoruje language oraz include_video_language. Filtruj results po iso_639_1 w swoim kodzie, na przykład najpierw ru, a en jako zapas. Wiele tytułów nie ma wideo w danym języku.

### Jak odtworzyć wideo z odpowiedzi?

Użyj pola site do wyboru odtwarzacza, a pola key jako ID wideo u tego hosta. W dzisiejszych danych site to zawsze YouTube. Adres osadzenia lub oglądania zbuduj według wzorca danego hosta. amodb zwraca metadane, a nie pliki wideo.

### Czy odcinki i sezony mają własne wideo?

Nie. Ścieżki wideo sezonów i odcinków odpowiadają 200 z pustą tablicą results. Rekordy wideo niosą tylko filmy i seriale.

## Powiązane strony

- [API szczegółów filmu](https://amodb.dev/pl/movies/): API szczegółów filmu z tymi samymi ścieżkami i JSON co TMDB v3. Pobierz film po ID, dołącz obsadę, oceny i nastroje przez append_to_response, 14 języków.
- [API szczegółów serialu](https://amodb.dev/pl/tv-series/): API szczegółów serialu z tymi samymi ścieżkami i JSON co TMDB v3. Serial po ID z sezonami, sieciami, klasyfikacją wiekową i dostawcami streamingu.
- [API sezonów i odcinków seriali](https://amodb.dev/pl/tv-seasons-episodes/): API sezonów i odcinków seriali z tymi samymi ścieżkami i JSON co TMDB v3. Odczytaj sezon ze wszystkimi odcinkami albo jeden odcinek z datą emisji i kadrem.
- [API zwiastunów filmowych](https://amodb.dev/pl/movie-trailer-api/): API zwiastunów filmowych na endpoincie videos TMDB v3. Sortuj zwiastuny, teasery i klipy według typu, flagi official i kodu języka, jedno żądanie na tytuł.
- [API obrazów i host obrazów](https://amodb.dev/pl/images-api/): API obrazów filmów ze ścieżkami TMDB v3: wypisz plakaty, tła, loga i kadry każdego tytułu, a potem ładuj je z img.amodb.dev w 10 rozmiarach bez klucza.
- [Szybki start](https://amodb.dev/pl/quickstart/): Pierwsze wywołanie amodb: zdobądź klucz, pobierz szczegóły filmu w curl, JavaScript, Python, PHP lub Go, potem załaduj plakat z img.amodb.dev. Poniżej 2 minut.

Zaktualizowano: 2026-10-18. Source: https://amodb.dev/pl/videos-trailers/
