# Саундтраци

> GET /3/movie/{movie_id}/soundtracks и GET /3/tv/{tv_id}/soundtracks връщат албума със саундтрака на заглавие в списък results. Всеки албум има source, име, изпълнител, дата на излизане, връзка и списък tracks с disc, number, title, artist и продължителност. Добавете append_to_response=soundtracks, за да го слеете с детайлите.

## Ендпойнт

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

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

Отговор:

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

## Вземане на саундтрака на филм

`GET /3/movie/{movie_id}/soundtracks` връща албума със саундтрака на един филм. Отговорът носи `id` на филма и масив `results`. Всеки запис е албум със своите детайли и списък `tracks`.

Примерът зарежда The Dark Knight (id 155) и отпечатва албума и по един ред за песен.

```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)
		}
	}
}
```

### Параметри

| Параметър  | Къде   | Задължителен  | Описание                                                            |
| ---------- | ------ | ------------- | ------------------------------------------------------------------- |
| `movie_id` | път    | да            | Числов id на филма, например `155`.                                 |
| `api_key`  | заявка | един от двата | Вашият ключ. Ползвайте него или заглавката `Authorization: Bearer`. |

### Полета на отговора

| Поле                             | Тип          | Бележки                                                                  |
| -------------------------------- | ------------ | ------------------------------------------------------------------------ |
| `id`                             | цяло число   | Id на филма. Липсва, когато ползвате `append_to_response`.               |
| `results`                        | масив        | Албуми. Празен, когато няма известен албум. Днес съдържа най-много един. |
| `results[].source`               | низ          | Откъде идва албумът: `musicbrainz` или `deezer`.                         |
| `results[].album`                | низ          | Заглавие на албума.                                                      |
| `results[].artist`               | низ или null | Изпълнител на албума, например `Hans Zimmer & James Newton Howard`.      |
| `results[].released`             | низ или null | Дата на излизане във вида `YYYY-MM-DD`.                                  |
| `results[].url`                  | низ или null | Връзка към страницата на албума при източника.                           |
| `results[].track_count`          | цяло число   | Брой песни в албума.                                                     |
| `results[].tracks`               | масив        | Песни по ред в албума.                                                   |
| `results[].tracks[].disc`        | цяло число   | Номер на диска, започвайки от 1.                                         |
| `results[].tracks[].number`      | цяло число   | Номер на песента на диска.                                               |
| `results[].tracks[].title`       | низ          | Заглавие на песента.                                                     |
| `results[].tracks[].artist`      | низ          | Изпълнител на песента.                                                   |
| `results[].tracks[].duration_ms` | цяло число   | Дължина в милисекунди.                                                   |

Четете ключовете, които ползвате, по име и пропускайте останалите.

### Примерен отговор

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

Списъкът с песни е съкратен до 3 от 14. Заглавие без известен албум, като Fight Club (id 550), отговаря с празен списък:

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

## Вземане на саундтрака на сериал

`GET /3/tv/{tv_id}/soundtracks` връща същата форма за сериал. Подайте id на сериала, например `1396`. Breaking Bad няма известен албум, затова масивът му `results` е празен.

| Метод и път                         | Какво връща                        | Параметри                                  |
| ----------------------------------- | ---------------------------------- | ------------------------------------------ |
| `GET /movie/{movie_id}/soundtracks` | `id` и `results`                   | `movie_id`                                 |
| `GET /tv/{tv_id}/soundtracks`       | `id` и `results`                   | `tv_id`                                    |
| `append_to_response=soundtracks`    | Същият `results` под `soundtracks` | Добавя се към детайлите на филм или сериал |

За да вземете албума, докато зареждате страница на филм, добавете го към детайлите:

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

Добавеният блок стои под ключа `soundtracks` на записа. Съдържа `results` и няма собствено `id`. Брои се като една заявка.

## Списък „музика от този филм“

Сортирайте по `disc` и `number`, показвайте заглавието и изпълнителя и скривайте блока, когато `results` е празен. Функциите по-долу връщат прости текстови редове, които можете да сложите в елемент от списък.

```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)})`);
}
```

Няколко идеи за интерфейс, които не искат допълнителни данни:

| Идея                   | Как                                                                                                 |
| ---------------------- | --------------------------------------------------------------------------------------------------- |
| Номериран списък       | Ползвайте `number` като номер в списъка и групирайте по `disc`, когато дисковете са няколко.        |
| Връзка към албума      | Свържете името на албума с `url`, когато не е null.                                                 |
| Обща продължителност   | Съберете `duration_ms` на песните.                                                                  |
| Съчетание с настроение | Показвайте списъка до [индикаторите за настроение](https://amodb.dev/bg/moods/) на същото заглавие. |

## Грешки

Всяка грешка връща `success` със стойност false и числов `status_code`, както прави TMDB.

| HTTP | status_code | Кога                                                                      |
| ---- | ----------- | ------------------------------------------------------------------------- |
| 401  | 7           | Ключът липсва или е грешен.                                               |
| 402  | 36          | Периодът на плана е изтекъл.                                              |
| 429  | 25          | Надхвърлен е лимитът на заявки в минута. Изчакайте `Retry-After` секунди. |

Ендпойнтът за саундтраци не отговаря с 404 за непознато id. Отговаря със 200 и празен масив `results`. Когато се добавя към детайлите, непознато id дава 404 от извикването за детайли. Вижте [грешки](https://amodb.dev/bg/errors/) за всеки код и [лимити на заявките](https://amodb.dev/bg/rate-limits/) за заглавките.

## Практически бележки

- Както другите данни за детайли, саундтраците се кешират на edge за 6 часа. По-кратък клиентски кеш не носи полза.
- Ползвайте `append_to_response=soundtracks` на страница с детайли, която вече зареждате. Така спестявате една от вашите 20, 40 или 120 заявки в минута.
- Не изисквайте албумът да съществува. Скривайте блока с музика, когато `results` е празен.
- Някои албуми идват от MusicBrainz, а други от Deezer. Филм 27205 (Inception) има албум от Deezer. Формата е една и съща, така че проверявайте `source`, само ако го показвате.
- Имената на песни и изпълнители са прости низове и могат да съдържат всякакъв знак. Пазете ги в UTF-8 и ги екранирайте, когато ги слагате в HTML.
- За трейлъра на същото заглавие вижте [видеа и трейлъри](https://amodb.dev/bg/videos-trailers/).

## Въпроси и отговори

### Какво съдържа един запис за саундтрак?

Един обект на албум. Има source, име на албума, изпълнител, дата на излизане, връзка и track_count. Масивът tracks изброява всяка песен с disc, number, title, artist и duration_ms. Отговорът носи и id на заглавието.

### Получавам ли аудио файлове или връзки за стрийминг?

Няма аудио. Полето url сочи към страницата на албума в MusicBrainz или Deezer и може да е null. За да слушат потребителите, потърсете албума в музикалната услуга, която вече ползвате, и го отворете от собствения си интерфейс.

### Има ли саундтрак за всяко заглавие?

Не. Много заглавия, сред тях Fight Club, нямат известен албум и отговорът е празен масив results. Днес едно заглавие има най-много един албум. Проектирайте блока с музика така, че да се скрива, когато няма какво да се покаже.

### Мога ли да взема саундтраци за сериал?

Да. Извикайте GET /3/tv/{tv_id}/soundtracks с id на сериала. Отговорът има същата форма като ендпойнта за филми, така че един парсер покрива и двата.

## Свързани страници

- [API за детайли на филм](https://amodb.dev/bg/movies/): API за детайли на филм със същите пътища и JSON като TMDB v3. Един филм по id, а актьори, рейтинги и настроения през append_to_response, на 14 езика.
- [API за сериали](https://amodb.dev/bg/tv-series/): API за сериали със същите пътища и JSON като TMDB v3. Сериал по id със сезони, мрежи и следващ епизод, плюс възрастови рейтинги и доставчици за гледане.
- [Индикатори за настроение](https://amodb.dev/bg/moods/): API за настроение с индикатори от 0 до 10 за заглавие. Вземете настроението на филм или сериал, добавете го с append_to_response=moods и направете значки.
- [API за видеа и трейлъри](https://amodb.dev/bg/videos-trailers/): API за видеа с пътища на TMDB v3: списък с трейлъри, тийзъри, клипове и featurette за филм или сериал, после филтриране по тип и език във вашия код.
- [Рейтинги на филми и сериали](https://amodb.dev/bg/ratings/): API за рейтинги на филми връща оценки от IMDb, Kinopoisk, Metacritic, Rotten Tomatoes и TMDB за заглавие с едно извикване, с null за неизвестен източник.
- [Бърз старт](https://amodb.dev/bg/quickstart/): Първата ви заявка към amodb: вземете ключ, поискайте детайли за филм с curl, JavaScript, Python, PHP или Go и заредете постера от img.amodb.dev. До 2 минути.

Обновено: 2026-10-18. Source: https://amodb.dev/bg/soundtracks/
