260 lines
10 KiB
Markdown
260 lines
10 KiB
Markdown
# JellyLMS
|
|
|
|
A Jellyfin plugin that bridges audio playback to Logitech Media Server (LMS) for multi-room synchronized playback.
|
|
|
|
## Quick Install
|
|
|
|
Add the following repository URL to your Jellyfin server to install JellyLMS directly from the plugin catalog:
|
|
|
|
```
|
|
https://gitea.tourolle.paris/dtourolle/jellyLMS/raw/branch/master/manifest.json
|
|
```
|
|
|
|
**Steps:**
|
|
1. Go to **Dashboard** → **Plugins** → **Repositories**
|
|
2. Click **Add** and paste the URL above
|
|
3. Go to **Catalog** and find "JellyLMS"
|
|
4. Click **Install** and restart Jellyfin
|
|
|
|
## Overview
|
|
|
|
JellyLMS enables Jellyfin to stream audio to LMS, which acts as a multi-room speaker system. The architecture is:
|
|
|
|
- **Jellyfin** owns the library, queue, and playback intent
|
|
- **LMS** owns synchronized audio delivery to players (Squeezebox, piCorePlayer, etc.)
|
|
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
│ Jellyfin │ │ JellyLMS │ │ LMS │
|
|
│ │ │ Plugin │ │ │
|
|
│ ┌───────────┐ │ │ │ │ ┌───────────┐ │
|
|
│ │ Library │──┼────────►│ LmsApiClient │────────►│ │ Players │ │
|
|
│ │ (Audio) │ │ │ │ │ │ (Zones) │ │
|
|
│ └───────────┘ │ │ ┌───────────┐ │ │ └───────────┘ │
|
|
│ │ │ │ Session │ │ │ │
|
|
│ ┌───────────┐ │ │ │ Manager │ │ │ ┌───────────┐ │
|
|
│ │ Queue │──┼────────►│ └───────────┘ │────────►│ │ Sync │ │
|
|
│ │ │ │ │ │ │ │ Groups │ │
|
|
│ └───────────┘ │ │ ┌───────────┐ │ │ └───────────┘ │
|
|
│ │ │ │ REST API │ │ │ │
|
|
│ ┌───────────┐ │ │ │Controller │ │ │ │
|
|
│ │ Playback │──┼────────►│ └───────────┘ │ │ │
|
|
│ │ Controls │ │ │ │ │ │
|
|
│ └───────────┘ │ └─────────────────┘ └─────────────────┘
|
|
└─────────────────┘
|
|
```
|
|
|
|
## Features
|
|
|
|
- **Player Discovery**: Automatically discovers all LMS players/zones
|
|
- **Multi-Room Sync**: Create and manage sync groups for synchronized playback across multiple rooms
|
|
- **Playback Control**: Play, pause, stop, seek, and volume control forwarded to LMS
|
|
- **Stream Bridging**: Generates audio stream URLs from Jellyfin for LMS to consume
|
|
|
|
## Screenshots
|
|
|
|
### Cast to LMS Players
|
|
Select any LMS player directly from Jellyfin's "Play On" menu:
|
|
|
|

|
|
|
|
### Plugin Configuration
|
|
Configure LMS and Jellyfin server connections:
|
|
|
|

|
|
|
|
### Player Discovery
|
|
View discovered LMS players with their status and volume levels:
|
|
|
|

|
|
|
|
### Sync Group Management
|
|
Create and manage synchronized playback groups for multi-room audio:
|
|
|
|

|
|
|
|
## Requirements
|
|
|
|
- Jellyfin Server 10.10.0 or later
|
|
- .NET 8.0 Runtime
|
|
- Logitech Media Server (LMS) with JSON-RPC API enabled (default on port 9000)
|
|
|
|
## Installation
|
|
|
|
### Manual Installation
|
|
|
|
1. Download the latest release or build from source
|
|
2. Copy `Jellyfin.Plugin.JellyLMS.dll` to your Jellyfin plugins directory:
|
|
- **Linux**: `~/.local/share/jellyfin/plugins/JellyLMS/`
|
|
- **Windows**: `%APPDATA%\jellyfin\plugins\JellyLMS\`
|
|
- **Docker**: `/config/plugins/JellyLMS/`
|
|
3. Restart Jellyfin
|
|
|
|
### Building from Source
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone https://gitea.tourolle.paris/dtourolle/jellyLMS.git
|
|
cd jellyLMS
|
|
|
|
# Build
|
|
dotnet build Jellyfin.Plugin.JellyLMS.sln -c Release
|
|
|
|
# The DLL will be in:
|
|
# Jellyfin.Plugin.JellyLMS/bin/Release/net8.0/
|
|
```
|
|
|
|
## Configuration
|
|
|
|
1. Navigate to Jellyfin Dashboard → Plugins → JellyLMS
|
|
2. Configure the following settings:
|
|
|
|
| Setting | Description | Default |
|
|
|---------|-------------|---------|
|
|
| LMS Server URL | Full URL to your LMS server | `http://localhost:9000` |
|
|
| Jellyfin Server URL | URL where LMS can reach Jellyfin | `http://localhost:8096` |
|
|
| Connection Timeout | Timeout for LMS API calls (seconds) | `10` |
|
|
| Enable Auto Sync | Automatically sync players when creating groups | `true` |
|
|
| Default Player | MAC address of the default player | (none) |
|
|
|
|
3. Click "Test Connection" to verify connectivity to LMS
|
|
4. Use "Discover Players" to see available LMS players
|
|
|
|
## API Endpoints
|
|
|
|
The plugin exposes REST API endpoints under `/JellyLms/`:
|
|
|
|
### Players
|
|
|
|
- `GET /JellyLms/Players` - List all LMS players
|
|
- `GET /JellyLms/Players/{mac}` - Get specific player details
|
|
- `POST /JellyLms/Players/Refresh` - Refresh player list from LMS
|
|
|
|
### Sync Groups
|
|
|
|
- `GET /JellyLms/SyncGroups` - List all sync groups
|
|
- `POST /JellyLms/SyncGroups` - Create a new sync group
|
|
- `DELETE /JellyLms/SyncGroups/{masterMac}` - Dissolve a sync group
|
|
- `DELETE /JellyLms/SyncGroups/{masterMac}/Players/{slaveMac}` - Remove player from group
|
|
|
|
### Sessions
|
|
|
|
- `GET /JellyLms/Sessions` - List active playback sessions
|
|
- `POST /JellyLms/Sessions` - Start a new playback session
|
|
- `POST /JellyLms/Sessions/{id}/Pause` - Pause playback
|
|
- `POST /JellyLms/Sessions/{id}/Resume` - Resume playback
|
|
- `POST /JellyLms/Sessions/{id}/Stop` - Stop playback
|
|
- `POST /JellyLms/Sessions/{id}/Seek` - Seek to position
|
|
- `POST /JellyLms/Sessions/{id}/Volume` - Set volume
|
|
|
|
### Status
|
|
|
|
- `GET /JellyLms/Status` - Get LMS connection status
|
|
- `POST /JellyLms/TestConnection` - Test LMS connectivity
|
|
|
|
## LMS Setup
|
|
|
|
Ensure your LMS server has the JSON-RPC API available. This is enabled by default and accessible at:
|
|
|
|
```
|
|
http://<lms-server>:9000/jsonrpc.js
|
|
```
|
|
|
|
The plugin communicates with LMS using the `slim.request` JSON-RPC method.
|
|
|
|
## Troubleshooting
|
|
|
|
### Cannot connect to LMS
|
|
|
|
1. Verify LMS is running and accessible at the configured URL
|
|
2. Check that the JSON-RPC endpoint responds: `curl http://localhost:9000/jsonrpc.js`
|
|
3. Ensure no firewall is blocking connections between Jellyfin and LMS
|
|
|
|
### Players not appearing
|
|
|
|
1. Ensure players are powered on and connected to LMS
|
|
2. Click "Discover Players" to refresh the player list
|
|
3. Check LMS web interface to verify players are visible there
|
|
|
|
### Audio not playing
|
|
|
|
1. Verify Jellyfin server URL is accessible from LMS server
|
|
2. Check that audio files are in a format supported by your LMS players
|
|
3. Ensure players are powered on (plugin can auto-power-on if configured)
|
|
|
|
## Known Limitations
|
|
|
|
### Seeking with HTTP Streaming
|
|
|
|
When using HTTP streaming (the default), LMS cannot seek within audio streams. To work around this, when you seek or cast from a specific position, JellyLMS restarts playback with a new transcoded stream that begins at the requested position. This means:
|
|
|
|
- **Seeking triggers a brief audio restart** rather than a smooth jump
|
|
- **Starting playback mid-track** uses transcoding (MP3 320kbps) instead of direct streaming
|
|
- **Playback from the beginning** uses direct/static streaming for best quality
|
|
|
|
This is a fundamental limitation of how LMS handles HTTP streams.
|
|
|
|
### Solution: Direct File Access
|
|
|
|
If your Jellyfin and LMS servers can both access the same storage (e.g., a NAS), you can enable **Direct File Access** mode in the plugin settings. This allows LMS to read files directly from disk, enabling:
|
|
|
|
- **Native smooth seeking** - no audio restart when scrubbing
|
|
- **Full quality playback** - no transcoding needed
|
|
- **Better performance** - no HTTP overhead
|
|
|
|
To configure, set the path mappings in the plugin settings:
|
|
- **Jellyfin Media Path**: The path prefix as Jellyfin sees your library (e.g., `/media/music`)
|
|
- **LMS Media Path**: The same location as LMS sees it (e.g., `/mnt/music` or `//nas/music`)
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
Jellyfin.Plugin.JellyLMS/
|
|
├── Plugin.cs # Main plugin entry point
|
|
├── PluginServiceRegistrator.cs # DI service registration
|
|
├── Configuration/
|
|
│ ├── PluginConfiguration.cs # Plugin settings
|
|
│ └── configPage.html # Dashboard configuration UI
|
|
├── Api/
|
|
│ └── JellyLmsController.cs # REST API endpoints
|
|
├── Services/
|
|
│ ├── ILmsApiClient.cs # LMS API interface
|
|
│ ├── LmsApiClient.cs # LMS JSON-RPC client
|
|
│ ├── LmsPlayerManager.cs # Player discovery & sync
|
|
│ └── LmsSessionManager.cs # Playback session management
|
|
└── Models/
|
|
├── LmsPlayer.cs # Player model
|
|
├── LmsPlaybackSession.cs # Session state model
|
|
└── LmsApiModels.cs # JSON-RPC DTOs
|
|
```
|
|
|
|
### Building for Development
|
|
|
|
```bash
|
|
# Build in debug mode
|
|
dotnet build Jellyfin.Plugin.JellyLMS.sln
|
|
|
|
# Copy to Jellyfin plugins directory
|
|
cp Jellyfin.Plugin.JellyLMS/bin/Debug/net8.0/Jellyfin.Plugin.JellyLMS.dll \
|
|
~/.local/share/jellyfin/plugins/JellyLMS/
|
|
|
|
# Restart Jellyfin to load the plugin
|
|
```
|
|
|
|
## License
|
|
|
|
This plugin is licensed under the GPLv3. See [LICENSE](LICENSE) for details.
|
|
|
|
Due to how Jellyfin plugins work, when compiled into a binary, it links against Jellyfin's GPLv3-licensed NuGet packages, making the resulting binary GPLv3 licensed.
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please open an issue or submit a pull request.
|
|
|
|
## Acknowledgments
|
|
|
|
- [Jellyfin](https://jellyfin.org/) - The Free Software Media System
|
|
- [Logitech Media Server](https://github.com/Logitech/slimserver) - Open source server for Squeezebox players
|