Jellyfin SRF Play Plugin
A Jellyfin plugin for accessing SRF Play (Swiss Radio and Television) video-on-demand content.
Features
- Access to SRF Play VOD content (video-on-demand only, no DRM-protected content)
- Support for all Swiss broadcasting units (SRF, RTS, RSI, RTR, SWI)
- Automatic content expiration handling
- Latest and trending content discovery
- Quality selection (Auto, SD, HD)
- HLS streaming support
- Proxy support for routing traffic through alternate gateways
Project Status
✅ Completed Components
Phase 1: Project Setup
- ✅ Renamed from Template to SRFPlay
- ✅ Updated all namespaces and identifiers
- ✅ Configured plugin metadata (ID, name)
Phase 2: Core API Infrastructure
- ✅ API Models (MediaComposition, Chapter, Resource, Show, Episode)
- ✅ SRF API Client with HTTP client wrapper
- ✅ JSON deserialization support
- ✅ Error handling and logging
Phase 3: Configuration
- ✅ Business unit selection (SRF/RTS/RSI/RTR/SWI)
- ✅ Quality preferences (Auto/SD/HD)
- ✅ Content refresh intervals
- ✅ Expiration check settings
- ✅ Cache duration configuration
- ✅ HTML configuration page
Phase 4: Services
- ✅ Stream URL Resolver
- HLS stream selection
- Quality-based filtering
- DRM content filtering
- Content expiration checking
- ✅ Metadata Cache Service
- Efficient caching with configurable duration
- Thread-safe with ReaderWriterLockSlim
- IDisposable implementation
- ✅ Content Expiration Service
- Automatic expiration checking
- Library cleanup of expired content
- Statistics and monitoring
- ✅ Content Refresh Service
- Latest and trending content discovery
- Automatic cache population
- Recommendations system
Phase 5: Content Providers
- ✅ Series Provider (for show metadata)
- ✅ Episode Provider (for episode metadata)
- ✅ Image Provider (for thumbnails and artwork)
- ✅ Media Provider (for playback URLs and HLS streams)
Phase 6: Scheduled Tasks
- ✅ Content Refresh Task
- Periodic discovery of new content
- Configurable refresh intervals
- ✅ Expiration Check Task
- Automatic cleanup of expired content
- Configurable check intervals
Phase 7: Dependency Injection & Integration
- ✅ Service registration (ServiceRegistrator)
- ✅ Jellyfin provider interfaces implementation
- ✅ Plugin initialization and configuration
✅ Build Status
Successfully compiling! All code analysis warnings resolved.
🧪 Testing Status
- Unit tests
- Integration testing with Jellyfin instance
- End-to-end playback testing
📝 Next Steps
- Test the plugin with a live Jellyfin instance
- Verify content discovery and playback
- Test expiration handling
- Add unit tests
- Performance optimization if needed
API Information
Base URL: https://il.srgssr.ch/integrationlayer/2.0/
Key Endpoints
GET /mediaComposition/byUrn/{urn}.json- Get video metadata and playable URLsGET /video/{businessUnit}/latest- Get latest videosGET /video/{businessUnit}/trending- Get trending videosGET /showList/{businessUnit}- Get all shows (to be implemented)GET /episodeList/{businessUnit}/{showId}- Get episodes for a show (to be implemented)
URN Format
urn:{bu}:video:{id}- Video URNurn:{bu}:video:livestream_{channel}- Livestream URN (not supported due to Widevine DRM)
Example: urn:srf:video:livestream_SRF1
Building the Plugin
Prerequisites
- .NET 8.0 SDK
- Jellyfin 10.9.11 or later
Build Steps
cd Jellyfin.Plugin.SRFPlay
dotnet build
Output
The compiled plugin will be in bin/Debug/net8.0/
Installation
- Build the plugin (see above)
- Copy the compiled DLL to your Jellyfin plugins directory
- Restart Jellyfin
- Configure the plugin in Jellyfin Dashboard → Plugins → SRF Play
Configuration
- Business Unit: Select the Swiss broadcasting unit (default: SRF)
- Quality Preference: Choose video quality (Auto/SD/HD)
- Content Refresh Interval: How often to check for new content (1-168 hours)
- Expiration Check Interval: How often to check for expired content (1-168 hours)
- Cache Duration: How long to cache metadata (5-1440 minutes)
- Enable Latest Content: Automatically discover latest videos
- Enable Trending Content: Automatically discover trending videos
- Proxy Settings: Configure proxy server for routing SRF API traffic (optional)
- Use Proxy: Enable/disable proxy usage
- Proxy Address: Proxy server URL (e.g., http://proxy.example.com:8080)
- Proxy Username: Optional authentication username
- Proxy Password: Optional authentication password
For detailed proxy setup instructions, see PROXY_SETUP_GUIDE.md.
Troubleshooting
If you encounter issues with the plugin:
- Check DEBUG_GUIDE.md for detailed logging information
- Enable debug logging in Jellyfin to see detailed request/response information
- Common issues include DRM-protected content and geo-restrictions
Technical Architecture
Directory Structure
Jellyfin.Plugin.SRFPlay/
├── Api/
│ ├── Models/ # API response models
│ │ ├── MediaComposition.cs
│ │ ├── Chapter.cs
│ │ ├── Resource.cs
│ │ ├── Show.cs
│ │ └── Episode.cs
│ └── SRFApiClient.cs # HTTP client for SRF API
├── Configuration/
│ ├── PluginConfiguration.cs
│ └── configPage.html
├── Services/
│ ├── StreamUrlResolver.cs # HLS stream resolution
│ ├── MetadataCache.cs # Caching layer
│ ├── ContentExpirationService.cs # Expiration management
│ └── ContentRefreshService.cs # Content discovery
├── Providers/
│ ├── SRFSeriesProvider.cs # Series metadata
│ ├── SRFEpisodeProvider.cs # Episode metadata
│ ├── SRFImageProvider.cs # Image fetching
│ └── SRFMediaProvider.cs # Playback URLs
├── ScheduledTasks/
│ ├── ContentRefreshTask.cs # Periodic content refresh
│ └── ExpirationCheckTask.cs # Periodic expiration check
├── ServiceRegistrator.cs # DI registration
└── Plugin.cs # Main plugin entry point
Key Components
- API Client: Handles all HTTP requests to SRF Integration Layer
- Stream Resolver: Extracts and selects optimal HLS streams
- Configuration: User-configurable settings via Jellyfin dashboard
- Metadata Cache: Thread-safe caching with configurable expiration
- Content Providers: Jellyfin integration for series, episodes, images, and media
- Scheduled Tasks: Automatic content refresh and expiration management
- Service Layer: Content discovery, expiration handling, and stream resolution
Important Notes
Content Limitations
- No DRM content: Only non-DRM protected content is accessible (no Widevine)
- No live TV channels: Only VOD content and live streams without DRM
- Content expiration: SRF content has validity periods, plugin tracks and removes expired content
- No subtitles: Subtitle support not currently implemented
Extensibility
The plugin is designed to support all Swiss broadcasting units:
- SRF (Schweizer Radio und Fernsehen - German)
- RTS (Radio Télévision Suisse - French)
- RSI (Radiotelevisione svizzera - Italian)
- RTR (Radiotelevisiun Svizra Rumantscha - Romansh)
- SWI (Swiss World International)
Currently focused on SRF but easily extensible.
Development
Current Status
All core functionality is implemented and compiling successfully! The plugin includes:
- Complete API integration with SRF Play
- Metadata providers for series and episodes
- Image fetching and caching
- HLS stream playback
- Automatic content expiration handling
- Scheduled tasks for content refresh
Testing
To test the plugin:
- Build the plugin:
dotnet build - Copy
bin/Debug/net8.0/Jellyfin.Plugin.SRFPlay.dllto your Jellyfin plugins directory - Restart Jellyfin
- Configure the plugin in Dashboard → Plugins → SRF Play
- Add a library with the SRF Play content provider
Known Limitations
- This is a first version that has not been tested with a live Jellyfin instance yet
- Some edge cases may need handling
- Performance optimization may be needed for large content catalogs
Contributing
This plugin is in active development. Contributions welcome!
License
See LICENSE file for details.
References
Languages
C#
93.4%
HTML
5.5%
Shell
1.1%