mirror of
https://github.com/jellyfin/jellyfin.org.git
synced 2026-09-03 05:30:05 +03:00
Add WebSocket Message Types, Playing Audio Guide
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Audio
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
# Audio
|
||||
|
||||
When playing audio, the client must decide whether to use a transcoding stream or a direct play stream. This is determined by the playback info response from the server (see the Media Info documentation).
|
||||
|
||||
### 1. Use the Transcoding URL (if provided)
|
||||
|
||||
If the playback info response includes a `transcodingUrl` (or `TranscodingUrl` in the media source), use this URL to fetch the audio stream. This means the server will transcode the media to a format compatible with the device profile.
|
||||
|
||||
See [Media Info](./media-info.md) for additional details.
|
||||
|
||||
### 2. Direct Play with the Audio API
|
||||
|
||||
If no transcoding URL is provided, the client can perform direct play using the [Audio API stream operation](https://api.jellyfin.org/#tag/Audio/operation/GetAudioStream). The direct play URL is constructed as follows:
|
||||
|
||||
- **Endpoint:** `/Audio/{itemId}/stream`
|
||||
- **Query Parameters:**
|
||||
- `playSessionId`: The sessionId returned by the posted playback info operation (required for authentication)
|
||||
- `static=true`: Ensures no encoding is performed (static file delivery)
|
||||
- `startTimeTicks=0`: (optional) Start at the beginning
|
||||
|
||||
### Example (TypeScript SDK-style)
|
||||
|
||||
```ts
|
||||
function buildAudioStreamUrl(itemId: string, playSessionId: string, apiBase: string) {
|
||||
const params = new URLSearchParams({
|
||||
playSessionId,
|
||||
static: 'true',
|
||||
startTimeTicks: '0',
|
||||
});
|
||||
return `${apiBase}/Audio/${itemId}/stream?${params}`;
|
||||
}
|
||||
|
||||
// Usage:
|
||||
// If playbackInfo.transcodingUrl exists, use that URL directly.
|
||||
// Otherwise, use buildAudioStreamUrl(itemId, playbackInfo.sessionId, api.basePath)
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
- Always use the `sessionId` (or `playSessionId`) returned by the posted playback info operation for authentication.
|
||||
- The `static=true` parameter ensures the server does not transcode or re-encode the file for direct play.
|
||||
- If transcoding is required, always prefer the transcoding URL provided by the server.
|
||||
|
||||
For more details, see the [Jellyfin Audio API documentation](https://api.jellyfin.org/#tag/Audio/operation/GetAudioStream).
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: Device Profiles
|
||||
sidebar_position: 7
|
||||
---
|
||||
# Device Profiles
|
||||
|
||||
Device profiles in Jellyfin define the media playback and transcoding capabilities of a client device. They are used by the server to determine how to deliver media to each client, optimizing for direct play when possible and falling back to transcoding when necessary.
|
||||
|
||||
## What is a Device Profile?
|
||||
|
||||
A device profile is an object that describes:
|
||||
|
||||
- **Maximum Bitrate**: The highest bitrate (in bits per second) the device can handle for streaming or static playback.
|
||||
- **Direct Play Formats**: The containers, codecs, and protocols the device can play natively, without transcoding.
|
||||
- **Transcoding Formats**: The formats and codecs the device supports when the server must transcode media.
|
||||
- **Other Capabilities**: Additional options such as maximum audio channels, supported resolutions, or platform-specific quirks.
|
||||
|
||||
Device profiles allow Jellyfin to deliver the best possible experience for each device, minimizing unnecessary transcoding and ensuring compatibility.
|
||||
|
||||
## Example Structure
|
||||
|
||||
While the exact structure may vary by implementation, a typical device profile includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "Example Device",
|
||||
"MaxStreamingBitrate": 20000000,
|
||||
"DirectPlayProfiles": [
|
||||
{ "Container": "mp4", "Type": "Video" },
|
||||
{ "Container": "mp3", "Type": "Audio" }
|
||||
],
|
||||
"TranscodingProfiles": [
|
||||
{ "Container": "ts", "AudioCodec": "aac", "VideoCodec": "h264", "Type": "Video" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## How Device Profiles Are Used
|
||||
|
||||
1. **Client Sends Profile**: When a client connects, it provides its device profile to the server (or the server uses a default profile for known devices).
|
||||
2. **Server Evaluates Media**: When a user requests playback, the server checks the device profile to see if the media can be sent directly or needs to be transcoded.
|
||||
3. **Optimized Delivery**: The server streams the media in the best format supported by the device, using direct play whenever possible.
|
||||
|
||||
## Fields Explained
|
||||
|
||||
- `MaxStreamingBitrate`: The maximum bitrate the device can handle for streaming.
|
||||
- `DirectPlayProfiles`: List of containers/codecs that can be played without transcoding.
|
||||
- `TranscodingProfiles`: List of formats/codecs the server can use when transcoding for this device.
|
||||
- `MusicStreamingTranscodingBitrate` (optional): Maximum bitrate for music transcoding.
|
||||
- `ContainerProfiles`, `CodecProfiles`, etc.: Advanced options for fine-tuning compatibility.
|
||||
|
||||
## Example (TypeScript SDK)
|
||||
|
||||
If you are using the TypeScript SDK, you can construct a device profile like this:
|
||||
|
||||
```ts
|
||||
import { DeviceProfile, DlnaProfileType } from '@jellyfin/sdk/lib/generated-client';
|
||||
|
||||
const profile: DeviceProfile = {
|
||||
Name: 'My Device',
|
||||
MaxStreamingBitrate: 10000000,
|
||||
DirectPlayProfiles: [
|
||||
{ Container: 'mp3', Type: DlnaProfileType.Audio },
|
||||
{ Container: 'mp4', Type: DlnaProfileType.Video },
|
||||
],
|
||||
TranscodingProfiles: [
|
||||
{ Container: 'ts', AudioCodec: 'aac', VideoCodec: 'h264', Type: DlnaProfileType.Video },
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [Jellyfin TypeScript SDK - DeviceProfile](https://typescript-sdk.jellyfin.org/interfaces/generated-client.DeviceProfile.html)
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: Media Info
|
||||
sidebar_position: 8
|
||||
---
|
||||
## Fetching Playback Info with Device Profiles
|
||||
|
||||
Once a [device profile](./device-profiles.md) is created, it can be used to request playback information for a media item from the Jellyfin server. This is done using the [Post Playback Info](https://api.jellyfin.org/#tag/MediaInfo/operation/GetPostedPlaybackInfo) operation.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Send Device Profile**: The client sends its device profile along with the media item ID to the server.
|
||||
2. **Server Decision**: The server evaluates the device profile and the media item to determine if direct play is possible or if transcoding is required.
|
||||
3. **Playback Info Response**: The server responds with playback details, including URLs for direct play or transcoding, and a session ID.
|
||||
|
||||
## Key Fields in the Response
|
||||
|
||||
- **transcodingUrl**: If transcoding is required, this field contains the URL to fetch the transcoded media stream. If direct play is possible, this may be omitted or a direct stream URL will be provided instead.
|
||||
- **sessionId**: This is required when fetching the media stream. The sessionId provided in the request to fetch the stream must match the Id returned by the playback info call for authentication.
|
||||
|
||||
## Example (TypeScript SDK)
|
||||
|
||||
Here is an example of how to fetch playback info using a device profile with the TypeScript SDK:
|
||||
|
||||
```ts
|
||||
import { getApi } from 'your-app/stores';
|
||||
import { DeviceProfile } from '@jellyfin/sdk/lib/generated-client/models';
|
||||
import { getMediaInfoApi } from '@jellyfin/sdk/lib/utils/api';
|
||||
|
||||
async function fetchMediaInfo(deviceProfile: DeviceProfile, itemId: string) {
|
||||
const api = getApi();
|
||||
const { data } = await getMediaInfoApi(api).getPostedPlaybackInfo({
|
||||
itemId,
|
||||
playbackInfoDto: { DeviceProfile: deviceProfile },
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
// Usage:
|
||||
// const playbackInfo = await fetchMediaInfo(profile, 'itemId');
|
||||
// const url = playbackInfo.transcodingUrl || playbackInfo.mediaSources[0]?.path;
|
||||
// const sessionId = playbackInfo.sessionId;
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Always provide the correct sessionId when fetching the media stream.
|
||||
- The server will return the optimal playback method based on the device profile and media item.
|
||||
|
||||
For more details, see the [Jellyfin API documentation](https://api.jellyfin.org/#tag/MediaInfo/operation/GetPostedPlaybackInfo).
|
||||
|
||||
|
||||
@@ -22,3 +22,38 @@ Some WebSocket message types will require a 'start' message be sent before messa
|
||||
- `ScheduledTasksInfo`
|
||||
|
||||
The 'start' message should have a `Data` field indicating the interval in which messages should be delivered to the client. The format for this is `<initialDelay>,<interval>`, where the `initialDelay` is the number of milliseconds the server will delay sending the first outbound message, and the `interval` is the number of milliseconds in between outbound messages to the client.
|
||||
|
||||
## WebSocket Message Types
|
||||
|
||||
The following message types can be received via WebSocket subscription. Each message type has a specific payload structure, typically with a `Data` field containing the relevant information. Some types require a 'start' message to begin receiving updates (see above).
|
||||
|
||||
| MessageType | Description | Data Field Type |
|
||||
|-------------------------------|------------------------------------------------------------------|-------------------------------|
|
||||
| `ActivityLogEntry` | Activity log entries (requires start message) | Array of ActivityLogEntry |
|
||||
| `ForceKeepAlive` | Server requests client to send keep-alive messages | Number (interval ms) |
|
||||
| `GeneralCommand` | General commands sent to clients | GeneralCommand |
|
||||
| `KeepAlive` | Keep-alive ping/pong | None or heartbeat |
|
||||
| `LibraryChanged` | Library items added/removed/updated | LibraryUpdateInfo |
|
||||
| `PackageInstallationCancelled`| Plugin package installation cancelled | InstallationInfo |
|
||||
| `PackageInstallationCompleted`| Plugin package installation completed | InstallationInfo |
|
||||
| `PackageInstallationFailed` | Plugin package installation failed | InstallationInfo |
|
||||
| `PackageInstalling` | Plugin package is being installed | InstallationInfo |
|
||||
| `PackageUninstalled` | Plugin package uninstalled | InstallationInfo |
|
||||
| `Play` | Play command sent to clients | PlayRequest |
|
||||
| `Playstate` | Playstate changes (pause, stop, etc.) | PlaystateRequest |
|
||||
| `RefreshProgress` | Library or metadata refresh progress | Object (progress info) |
|
||||
| `RestartRequired` | Server restart required | RestartRequiredMessage |
|
||||
| `ScheduledTaskEnded` | Scheduled task finished | TaskResult |
|
||||
| `ScheduledTasksInfo` | Scheduled tasks status (requires start message) | Array of TaskInfo |
|
||||
| `SeriesTimerCancelled` | Series timer cancelled | SeriesTimerCancelledMessage |
|
||||
| `SeriesTimerCreated` | Series timer created | SeriesTimerCreatedMessage |
|
||||
| `ServerRestarting` | Server is restarting | ServerRestartingMessage |
|
||||
| `ServerShuttingDown` | Server is shutting down | ServerShuttingDownMessage |
|
||||
| `Sessions` | Active sessions (requires start message) | Array of SessionInfoDto |
|
||||
| `SyncPlayCommand` | SyncPlay command sent to group | SendCommand |
|
||||
| `SyncPlayGroupUpdate` | SyncPlay group state update | GroupUpdate |
|
||||
| `TimerCancelled` | Timer cancelled | TimerCancelledMessage |
|
||||
| `TimerCreated` | Timer created | TimerCreatedMessage |
|
||||
| `UserDataChanged` | User data (e.g. watched status) changed | UserDataChangeInfo |
|
||||
| `UserDeleted` | User deleted | string (user id) |
|
||||
| `UserUpdated` | User updated | UserDto |
|
||||
|
||||
@@ -27,6 +27,9 @@ export default function Index() {
|
||||
{ url: '/developers/docs/api/websockets', name: 'Connecting to WebSockets'},
|
||||
{ url: '/developers/docs/api/syncplay', name: 'Utilising the SyncPlay API' },
|
||||
{ url: '/developers/docs/api/playlists', name: 'Managing playlists' },
|
||||
{ url: '/developers/docs/api/device-profiles', name: 'Device profiles' },
|
||||
{ url: '/developers/docs/api/media-info', name: 'Fetching Media Info' },
|
||||
{ url: '/developers/docs/api/audio', name: 'Playing Audio' },
|
||||
]}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user