# Ścieżki dźwiękowe

> GET /3/movie/{movie_id}/soundtracks i GET /3/tv/{tv_id}/soundtracks zwracają album ze ścieżką dźwiękową tytułu w liście results. Każdy album ma źródło, nazwę, wykonawcę, datę wydania, link oraz listę tracks z polami disc, number, title, artist i czas trwania. Dodaj append_to_response=soundtracks, by scalić go ze szczegółami bez dodatkowego żądania.

## Endpoint

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

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

Odpowiedź:

```json
{
  "id": 155,
  "results": [
    {
      "source": "musicbrainz",
      "album": "The Dark Knight",
      "artist": "Hans Zimmer & James Newton Howard",
      "released": "2008-07-15",
      "url": "https://musicbrainz.org/release/814b2f7b-c27c-451e-abac-a316d2e6cea9",
      "track_count": 14,
      "tracks": [
        {
          "disc": 1,
          "number": 1,
          "title": "Why So Serious?",
          "artist": "Hans Zimmer",
          "duration_ms": 554000
        },
        {
          "disc": 1,
          "number": 2,
          "title": "I'm Not a Hero",
          "artist": "Hans Zimmer",
          "duration_ms": 395000
        },
        {
          "disc": 1,
          "number": 3,
          "title": "Harvey Two-Face",
          "artist": "James Newton Howard",
          "duration_ms": 377000
        }
      ]
    }
  ]
}
```

## Pobieranie ścieżki dźwiękowej filmu

`GET /3/movie/{movie_id}/soundtracks` zwraca album ze ścieżką dźwiękową jednego filmu. Odpowiedź niesie `id` filmu i tablicę `results`. Każda pozycja to album ze szczegółami i listą `tracks`.

Przykład pobiera The Dark Knight (ID 155) i wypisuje album oraz po jednym wierszu na utwór.

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

```js
const res = await fetch('https://api.amodb.dev/3/movie/155/soundtracks', {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results } = await res.json();
if (results.length === 0) console.log('no soundtrack album known');
for (const album of results) {
  console.log(`${album.album} by ${album.artist} (${album.track_count} tracks)`);
  for (const t of album.tracks) {
    console.log(`${t.number}. ${t.title} by ${t.artist}`);
  }
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/155/soundtracks",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
results = r.json()["results"]
if not results:
    print("no soundtrack album known")
for album in results:
    print(f"{album['album']} by {album['artist']} ({album['track_count']} tracks)")
    for t in album["tracks"]:
        print(f"{t['number']}. {t['title']} by {t['artist']}")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/155/soundtracks');
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");
}
$results = json_decode($body, true)['results'];
if (!$results) {
    echo 'no soundtrack album known', PHP_EOL;
}
foreach ($results as $album) {
    echo $album['album'], ' by ', $album['artist'] ?? 'unknown', ' (', $album['track_count'], ' tracks)', PHP_EOL;
    foreach ($album['tracks'] as $t) {
        echo $t['number'], '. ', $t['title'], ' by ', $t['artist'], PHP_EOL;
    }
}
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
)

type Track struct {
	Disc       int    `json:"disc"`
	Number     int    `json:"number"`
	Title      string `json:"title"`
	Artist     string `json:"artist"`
	DurationMs int    `json:"duration_ms"`
}

type Album struct {
	Source     string  `json:"source"`
	Album      string  `json:"album"`
	Artist     string  `json:"artist"`
	Released   string  `json:"released"`
	URL        string  `json:"url"`
	TrackCount int     `json:"track_count"`
	Tracks     []Track `json:"tracks"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/155/soundtracks", 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 body struct {
		Results []Album `json:"results"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		panic(err)
	}
	if len(body.Results) == 0 {
		fmt.Println("no soundtrack album known")
	}
	for _, a := range body.Results {
		fmt.Printf("%s by %s (%d tracks)\n", a.Album, a.Artist, a.TrackCount)
		for _, t := range a.Tracks {
			fmt.Printf("%d. %s by %s\n", t.Number, t.Title, t.Artist)
		}
	}
}
```

### Parametry

| Parametr   | Gdzie | Wymagany      | Opis                                                       |
| ---------- | ----- | ------------- | ---------------------------------------------------------- |
| `movie_id` | path  | tak           | Numeryczne ID filmu, na przykład `155`.                    |
| `api_key`  | query | jeden z dwóch | Twój klucz. Użyj go albo nagłówka `Authorization: Bearer`. |

### Pola odpowiedzi

| Pole                             | Typ             | Uwagi                                                                          |
| -------------------------------- | --------------- | ------------------------------------------------------------------------------ |
| `id`                             | integer         | ID filmu. Nieobecne przy użyciu `append_to_response`.                          |
| `results`                        | array           | Albumy. Puste, gdy nie jest znany żaden album. Dziś zawiera co najwyżej jeden. |
| `results[].source`               | string          | Skąd pochodzi album: `musicbrainz` lub `deezer`.                               |
| `results[].album`                | string          | Tytuł albumu.                                                                  |
| `results[].artist`               | string lub null | Wykonawca albumu, na przykład `Hans Zimmer & James Newton Howard`.             |
| `results[].released`             | string lub null | Data wydania jako `YYYY-MM-DD`.                                                |
| `results[].url`                  | string lub null | Link do strony albumu u źródła.                                                |
| `results[].track_count`          | integer         | Liczba utworów na albumie.                                                     |
| `results[].tracks`               | array           | Utwory w kolejności albumu.                                                    |
| `results[].tracks[].disc`        | integer         | Numer płyty, od 1.                                                             |
| `results[].tracks[].number`      | integer         | Numer utworu na płycie.                                                        |
| `results[].tracks[].title`       | string          | Tytuł utworu.                                                                  |
| `results[].tracks[].artist`      | string          | Wykonawca utworu.                                                              |
| `results[].tracks[].duration_ms` | integer         | Długość w milisekundach.                                                       |

Klucze, których używasz, czytaj po nazwie i pomijaj pozostałe.

### Przykładowa odpowiedź

```json
{
  "id": 155,
  "results": [
    {
      "source": "musicbrainz",
      "album": "The Dark Knight",
      "artist": "Hans Zimmer & James Newton Howard",
      "released": "2008-07-15",
      "url": "https://musicbrainz.org/release/814b2f7b-c27c-451e-abac-a316d2e6cea9",
      "track_count": 14,
      "tracks": [
        { "disc": 1, "number": 1, "title": "Why So Serious?", "artist": "Hans Zimmer", "duration_ms": 554000 },
        { "disc": 1, "number": 2, "title": "I'm Not a Hero", "artist": "Hans Zimmer", "duration_ms": 395000 },
        { "disc": 1, "number": 3, "title": "Harvey Two-Face", "artist": "James Newton Howard", "duration_ms": 377000 }
      ]
    }
  ]
}
```

Lista utworów jest przycięta do 3 z 14. Tytuł bez znanego albumu, taki jak Fight Club (ID 550), odpowiada pustą listą:

```json
{
  "id": 550,
  "results": []
}
```

## Pobieranie ścieżki dźwiękowej serialu

`GET /3/tv/{tv_id}/soundtracks` zwraca ten sam kształt dla serialu. Przekaż ID serialu, na przykład `1396`. Breaking Bad nie ma znanego albumu, więc jego tablica `results` jest pusta.

| Metoda i ścieżka                    | Zwraca                              | Parametry                                |
| ----------------------------------- | ----------------------------------- | ---------------------------------------- |
| `GET /movie/{movie_id}/soundtracks` | `id` i `results`                    | `movie_id`                               |
| `GET /tv/{tv_id}/soundtracks`       | `id` i `results`                    | `tv_id`                                  |
| `append_to_response=soundtracks`    | Te same `results` pod `soundtracks` | Dodawane do szczegółów filmu lub serialu |

Aby dostać album podczas ładowania strony filmu, dołącz go do szczegółów:

```bash
curl -sf "https://api.amodb.dev/3/movie/155?append_to_response=credits,soundtracks" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Dołączony blok leży pod kluczem `soundtracks` rekordu. Zawiera `results` i nie ma własnego `id`. Liczy się jako jedno żądanie.

## Budowanie listy muzyki z filmu

Posortuj według `disc` i `number`, pokaż tytuł i wykonawcę, a blok ukryj, gdy `results` jest puste. Poniższe funkcje zwracają wiersze zwykłego tekstu, które możesz wstawić do elementu listy.

```js
function clock(ms) {
  const s = Math.round(ms / 1000);
  return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
}

function musicLines(results) {
  const album = results[0];
  if (!album) return [];
  return [...album.tracks]
    .sort((a, b) => a.disc - b.disc || a.number - b.number)
    .map((t) => `${t.title} by ${t.artist} (${clock(t.duration_ms)})`);
}
```

Kilka pomysłów na interfejs, które nie wymagają dodatkowych danych:

| Pomysł                 | Jak                                                                                    |
| ---------------------- | -------------------------------------------------------------------------------------- |
| Lista numerowana       | Użyj `number` jako numeru na liście, a przy kilku płytach grupuj według `disc`.        |
| Link do albumu         | Połącz nazwę albumu z `url`, gdy nie jest null.                                        |
| Łączna długość         | Zsumuj `duration_ms` po utworach.                                                      |
| Połączenie z nastrojem | Pokaż listę obok [mierników nastroju](https://amodb.dev/pl/moods/) tego samego tytułu. |

## Błędy

Każda awaria zwraca `success` jako false z numerycznym `status_code`, tak jak TMDB.

| HTTP | status_code | Kiedy                                                                               |
| ---- | ----------- | ----------------------------------------------------------------------------------- |
| 401  | 7           | Brakuje klucza lub jest błędny.                                                     |
| 402  | 36          | Okres planu dobiegł końca.                                                          |
| 429  | 25          | Przekroczono limit żądań na minutę. Poczekaj tyle sekund, ile podaje `Retry-After`. |

Endpoint ścieżek dźwiękowych nie odpowiada 404 dla nieznanego ID. Odpowiada 200 z pustą tablicą `results`. Przy dołączeniu do szczegółów nieznane ID daje 404 z wywołania szczegółów. Wszystkie kody zobacz w [błędy](https://amodb.dev/pl/errors/), a nagłówki w [limity żądań](https://amodb.dev/pl/rate-limits/).

## Praktyczne uwagi

- Jak inne dane szczegółów, ścieżki dźwiękowe są w cache na edge przez 6 godzin. Krótszy cache klienta nic nie daje.
- Używaj `append_to_response=soundtracks` na stronie szczegółów, którą i tak ładujesz. Oszczędza żądanie z twoich 20, 40 lub 120 żądań na minutę.
- Nie wymagaj, by album istniał. Ukryj blok muzyczny, gdy `results` jest puste.
- Niektóre albumy pochodzą z MusicBrainz, a inne z Deezer. Film 27205 (Inception) ma album z Deezer. Kształt jest ten sam, więc sprawdzaj `source` tylko wtedy, gdy go pokazujesz.
- Nazwy utworów i wykonawców to zwykłe ciągi i mogą zawierać dowolny znak. Zapisuj je jako UTF-8 i escapuj przy wstawianiu do HTML.
- Zwiastun tego samego tytułu znajdziesz na stronie [wideo i zwiastuny](https://amodb.dev/pl/videos-trailers/).

## Pytania i odpowiedzi

### Co zawiera jedna pozycja soundtracku?

Jeden obiekt albumu. Ma źródło, nazwę albumu, wykonawcę, datę wydania, link i track_count. Jego tablica tracks wymienia każdy utwór z disc, number, title, artist i duration_ms. Odpowiedź niesie też ID tytułu.

### Czy dostanę pliki audio lub linki do streamingu?

Żadnego audio. Pole url prowadzi do strony albumu w MusicBrainz lub Deezer i może mieć wartość null. Aby użytkownicy mogli posłuchać, wyszukaj album w serwisie muzycznym, którego już używasz, i otwórz go z własnego interfejsu.

### Czy każdy tytuł ma ścieżkę dźwiękową?

Nie. Wiele tytułów, w tym Fight Club, nie ma znanego albumu, a odpowiedzią jest pusta tablica results. Dziś tytuł ma co najwyżej jeden album. Zaprojektuj blok muzyczny tak, by ukrywał się, gdy nie ma czego pokazać.

### Czy mogę pobrać ścieżki dźwiękowe serialu?

Tak. Wywołaj GET /3/tv/{tv_id}/soundtracks z ID serialu. Odpowiedź ma ten sam kształt co endpoint filmów, więc wystarczy jeden parser.

## 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.
- [Mierniki nastroju](https://amodb.dev/pl/moods/): API nastrojów z miernikami na skali od 0 do 10. Odczytaj nastroje filmu lub serialu, scal je przez append_to_response=moods i zbuduj plakietki albo filtry.
- [API wideo i zwiastunów](https://amodb.dev/pl/videos-trailers/): API wideo filmów ze ścieżkami TMDB v3: wypisz zwiastuny, teasery, klipy i featurette filmu lub serialu, a potem filtruj według typu i języka w kodzie.
- [Oceny filmów i seriali](https://amodb.dev/pl/ratings/): API ocen filmów zwraca wyniki z IMDb, Kinopoisk, Metacritic, Rotten Tomatoes i TMDB dla tytułu jednym wywołaniem, z null dla każdego nieznanego źródła.
- [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/soundtracks/
