0
# Client Control and Remote Playback
1
2
Remote control interface for all connected Plex clients including smartphones, tablets, streaming devices, and Sonos speakers. Supports comprehensive playback control, volume adjustment, timeline navigation, and status monitoring with real-time client state management.
3
4
## Capabilities
5
6
### PlexClient - Remote Client Control
7
8
Main interface for controlling connected Plex client devices with full playback control and status monitoring.
9
10
```python { .api }
11
class PlexClient:
12
def __init__(self, baseurl, token=None, session=None, timeout=None):
13
"""
14
Initialize connection to a Plex client.
15
16
Args:
17
baseurl (str): Client base URL
18
token (str, optional): Client authentication token
19
session (requests.Session, optional): Custom session object
20
timeout (int, optional): Connection timeout
21
"""
22
23
@property
24
def title(self):
25
"""Client device name/title."""
26
27
@property
28
def machineIdentifier(self):
29
"""Unique client machine identifier."""
30
31
@property
32
def product(self):
33
"""Client product name (e.g. 'Plex for iOS')."""
34
35
@property
36
def platform(self):
37
"""Client platform (e.g. 'iOS', 'Android', 'Windows')."""
38
39
@property
40
def platformVersion(self):
41
"""Platform version string."""
42
43
@property
44
def version(self):
45
"""Client application version."""
46
47
@property
48
def state(self):
49
"""Current playback state ('playing', 'paused', 'stopped')."""
50
51
def playMedia(self, media, offset=0, **kwargs):
52
"""
53
Play media on this client.
54
55
Args:
56
media (MediaObject): Media item to play (Movie, Episode, Track, etc.)
57
offset (int): Playback start offset in milliseconds
58
**kwargs: Additional playback parameters
59
"""
60
61
def pause(self):
62
"""Pause current playback."""
63
64
def play(self):
65
"""Resume/start playback."""
66
67
def stop(self):
68
"""Stop current playback."""
69
70
def skipNext(self):
71
"""Skip to next item in queue."""
72
73
def skipPrevious(self):
74
"""Skip to previous item in queue."""
75
76
def stepForward(self):
77
"""Step forward in playback."""
78
79
def stepBack(self):
80
"""Step backward in playback."""
81
82
def seekTo(self, offset, mtype='video'):
83
"""
84
Seek to specific position.
85
86
Args:
87
offset (int): Target position in milliseconds
88
mtype (str): Media type ('video', 'music', 'photo')
89
"""
90
91
def setVolume(self, volume, mtype='video'):
92
"""
93
Set playback volume.
94
95
Args:
96
volume (int): Volume level (0-100)
97
mtype (str): Media type ('video', 'music')
98
"""
99
100
def timeline(self):
101
"""
102
Get current playback timeline information.
103
104
Returns:
105
dict: Timeline data with current position, duration, state
106
"""
107
108
def isPlaying(self, mtype='video'):
109
"""
110
Check if client is currently playing.
111
112
Args:
113
mtype (str): Media type to check
114
115
Returns:
116
bool: True if playing
117
"""
118
119
def status(self):
120
"""
121
Get detailed client status.
122
123
Returns:
124
dict: Comprehensive client status information
125
"""
126
127
def sendCommand(self, command, **kwargs):
128
"""
129
Send raw command to client.
130
131
Args:
132
command (str): Command to send
133
**kwargs: Command parameters
134
135
Returns:
136
requests.Response: Command response
137
"""
138
139
def connect(self, ssl=None, timeout=None):
140
"""
141
Establish connection to client.
142
143
Args:
144
ssl (bool, optional): Force SSL connection
145
timeout (int, optional): Connection timeout
146
147
Returns:
148
PlexClient: Connected client instance
149
"""
150
```
151
152
### PlexSonosClient - Sonos Speaker Control
153
154
Specialized client for controlling Sonos speakers through Plex, extending PlexClient with Sonos-specific functionality.
155
156
```python { .api }
157
class PlexSonosClient(PlexClient):
158
"""
159
Specialized client for Sonos speakers.
160
Inherits all PlexClient methods with Sonos-specific behavior.
161
"""
162
163
def playMedia(self, media, **kwargs):
164
"""
165
Play media on Sonos speaker.
166
Routes through Plex's Sonos integration.
167
168
Args:
169
media (MediaObject): Media to play (typically music)
170
**kwargs: Sonos-specific playback parameters
171
"""
172
173
def setVolume(self, volume):
174
"""
175
Set Sonos speaker volume.
176
177
Args:
178
volume (int): Volume level (0-100)
179
"""
180
181
def mute(self):
182
"""Mute Sonos speaker."""
183
184
def unmute(self):
185
"""Unmute Sonos speaker."""
186
```
187
188
## Client Discovery and Management
189
190
### Finding Connected Clients
191
192
```python
193
# List all connected clients
194
clients = plex.clients()
195
for client in clients:
196
print(f"Client: {client.title} ({client.product})")
197
print(f"Platform: {client.platform} {client.platformVersion}")
198
print(f"State: {client.state}")
199
200
# Get specific client by name
201
iphone = plex.client("Michael's iPhone")
202
apple_tv = plex.client("Living Room Apple TV")
203
```
204
205
### Client Status Monitoring
206
207
```python
208
# Check client status
209
client = plex.client("Living Room TV")
210
status = client.status()
211
timeline = client.timeline()
212
213
print(f"Playing: {client.isPlaying()}")
214
print(f"State: {client.state}")
215
print(f"Current Position: {timeline.get('time', 0) // 1000} seconds")
216
print(f"Duration: {timeline.get('duration', 0) // 1000} seconds")
217
```
218
219
## Playback Control Examples
220
221
### Basic Media Playback
222
223
```python
224
# Play a movie on specific client
225
movie = plex.library.section('Movies').get('Inception')
226
tv_client = plex.client("Living Room TV")
227
228
# Start from beginning
229
tv_client.playMedia(movie)
230
231
# Start from specific timestamp (30 minutes in)
232
tv_client.playMedia(movie, offset=30*60*1000) # milliseconds
233
```
234
235
### Playback Control Operations
236
237
```python
238
client = plex.client("Living Room TV")
239
240
# Basic playback control
241
client.pause() # Pause playback
242
client.play() # Resume playback
243
client.stop() # Stop playback
244
245
# Navigation
246
client.skipNext() # Next item
247
client.skipPrevious() # Previous item
248
client.stepForward() # Small skip forward
249
client.stepBack() # Small skip backward
250
251
# Seeking
252
client.seekTo(45*60*1000) # Seek to 45 minutes
253
254
# Volume control
255
client.setVolume(75) # Set volume to 75%
256
```
257
258
### Music Playback
259
260
```python
261
# Play music track
262
track = plex.library.section('Music').get('The Beatles').album('Abbey Road').track('Come Together')
263
sonos = plex.client("Kitchen Sonos")
264
265
# Play track
266
sonos.playMedia(track)
267
268
# Control volume
269
sonos.setVolume(60)
270
271
# For PlexSonosClient specifically
272
if isinstance(sonos, PlexSonosClient):
273
sonos.mute()
274
# ... do something
275
sonos.unmute()
276
```
277
278
### Episode/Show Playback
279
280
```python
281
# Play TV episode
282
show = plex.library.section('TV Shows').get('The Office')
283
episode = show.episode(season=1, episode=1)
284
client = plex.client("Bedroom TV")
285
286
client.playMedia(episode)
287
288
# Binge watching - play next episode automatically
289
current_episode = episode
290
while current_episode:
291
client.playMedia(current_episode)
292
293
# Wait for completion (simplified example)
294
import time
295
while client.isPlaying():
296
time.sleep(30)
297
298
# Get next episode
299
next_episodes = show.episodes()
300
current_index = next_episodes.index(current_episode)
301
if current_index + 1 < len(next_episodes):
302
current_episode = next_episodes[current_index + 1]
303
else:
304
break
305
```
306
307
## Advanced Client Operations
308
309
### Timeline Monitoring
310
311
```python
312
import time
313
314
def monitor_playback(client, interval=5):
315
"""Monitor playback progress on a client."""
316
while client.isPlaying():
317
timeline = client.timeline()
318
current_time = timeline.get('time', 0) // 1000
319
duration = timeline.get('duration', 0) // 1000
320
321
if duration > 0:
322
progress = (current_time / duration) * 100
323
print(f"Progress: {current_time//60}:{current_time%60:02d} / {duration//60}:{duration%60:02d} ({progress:.1f}%)")
324
325
time.sleep(interval)
326
327
# Monitor playback
328
client = plex.client("Living Room TV")
329
monitor_playback(client)
330
```
331
332
### Multi-Client Synchronization
333
334
```python
335
# Play same content on multiple clients
336
movie = plex.library.section('Movies').get('Movie Night Pick')
337
clients = [
338
plex.client("Living Room TV"),
339
plex.client("Bedroom TV"),
340
plex.client("Kitchen Tablet")
341
]
342
343
# Start playback on all clients simultaneously
344
for client in clients:
345
client.playMedia(movie)
346
347
# Synchronized pause/play
348
def sync_pause(clients):
349
for client in clients:
350
client.pause()
351
352
def sync_play(clients):
353
for client in clients:
354
client.play()
355
```
356
357
### Error Handling
358
359
```python
360
from plexapi.exceptions import NotFound, BadRequest
361
362
try:
363
client = plex.client("Non-existent Client")
364
except NotFound:
365
print("Client not found")
366
367
try:
368
# Try to play media on offline client
369
movie = plex.library.section('Movies').get('Test Movie')
370
offline_client = plex.client("Offline TV")
371
offline_client.playMedia(movie)
372
except BadRequest as e:
373
print(f"Playback failed: {e}")
374
```
375
376
## Sonos Integration Requirements
377
378
To control Sonos speakers through PlexAPI:
379
380
1. **Active Plex Pass subscription**
381
2. **Sonos account linked to Plex account**
382
3. **Plex remote access enabled**
383
384
The API calls route through https://sonos.plex.tv and back via the Plex server's remote access. Media playback is local unless networking restrictions prevent direct connection.
385
386
```python
387
# Example Sonos setup verification
388
try:
389
sonos_clients = [c for c in plex.clients() if 'Sonos' in c.product]
390
if sonos_clients:
391
print(f"Found {len(sonos_clients)} Sonos speakers")
392
for sonos in sonos_clients:
393
print(f" - {sonos.title}")
394
else:
395
print("No Sonos speakers found - check Plex Pass and account linking")
396
except Exception as e:
397
print(f"Sonos discovery failed: {e}")
398
```