# 스트리밍 · 재생

번개라디오는 **방송사가 제공하는 스트림 URL을 그대로 사용**합니다. 우리 서버는 오디오 트래픽을 중계(proxy)하지 않으며, 앱이 방송사 서버와 직접 연결해 재생합니다.

## 스트림 접근 방식 (access_model)

| 값 | 의미 | 처리 |
|---|---|---|
| `open_static` | 무인증 공개 HLS | URL이 그대로 제공됨. 바로 재생. |
| `token_signed` | 재생 시 토큰 발급 필요(KBS·MBC·SBS) | `/stations/{id}/stream` 호출 → 서버가 방송사 API로 단명 URL 발급 |
| `geo_restricted` | 한국 IP 전용 등 | URL 제공되나 지역 제한 가능 |

## GET /stations/{id}/stream

재생용 스트림 URL을 반환합니다. `token_signed` 는 이 시점에 방송사에서 토큰을 발급받아 반환합니다.

**쿼리**: `stream_id`(선택) — 특정 스트림 지정. 생략 시 우선순위 1순위 스트림.

```bash
curl https://tune.tideflo.work/api/v1/stations/5/stream
```

```json
{
  "success": true,
  "data": {
    "station_id": 5,
    "stream_id": 5,
    "access_model": "token_signed",
    "protocol": "hls",
    "format": "aac",
    "media_type": "audio",
    "requires_app_headers": false,
    "geo_restricted": false,
    "resolved": true,
    "url": "https://2fm-ad.gscdn.kbs.co.kr/2fm_ad_192_1.m3u8?Policy=...&Signature=...&Key-Pair-Id=...",
    "note": "토큰 URL은 만료됩니다. 재생 실패 시 이 엔드포인트를 다시 호출하세요."
  }
}
```

## 앱 재생 가이드

1. **HLS(.m3u8) 플레이어** 사용 (Android: ExoPlayer, iOS: AVPlayer).
2. `access_model` 확인:
   - `open_static` → 상세 응답의 `streams[].url` 을 바로 재생.
   - `token_signed` → `/stations/{id}/stream` 호출 후 `data.url` 재생.
3. **`requires_app_headers: true`** (MBC 등) 인 경우, 플레이어 HTTP 요청에 아래 헤더를 넣어야 재생됩니다:
   ```
   User-Agent: Mozilla/5.0 (Linux; Android 12) ...
   Referer: https://www.imbc.com/
   ```
4. **토큰 만료 처리**: `token_signed` URL은 만료됩니다(KBS CloudFront, SBS JWT ~12h, MBC Wowza). 재생 중 403/오류가 나면 `/stations/{id}/stream` 을 **다시 호출**해 새 URL을 받으세요. 서버는 발급 결과를 30초만 캐시하므로 재호출이 안전합니다.
5. `media_type: video` 는 "보이는 라디오"(영상 포함) 입니다.

## 주의 / 라이선스

- 토큰형(KBS/MBC/SBS) URL을 **캐싱·재호스팅·자체 광고 플레이어에 임베드하지 마세요**. 방송사 정책·저작권(공중송신권 방조) 리스크가 있습니다.
- 재생 연결은 항상 **앱 ↔ 방송사 직접**. 서버는 URL만 전달합니다.
- 상세 배경은 저장소 `docs/research/korean-radio-catalog.md` 참고.
