# Coloane sonore

> GET /3/movie/{movie_id}/soundtracks și GET /3/tv/{tv_id}/soundtracks întorc albumul cu coloana sonoră a unui titlu într-o listă results. Fiecare album are o sursă, un nume, un artist, o dată de lansare, un link și o listă tracks cu disc, număr, titlu, artist și durată. Adaugă append_to_response=soundtracks ca să-l îmbini în detalii.

## Endpoint

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

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

Răspuns:

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

## Obține coloana sonoră a unui film

`GET /3/movie/{movie_id}/soundtracks` întoarce albumul cu coloana sonoră a unui film. Răspunsul conține `id`-ul filmului și un array `results`. Fiecare intrare este un album, cu detaliile lui și o listă `tracks`.

Exemplul încarcă The Dark Knight (ID 155) și afișează albumul și câte o linie pe piesă.

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

### Parametri

| Parametru  | Loc        | Obligatoriu          | Descriere                                                             |
| ---------- | ---------- | -------------------- | --------------------------------------------------------------------- |
| `movie_id` | cale       | da                   | ID numeric de film, de exemplu `155`.                                 |
| `api_key`  | interogare | una dintre cele două | Cheia ta. Folosește-o pe aceasta sau antetul `Authorization: Bearer`. |

### Câmpurile răspunsului

| Câmp                             | Tip          | Observații                                                               |
| -------------------------------- | ------------ | ------------------------------------------------------------------------ |
| `id`                             | număr întreg | ID-ul filmului. Lipsește când folosești `append_to_response`.            |
| `results`                        | array        | Albume. Gol când nu se cunoaște niciun album. Azi conține cel mult unul. |
| `results[].source`               | șir          | De unde vine albumul: `musicbrainz` sau `deezer`.                        |
| `results[].album`                | șir          | Titlul albumului.                                                        |
| `results[].artist`               | șir sau null | Artistul albumului, de exemplu `Hans Zimmer & James Newton Howard`.      |
| `results[].released`             | șir sau null | Data lansării ca `YYYY-MM-DD`.                                           |
| `results[].url`                  | șir sau null | Link către pagina albumului la sursă.                                    |
| `results[].track_count`          | număr întreg | Numărul de piese de pe album.                                            |
| `results[].tracks`               | array        | Piesele în ordinea albumului.                                            |
| `results[].tracks[].disc`        | număr întreg | Numărul discului, începând de la 1.                                      |
| `results[].tracks[].number`      | număr întreg | Numărul piesei de pe disc.                                               |
| `results[].tracks[].title`       | șir          | Titlul piesei.                                                           |
| `results[].tracks[].artist`      | șir          | Artistul piesei.                                                         |
| `results[].tracks[].duration_ms` | număr întreg | Durata în milisecunde.                                                   |

Citește după nume cheile pe care le folosești și sari peste celelalte chei.

### Exemplu de răspuns

```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 de piese este tăiată la 3 din 14. Un titlu fără album cunoscut, precum Fight Club (ID 550), răspunde cu o listă goală:

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

## Obține coloana sonoră a unui serial

`GET /3/tv/{tv_id}/soundtracks` întoarce aceeași structură pentru un serial. Transmite ID-ul serialului, de exemplu `1396`. Breaking Bad nu are niciun album cunoscut, deci array-ul lui `results` este gol.

| Metodă și cale                      | Întoarce                            | Parametri                           |
| ----------------------------------- | ----------------------------------- | ----------------------------------- |
| `GET /movie/{movie_id}/soundtracks` | `id` și `results`                   | `movie_id`                          |
| `GET /tv/{tv_id}/soundtracks`       | `id` și `results`                   | `tv_id`                             |
| `append_to_response=soundtracks`    | Același `results` sub `soundtracks` | Adăugat la detaliile de film sau TV |

Ca să primești albumul în timp ce încarci o pagină de film, atașează-l la detalii:

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

Blocul atașat stă sub cheia `soundtracks` a înregistrării. Conține `results` și nu are un `id` propriu. Se numără ca o singură cerere.

## Construiește o listă „muzica din film”

Sortează după `disc` și `number`, arată titlul și artistul și ascunde blocul când `results` este gol. Funcțiile de mai jos întorc linii de text simplu pe care le poți pune într-un element de listă.

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

Câteva idei de interfață care nu cer date suplimentare:

| Idee                  | Cum                                                                                           |
| --------------------- | --------------------------------------------------------------------------------------------- |
| Listă numerotată      | Folosește `number` ca număr de listă și grupează după `disc` când există mai multe discuri.   |
| Link la album         | Leagă numele albumului de `url` când nu este null.                                            |
| Durată totală         | Adună `duration_ms` peste piese.                                                              |
| Asociere cu atmosfera | Arată lista lângă [indicatorii de atmosferă](https://amodb.dev/ro/moods/) ai aceluiași titlu. |

## Erori

Fiecare eșec întoarce `success` ca false cu un `status_code` numeric, ca la TMDB.

| HTTP | status_code | Când                                                                         |
| ---- | ----------- | ---------------------------------------------------------------------------- |
| 401  | 7           | Cheia lipsește sau este greșită.                                             |
| 402  | 36          | Perioada planului s-a încheiat.                                              |
| 429  | 25          | Ai depășit cererile pe minut. Așteaptă numărul de secunde din `Retry-After`. |

Endpoint-ul de coloane sonore nu răspunde 404 pentru un ID necunoscut. Răspunde 200 cu un array `results` gol. Atașat la detalii, un ID necunoscut este un 404 de la apelul de detalii. Vezi [erori](https://amodb.dev/ro/errors/) pentru fiecare cod și [limite de cereri](https://amodb.dev/ro/rate-limits/) pentru antete.

## Note practice

- Ca alte date de detalii, coloanele sonore sunt ținute în cache la margine 6 ore. Un cache de client mai scurt nu aduce nimic.
- Folosește `append_to_response=soundtracks` pe o pagină de detalii pe care o încarci deja. Economisește o cerere din cele 20, 40 sau 120 pe minut.
- Nu cere ca un album să existe. Ascunde blocul de muzică când `results` este gol.
- Unele albume vin de la MusicBrainz, altele de la Deezer. Filmul 27205 (Inception) are un album Deezer. Structura este aceeași, deci verifică `source` doar dacă îl afișezi.
- Numele pieselor și ale artiștilor sunt șiruri simple și pot conține orice caracter. Stochează-le ca UTF-8 și escapează-le când le pui în HTML.
- Pentru trailerul aceluiași titlu, vezi [videoclipuri și trailere](https://amodb.dev/ro/videos-trailers/).

## Întrebări și răspunsuri

### Ce conține o intrare de coloană sonoră?

Un obiect album. Are sursa, numele albumului, artistul, data lansării, un link și track_count. Array-ul lui tracks listează fiecare piesă cu disc, number, title, artist și duration_ms. Răspunsul poartă și ID-ul titlului.

### Primesc fișiere audio sau linkuri de streaming?

Fără audio. Câmpul url duce la pagina albumului de pe MusicBrainz sau Deezer și poate fi null. Ca utilizatorii să poată asculta, caută albumul în serviciul de muzică pe care îl folosești deja și deschide-l din propria interfață.

### Există o coloană sonoră pentru fiecare titlu?

Nu. Multe titluri, printre ele Fight Club, nu au niciun album cunoscut, iar răspunsul este un array results gol. Azi un titlu are cel mult un album. Proiectează blocul de muzică să se ascundă când nu are ce arăta.

### Pot obține coloane sonore pentru un serial?

Da. Apelează GET /3/tv/{tv_id}/soundtracks cu ID-ul serialului. Răspunsul are aceeași structură ca endpoint-ul pentru filme, deci un singur parser le acoperă pe amândouă.

## Pagini conexe

- [API detalii film](https://amodb.dev/ro/movies/): API detalii film cu aceleași căi și același JSON ca TMDB v3. Preia un film după ID, adaugă credite, evaluări și atmosferă cu append_to_response, în 14 limbi.
- [API seriale TV](https://amodb.dev/ro/tv-series/): API seriale TV cu căile și JSON-ul TMDB v3. Preia un serial după ID cu sezoane, rețele și următorul episod, plus clasificări de conținut și furnizori.
- [Indicatori de atmosferă](https://amodb.dev/ro/moods/): API atmosferă filme cu indicatori de la 0 la 10 pe titlu. Citește atmosferele unui film, îmbină-le cu append_to_response=moods, construiește insigne sau filtre.
- [API videoclipuri și trailere](https://amodb.dev/ro/videos-trailers/): API videoclipuri filme cu căi TMDB v3: listează trailere, teasere, clipuri și featurette-uri ale unui film sau serial, apoi filtrează după tip și limbă în cod.
- [Evaluări pentru filme și TV](https://amodb.dev/ro/ratings/): API evaluări filme ce întoarce scorurile IMDb, Kinopoisk, Metacritic, Rotten Tomatoes și TMDB pentru un titlu într-un apel, cu null pentru sursele necunoscute.
- [Ghid rapid](https://amodb.dev/ro/quickstart/): Fă primul apel amodb: ia o cheie, cere detaliile unui film în curl, JavaScript, Python, PHP sau Go, apoi încarcă posterul de pe img.amodb.dev. Sub 2 minute.

Actualizat: 2026-10-18. Source: https://amodb.dev/ro/soundtracks/
