Duncan Tourolle ac6a3842dd
Some checks failed
🏗️ Build Plugin / call (push) Failing after 0s
📝 Create/Update Release Draft & Release Bump PR / call (push) Failing after 0s
🧪 Test Plugin / call (push) Failing after 0s
🔬 Run CodeQL / call (push) Failing after 0s
first commit
2025-11-12 22:05:36 +01:00

8.6 KiB

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

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.

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

  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