# f1radio

F1 team radio clips with full race context. Built on [OpenF1](https://openf1.org).

Load any session from 2023 onwards — every radio clip comes enriched with position, tyres, gaps, flags, overtakes, and pit stops. Everything is cached locally so you only hit the API once.

## Installation

```bash
pip install f1radio
```

**Optional extras** for audio playback and transcription:

```bash
pip install 'f1radio[playback]'       # audio playback
pip install 'f1radio[transcribe]'     # whisper transcription (coming soon)
pip install 'f1radio[all]'            # everything
```

> **Note:** If you're using zsh (default on macOS), you need quotes around the brackets — `'f1radio[playback]'` instead of `f1radio[playback]`.

**Requirements:** Python 3.9+. No API keys needed.

## Quick Start

```python
import f1radio

# load a session — race names are fuzzy matched
session = f1radio.load(2024, "Monza", "R")

# browse clips
for clip in session.clips:
    print(f"{clip.driver} | Lap {clip.lap} | P{clip.context.position} | {clip.context.compound}")

# filter by driver
for clip in session.clips.filter(driver="VER"):
    print(clip)
    clip.play()  # requires playback extra

# export
session.export_json("monza_radio.json")
session.export_csv("monza_radio.csv")
```

Race name matching is flexible — `"Monza"`, `"Italian"`, `"Italy"`, `"Italian Grand Prix"` all resolve to the same session.

## What You Get

Every clip is enriched with what was happening at that exact moment:

| Field | Example | Description |
| ----- | ------- | ----------- |
| `position` | `1` | Driver's position |
| `gap_to_leader` | `"+1.432"` | Gap to P1 |
| `compound` | `"SOFT"` | Current tyre |
| `tyre_age` | `12` | Laps on current set |
| `lap_number` | `14` | Current lap |
| `events` | `["SAFETY CAR"]` | Flags/events within ±30s |
| `overtakes` | `["VER → NOR for P2"]` | Nearby overtakes |
| `pit_stops` | `["HAM pitted"]` | Nearby pit activity |

```python
clip = session.clips[0]
ctx = clip.context

print(ctx.position)       # 1
print(ctx.compound)       # "SOFT"
print(ctx.tyre_age)       # 12
print(ctx.events)         # ["YELLOW FLAG - Turn 4"]
```

## CLI

```bash
f1radio download 2024 Monza R     # download and cache a session
f1radio info 2024 Monza R         # show session metadata
f1radio cache list                # see what's cached
f1radio cache clear               # clear everything
```

## Caching

Sessions are cached after first load — subsequent calls are instant with zero API requests. Cache is cleaned up automatically after 30 days of inactivity.

```python
f1radio.cache_info()       # see cached sessions and sizes
f1radio.clear_cache()      # wipe everything
```

## API Responsibility

Built to be a respectful consumer of the OpenF1 API:

- **Rate limited** — 2.5 req/sec, 28 req/min (under the API's limit of 3/s)
- **Circuit breaker** — stops after repeated 429s to avoid bans
- **Conditional requests** — ETag headers to skip unchanged data
- **Transparent** — `f1radio.stats` shows exactly how many API calls were made

## Supported Sessions

| Code | Session |
| ---- | ------- |
| R | Race |
| Q | Qualifying |
| S | Sprint |
| SQ | Sprint Qualifying |
| FP1 | Free Practice 1 |
| FP2 | Free Practice 2 |
| FP3 | Free Practice 3 |

Data available from the **2023 season** onwards (OpenF1 limitation).

## Data Source

All data comes from [OpenF1](https://openf1.org) under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/). Audio files are hosted by Formula One Management.

**This package is for personal and non-commercial use.** See the [NOTICE](https://github.com/4f4d/f1radio/blob/main/NOTICE) file for details.

## License

Apache 2.0 — see [LICENSE](https://github.com/4f4d/f1radio/blob/main/LICENSE).

## Contributing

See [CONTRIBUTING.md](https://github.com/4f4d/f1radio/blob/main/CONTRIBUTING.md) for development setup and guidelines.
