# 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 1. Test the plugin with a live Jellyfin instance 2. Verify content discovery and playback 3. Test expiration handling 4. Add unit tests 5. 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 URLs - `GET /video/{businessUnit}/latest` - Get latest videos - `GET /video/{businessUnit}/trending` - Get trending videos - `GET /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 URN - `urn:{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 ```bash cd Jellyfin.Plugin.SRFPlay dotnet build ``` ### Output The compiled plugin will be in `bin/Debug/net8.0/` ## Installation 1. Build the plugin (see above) 2. Copy the compiled DLL to your Jellyfin plugins directory 3. Restart Jellyfin 4. 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](PROXY_SETUP_GUIDE.md). ## Troubleshooting If you encounter issues with the plugin: - Check [DEBUG_GUIDE.md](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 1. **API Client**: Handles all HTTP requests to SRF Integration Layer 2. **Stream Resolver**: Extracts and selects optimal HLS streams 3. **Configuration**: User-configurable settings via Jellyfin dashboard 4. **Metadata Cache**: Thread-safe caching with configurable expiration 5. **Content Providers**: Jellyfin integration for series, episodes, images, and media 6. **Scheduled Tasks**: Automatic content refresh and expiration management 7. **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: 1. Build the plugin: `dotnet build` 2. Copy `bin/Debug/net8.0/Jellyfin.Plugin.SRFPlay.dll` to your Jellyfin plugins directory 3. Restart Jellyfin 4. Configure the plugin in Dashboard → Plugins → SRF Play 5. 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 - [SRF Play](https://www.srf.ch/play) - [Jellyfin Plugin Documentation](https://jellyfin.org/docs/general/server/plugins/) - [SRG SSR Integration Layer API](https://il.srgssr.ch/)