@scarlett-player/media-session 1.7.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -0
- package/dist/index.cjs +6 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @scarlett-player/media-session
|
|
2
|
+
|
|
3
|
+
Media Session plugin for [Scarlett Player](https://scarlettplayer.com). Wires the player into the browser's Media Session API so playback can be controlled from the lock screen, the notification shade, hardware media keys and the system media UI, with track title, artist, album, artwork and a live seek bar. Where the API is missing the plugin logs a notice and does nothing, so it is safe to include everywhere.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @scarlett-player/media-session @scarlett-player/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`@scarlett-player/core` is a peer dependency.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createPlayer } from '@scarlett-player/core';
|
|
17
|
+
import { createNativePlugin } from '@scarlett-player/native';
|
|
18
|
+
import { createMediaSessionPlugin } from '@scarlett-player/media-session';
|
|
19
|
+
|
|
20
|
+
const player = await createPlayer({
|
|
21
|
+
container: document.getElementById('player'),
|
|
22
|
+
src: 'https://example.com/track.mp3',
|
|
23
|
+
plugins: [
|
|
24
|
+
createNativePlugin(),
|
|
25
|
+
createMediaSessionPlugin({
|
|
26
|
+
seekOffset: 15,
|
|
27
|
+
defaultArtwork: [{ src: '/default-artwork.png', sizes: '512x512' }],
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
With no configuration the plugin registers play, pause, stop, seek and track navigation handlers, mirrors the player's playing, paused and ended states, and updates the system seek bar about once a second while playing.
|
|
34
|
+
|
|
35
|
+
Metadata comes from three places, in order of arrival: the player's `title` and `poster` state (the poster becomes the artwork), a `playlist:change` event from `@scarlett-player/playlist` (title, artist, album and artwork are read from the track), and calls to `setMetadata()`. When no artwork is available `defaultArtwork` is used.
|
|
36
|
+
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
| Option | Type | Default | Description |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| `enablePlayPause` | `boolean` | `true` | Register the `play`, `pause` and `stop` action handlers |
|
|
42
|
+
| `enableSeek` | `boolean` | `true` | Register the `seekbackward`, `seekforward` and `seekto` action handlers |
|
|
43
|
+
| `enableTrackNavigation` | `boolean` | `true` | Register `previoustrack` and `nexttrack`. Both call the playlist plugin when it is present; without one, previous seeks to 0 and next does nothing |
|
|
44
|
+
| `seekOffset` | `number` | `10` | Seconds to skip for `seekbackward` and `seekforward` when the OS does not supply its own offset |
|
|
45
|
+
| `defaultArtwork` | `MediaSessionArtwork[]` | `undefined` | Artwork used when the current metadata has none. Each entry is `{ src, sizes?, type? }`; `sizes` defaults to `'512x512'` and `type` to `'image/png'` |
|
|
46
|
+
| `updatePositionState` | `boolean` | `true` | Push duration, position and playback rate to the system seek bar on `playback:timeupdate` (throttled to once per second) and on `media:loadedmetadata` |
|
|
47
|
+
|
|
48
|
+
## Plugin API
|
|
49
|
+
|
|
50
|
+
The plugin is registered under the id `media-session`:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import type { IMediaSessionPlugin } from '@scarlett-player/media-session';
|
|
54
|
+
|
|
55
|
+
const session = player.getPlugin<IMediaSessionPlugin>('media-session');
|
|
56
|
+
|
|
57
|
+
session?.isSupported();
|
|
58
|
+
session?.setMetadata({
|
|
59
|
+
title: 'Track 1',
|
|
60
|
+
artist: 'Artist',
|
|
61
|
+
album: 'Album',
|
|
62
|
+
artwork: [{ src: '/art1.jpg', sizes: '512x512', type: 'image/jpeg' }],
|
|
63
|
+
});
|
|
64
|
+
session?.setPlaybackState('playing');
|
|
65
|
+
session?.setPositionState({ duration: 240, position: 12, playbackRate: 1 });
|
|
66
|
+
session?.setActionHandler('nexttrack', () => goToNextEpisode());
|
|
67
|
+
session?.setActionHandler('nexttrack', null); // remove it again
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Method | Description |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `isSupported()` | `true` when `navigator.mediaSession` exists |
|
|
73
|
+
| `setMetadata(metadata)` | Merge `title`, `artist`, `album` and `artwork` into the current metadata and push it to the OS |
|
|
74
|
+
| `setPlaybackState(state)` | Set `'none'`, `'paused'` or `'playing'` directly |
|
|
75
|
+
| `setPositionState({ duration, position, playbackRate })` | Update the system seek bar directly |
|
|
76
|
+
| `setActionHandler(action, handler)` | Replace one of the built-in handlers, or pass `null` to clear it |
|
|
77
|
+
|
|
78
|
+
## Events
|
|
79
|
+
|
|
80
|
+
The plugin emits no events of its own. In response to OS actions it emits the core events `playback:play`, `playback:pause` and `playback:seeking`, and it listens to `playback:play`, `playback:pause`, `playback:ended`, `playback:timeupdate`, `media:loadedmetadata` and `playlist:change`.
|
|
81
|
+
|
|
82
|
+
On destroy every action handler is cleared, the metadata is set to `null` and the playback state returns to `'none'`.
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,11 @@ __export(index_exports, {
|
|
|
24
24
|
default: () => index_default
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/version.ts
|
|
29
|
+
var PKG_VERSION = true ? "1.8.1" : "0.0.0-dev";
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
27
32
|
var DEFAULT_CONFIG = {
|
|
28
33
|
enablePlayPause: true,
|
|
29
34
|
enableSeek: true,
|
|
@@ -171,7 +176,7 @@ function createMediaSessionPlugin(config) {
|
|
|
171
176
|
const plugin = {
|
|
172
177
|
id: "media-session",
|
|
173
178
|
name: "Media Session",
|
|
174
|
-
version:
|
|
179
|
+
version: PKG_VERSION,
|
|
175
180
|
type: "feature",
|
|
176
181
|
description: "Media Session API integration for system-level media controls",
|
|
177
182
|
async init(pluginApi) {
|
package/dist/index.d.cts
CHANGED
|
@@ -124,9 +124,10 @@ interface IMediaSessionPlugin extends Plugin<MediaSessionPluginConfig> {
|
|
|
124
124
|
*
|
|
125
125
|
* @example
|
|
126
126
|
* ```ts
|
|
127
|
+
* import { createPlayer } from '@scarlett-player/core';
|
|
127
128
|
* import { createMediaSessionPlugin } from '@scarlett-player/media-session';
|
|
128
129
|
*
|
|
129
|
-
* const player =
|
|
130
|
+
* const player = await createPlayer({
|
|
130
131
|
* container: document.getElementById('player'),
|
|
131
132
|
* plugins: [
|
|
132
133
|
* createMediaSessionPlugin({
|
package/dist/index.d.ts
CHANGED
|
@@ -124,9 +124,10 @@ interface IMediaSessionPlugin extends Plugin<MediaSessionPluginConfig> {
|
|
|
124
124
|
*
|
|
125
125
|
* @example
|
|
126
126
|
* ```ts
|
|
127
|
+
* import { createPlayer } from '@scarlett-player/core';
|
|
127
128
|
* import { createMediaSessionPlugin } from '@scarlett-player/media-session';
|
|
128
129
|
*
|
|
129
|
-
* const player =
|
|
130
|
+
* const player = await createPlayer({
|
|
130
131
|
* container: document.getElementById('player'),
|
|
131
132
|
* plugins: [
|
|
132
133
|
* createMediaSessionPlugin({
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/version.ts
|
|
2
|
+
var PKG_VERSION = true ? "1.8.1" : "0.0.0-dev";
|
|
3
|
+
|
|
1
4
|
// src/index.ts
|
|
2
5
|
var DEFAULT_CONFIG = {
|
|
3
6
|
enablePlayPause: true,
|
|
@@ -146,7 +149,7 @@ function createMediaSessionPlugin(config) {
|
|
|
146
149
|
const plugin = {
|
|
147
150
|
id: "media-session",
|
|
148
151
|
name: "Media Session",
|
|
149
|
-
version:
|
|
152
|
+
version: PKG_VERSION,
|
|
150
153
|
type: "feature",
|
|
151
154
|
description: "Media Session API integration for system-level media controls",
|
|
152
155
|
async init(pluginApi) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scarlett-player/media-session",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Media Session Plugin for Scarlett Player - Lock screen controls, media keys, and system media UI integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@scarlett-player/core": "^1.0
|
|
25
|
+
"@scarlett-player/core": "^1.8.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"tsup": "^8.0.0",
|
|
29
29
|
"typescript": "^5.3.0",
|
|
30
30
|
"vitest": "^1.6.0",
|
|
31
31
|
"jsdom": "^24.0.0",
|
|
32
|
-
"@scarlett-player/core": "1.
|
|
32
|
+
"@scarlett-player/core": "1.8.1"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
35
35
|
"video",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
},
|
|
54
54
|
"homepage": "https://scarlettplayer.com",
|
|
55
55
|
"scripts": {
|
|
56
|
-
"build": "tsup
|
|
57
|
-
"dev": "tsup
|
|
56
|
+
"build": "tsup",
|
|
57
|
+
"dev": "tsup --watch",
|
|
58
58
|
"test": "vitest --run",
|
|
59
59
|
"test:watch": "vitest",
|
|
60
60
|
"typecheck": "tsc --noEmit"
|