Dynamic EPG Generator for Sports Channels
Teamarr creates rich, dynamic Electronic Program Guide (EPG) data for your sports channels. It fetches real-time schedules from ESPN and generates XMLTV-format EPG files with intelligent descriptions that adapt based on game context—streaks, odds, matchups, and more.
- Team-Based EPG — Add your favorite teams and get 24/7 EPG coverage with pregame, live game, postgame, and idle programming
- Event-Based EPG — Automatically match streams from your M3U provider to ESPN events and create channels on-the-fly
- Smart Descriptions — Conditional templates that change based on win streaks, betting odds, home/away status, and more
- Dispatcharr Integration — Seamless channel lifecycle management with automatic channel creation and deletion
- Multi-Sport Support — NFL, NBA, NHL, MLB, MLS, college sports, Premier League, La Liga, and more
services:
teamarr:
image: ghcr.io/egyptiangio/teamarr:latest
container_name: teamarr
restart: unless-stopped
ports:
- 9195:9195
volumes:
- ./data:/app/data
environment:
- TZ=America/New_Yorkdocker-compose up -dOpen http://localhost:9195 in your browser.
| Tag | Description |
|---|---|
latest |
Stable release, recommended for most users |
dev |
Development branch with newest features, may have bugs |
Teamarr works best with Dispatcharr for automatic channel management. Here's how to connect them:
- In Dispatcharr, go to Settings → EPG Sources
- Click Add EPG Source
- Enter the Teamarr EPG URL:
(Use your Teamarr container name or IP address)
http://teamarr:9195/epg/teamarr.xml - Save and refresh the EPG
- In Teamarr, go to Settings
- Under Dispatcharr Integration, enter:
- URL:
http://dispatcharr:9191(your Dispatcharr address) - Username: Your Dispatcharr username
- Password: Your Dispatcharr password
- URL:
- Click Test Connection
- Select the Teamarr EPG you created in Step 1 from the dropdown
- Save settings
For event-based EPG (automatic channel creation), configure these in Dispatcharr:
| Setting | Recommended Value | Why |
|---|---|---|
| Stale Stream Retention | 0 |
Prevents old/dead streams from being mapped to new channels |
Note: You don't need to worry about EPG refresh intervals—Teamarr automatically triggers a Dispatcharr EPG refresh each time it generates.
Team-based EPG creates a dedicated channel for each team you follow. The channel shows relevant programming 24/7:
- Pregame — Builds anticipation before games
- Live Game — The actual event with real-time data
- Postgame — Recaps and results after games end
- Idle — Between games, showing next game info
- Go to Teams → Add Team
- Search by team name or paste an ESPN team URL
- Assign a Template (controls how descriptions are formatted)
- Save
This is where Teamarr shines. Instead of repetitive descriptions, you can create conditions that produce different text based on the game situation.
Every description has a priority score (1-100). Lower numbers = higher priority. Teamarr checks conditions from lowest to highest score and uses the first one that matches.
Default descriptions always have priority 100 and cannot be changed. You can add multiple defaults—Teamarr will randomly pick one when no conditions match.
| Type | Condition | Description Template | Priority |
|---|---|---|---|
| Conditional | Win streak ≥ 3 | {team_name} looks to extend their {win_streak}-game winning streak against {opponent}! |
10 |
| Conditional | Has odds | {team_name} vs {opponent} • {odds_spread} • O/U {odds_over_under} |
20 |
| Default | — | {team_name} plays {opponent} at {game_time} on {game_date} |
100 |
| Default | — | {away_team} travels to {venue_city} to face {home_team} |
100 |
-
Check priority 10: Is win streak ≥ 3?
- ✅ Yes → Use this description
- ❌ No → Continue...
-
Check priority 20: Are betting odds available?
- ✅ Yes → Use this description
- ❌ No → Continue...
-
Check priority 100: Multiple defaults exist
- Pick one at random for variety
The result: descriptions that feel fresh and contextual, not copy-paste repetitive.
- Edit your Template
- Go to the Conditions tab
- Click Add Condition
- Configure:
- Name: Label for your reference
- Condition Type: What to check (streak, odds, home/away, etc.)
- Value: Threshold (e.g., 3 for "streak ≥ 3")
- Priority: Lower = checked first (1-99)
- Description Template: Text with variables
| Condition | Description |
|---|---|
| Is home | Team is playing at home |
| Is away | Team is playing away |
| Win streak ≥ N | Team has won N+ games in a row |
| Loss streak ≥ N | Team has lost N+ games in a row |
| Home win streak ≥ N | Team has won N+ home games in a row |
| Away win streak ≥ N | Team has won N+ away games in a row |
| Has odds | Betting odds are available for this game |
| Is playoff | Game is a playoff game |
| Is preseason | Game is a preseason game |
| Is national broadcast | Game is on national TV |
| Is ranked opponent | Opponent is ranked (college) |
| Opponent contains | Opponent name contains specific text |
Event-based EPG automatically creates channels from your M3U provider streams. Perfect for providers with game-day channels like "NFL: Bears @ Lions".
- Teamarr scans your M3U channel groups
- Parses stream names to identify teams (e.g., "Bears @ Lions")
- Matches teams to ESPN events
- Creates channels in Dispatcharr with full EPG data
- Deletes channels when games end
- Go to Event EPG → Add Group
- Select your M3U Account and Channel Group
- Choose the Sport and League
- Configure channel settings:
- Starting Channel Number: Where to begin numbering
- Channel Group: Dispatcharr group to create channels in
- Assign an Event Template for descriptions
- Save and click Refresh to test matching
| Setting | Options | Description |
|---|---|---|
| Create Timing | Stream Available, Same Day, Day Before, 2 Days Before | When to create the channel |
| Delete Timing | Stream Removed, Same Day, Day After, 2 Days After | When to delete the channel |
Tip: "Same Day" for both is recommended—channels appear on game day and disappear at midnight.
| Setting | Default | Description |
|---|---|---|
| Days Ahead | 3 | How many days of schedule to include |
| Output Path | /app/data/teamarr.xml |
Where to save the EPG file |
| Auto Generate | Enabled | Automatically regenerate EPG on schedule |
| Frequency | Hourly | How often to regenerate (Hourly or Daily) |
| Schedule Time | :00 | For hourly: minute of hour (0-59). For daily: time (HH:MM) |
| Setting | Default | Description |
|---|---|---|
| Timezone | America/New_York | Timezone for all times (syncs from TZ env var) |
| Time Format | 12h | 12-hour or 24-hour time display |
| Show Timezone | Yes | Include timezone abbreviation (EST, PST) |
How long to block out for each sport's games:
| Sport | Default Duration |
|---|---|
| Basketball | 3.0 hours |
| Football | 3.5 hours |
| Hockey | 3.0 hours |
| Baseball | 3.5 hours |
| Soccer | 2.5 hours |
| Other | 4.0 hours |
Default: {team_name_pascal}.{league_id}
Available variables:
{team_name}— Full team name{team_name_pascal}— PascalCase team name{team_abbrev}— Team abbreviation{team_slug}— URL-friendly team name{league}— League code{league_id}— League identifier{sport}— Sport type
| Setting | Default | Description |
|---|---|---|
| Midnight Crossover | Idle | What to show if game crosses midnight: "Postgame" or "Idle" |
| Max Program Hours | 6.0 | Maximum length for a single filler program block |
| Include Final Events | No | Show completed games from today in event-based EPG |
Use these in your description templates:
| Variable | Example |
|---|---|
{team_name} |
Detroit Pistons |
{opponent} |
Los Angeles Lakers |
{home_team} |
Detroit Pistons |
{away_team} |
Los Angeles Lakers |
{game_time} |
7:00 PM EST |
{game_date} |
Dec 15 |
{game_day} |
Sunday |
| Variable | Example |
|---|---|
{venue} |
Little Caesars Arena |
{venue_city} |
Detroit |
{venue_state} |
MI |
{venue_full} |
Little Caesars Arena, Detroit, MI |
| Variable | Example |
|---|---|
{team_record} |
15-8 |
{opponent_record} |
12-11 |
{win_streak} |
4 |
{loss_streak} |
0 |
{home_record} |
8-2 |
{away_record} |
7-6 |
| Variable | Example |
|---|---|
{odds_spread} |
-3.5 |
{odds_over_under} |
221.5 |
{odds_moneyline} |
-150 |
Many variables support .next and .last suffixes:
{opponent.next}— Next game's opponent{game_date.last}— Last game's date{final_score.last}— Last game's final score
Database migrations run automatically when you update. Your teams, templates, and settings are preserved.
docker-compose pull
docker-compose up -d- Issues: GitHub Issues
- Discussions: GitHub Discussions
MIT License — see LICENSE for details.