EPG Cache Overview
M3U Editor includes comprehensive EPG caching for dramatically improved performance with large EPG files.
Overview
The EPG optimization system provides:
- ✅ Instant data retrieval instead of slow XML parsing
- ✅ Date-chunked storage for efficient access
- ✅ Memory-efficient pagination support
- ✅ Automatic cache validation based on file modification times
How It Works
EPG Cache Service
The EpgCacheService provides high-performance caching:
Features:
- JSON-based cache files for fast access
- Programmes organized by date for efficient queries
- Automatic validation against source EPG changes
- Support for large EPG files (100,000+ programmes)
Automatic Cache Generation
Caches are automatically generated:
- After EPG import completes
- When EPG is refreshed
- On EPG file modification detection
Manual generation:
php artisan epg:cache-generate {uuid}
API Endpoints
Get EPG Data for Specific EPG
Endpoint: GET /api/epg/{uuid}/data
Parameters:
page- Page number (default: 1)per_page- Items per page (default: 50)start_date- Filter start date (YYYY-MM-DD)end_date- Filter end date (YYYY-MM-DD)
Example:
fetch('/api/epg/9f21e8bd-921c-452f-bec7-14fc0144c51b/data?page=1&per_page=50&start_date=2025-07-23')
.then(response => response.json())
.then(data => {
console.log('Channels:', data.channels);
console.log('Programmes:', data.programmes);
console.log('Pagination:', data.pagination);
});
Get EPG Data for Playlist Channels
Endpoint: GET /api/epg/playlist/{uuid}/data
Returns EPG data for all enabled channels in a playlist.
Parameters:
- Same as above
Example:
fetch('/api/epg/playlist/playlist-uuid-here/data?page=1&per_page=50&start_date=2025-07-23')
.then(response => response.json())
.then(data => {
console.log('Playlist:', data.playlist);
console.log('Channels:', data.channels);
console.log('Programmes:', data.programmes);
console.log('Cache Info:', data.cache_info);
});
Response Format
{
"epg": {
"id": 1,
"name": "EPG Name",
"uuid": "uuid-here"
},
"date_range": {
"start": "2025-07-23",
"end": "2025-07-23"
},
"pagination": {
"current_page": 1,
"per_page": 50,
"total_channels": 23588,
"returned_channels": 50,
"has_more": true
},
"channels": [
{
"id": "channel-id",
"display_name": "Channel Name",
"icon": "https://example.com/logo.png"
}
],
"programmes": {
"channel-id": [
{
"start": "20250723120000 +0000",
"stop": "20250723130000 +0000",
"title": "Programme Title",
"desc": "Programme description",
"category": "Entertainment"
}
]
},
"cache_info": {
"cached": true,
"source": "cache"
}
}
Performance Benefits
Before Optimization
Large EPG files (100,000+ programmes):
- Initial load: 30+ seconds
- XML parsing on every request
- High memory usage
- Timeouts on very large files
After Optimization
With caching:
- Initial load: < 1 second
- No XML parsing needed
- Minimal memory usage
- Handles any EPG size
Cache Management
Cache Location
Caches are stored in:
storage/app/epg-cache/{uuid}/
├── channels.json
└── programmes/
├── 2025-07-23.json
├── 2025-07-24.json
└── ...
Cache Validation
Caches automatically invalidate when:
- Source EPG file is modified
- EPG is re-imported
- Manual cache clear requested
Manual Cache Management
Generate cache:
php artisan epg:cache-generate {uuid}
Clear cache:
php artisan epg:cache-clear {uuid}
Clear all caches:
php artisan epg:cache-clear --all
Integration
EPG Generate Controller
The EPG generation controller automatically uses cached data:
// Automatically uses cache when available
$xml = app(EpgGenerateController::class)->generate($playlist);
Benefits:
- Dramatically faster EPG XML generation
- Reduced server load
- Better user experience
API Controllers
Both EPG API endpoints leverage the cache service:
EpgApiController::getData()- Single EPG dataEpgApiController::getDataForPlaylist()- Playlist EPG data
Fallback behavior: If cache is unavailable, falls back to XML parsing automatically.
Pagination Support
Efficient pagination for large EPG files:
Example pagination:
// Load first 50 channels
let page = 1;
const perPage = 50;
async function loadEPG() {
const response = await fetch(
`/api/epg/playlist/${playlistUuid}/data?page=${page}&per_page=${perPage}&start_date=2025-07-23`
);
const data = await response.json();
// Process channels and programmes
displayEPG(data.channels, data.programmes);
// Check if more pages available
if (data.pagination.has_more) {
page++;
// Load more as needed
}
}
Troubleshooting
Cache Not Generating
Check:
- ✅ EPG import completed successfully
- ✅ Storage directory is writable
- ✅ Sufficient disk space
Solution:
# Manually generate cache
php artisan epg:cache-generate {uuid}
# Check logs for errors
tail -f storage/logs/laravel.log
Slow EPG Loading
If EPG is still slow:
-
Verify cache exists:
ls storage/app/epg-cache/{uuid}/ -
Check cache is being used:
- Look for
"cached": truein API response
- Look for
-
Regenerate cache:
php artisan epg:cache-clear {uuid}
php artisan epg:cache-generate {uuid}
Cache Out of Date
If EPG data seems old:
- Cache automatically updates on EPG refresh
- Manually refresh EPG from the UI
- Or force regenerate:
php artisan epg:cache-generate {uuid} --force
Best Practices
For Large EPG Files
✅ Recommended:
- Enable automatic caching (default)
- Use pagination in API calls
- Limit date ranges when possible
- Filter to only needed channels
For API Integration
✅ Recommended:
- Use
per_pageparameter to limit results - Implement progressive loading
- Cache API responses client-side
- Use date ranges to reduce data
For Playlist Output
✅ Recommended:
- Cache handles generation automatically
- Use time-limited outputs (7-14 days)
- Filter to only mapped channels
- Regenerate periodically
Next Steps
- EPG Setup - Initial EPG configuration
- Auto-Merge Channels - Automatic channel management
- M3U Proxy Integration - External proxy setup