or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

audio-filters.mdevents-exceptions.mdindex.mdnode-management.mdplayer-control.mdqueue-system.mdtrack-search.md

player-control.mddocs/

0

# Player Control

1

2

Main audio player interface providing playback control, volume management, seeking, and voice channel operations with full discord.py VoiceProtocol integration. The Player class extends discord.VoiceProtocol to seamlessly integrate with Discord's voice system while providing advanced audio playback capabilities.

3

4

## Capabilities

5

6

### Player Creation & Connection

7

8

The Player class integrates with discord.py's voice system to provide audio playback in Discord voice channels.

9

10

```python { .api }

11

class Player(discord.VoiceProtocol):

12

def __init__(self, client: discord.Client, channel: discord.VoiceChannel):

13

"""

14

Initialize a new Player instance.

15

16

Parameters:

17

- client: Discord client instance

18

- channel: Voice channel to connect to

19

"""

20

21

# Predefined queue instances

22

queue: Queue # Standard track queue

23

auto_queue: Queue # AutoPlay queue for recommendations

24

25

async def connect(

26

self,

27

channel: discord.VoiceChannel,

28

*,

29

self_deaf: bool = True,

30

**kwargs

31

) -> None:

32

"""

33

Connect to a Discord voice channel.

34

35

Parameters:

36

- channel: Voice channel to connect to

37

- self_deaf: Whether to self-deafen the bot

38

- **kwargs: Additional connection parameters

39

40

Raises:

41

InvalidChannelStateException: If channel is invalid or no permissions

42

ChannelTimeoutException: If connection times out

43

"""

44

45

async def move_to(self, channel: discord.VoiceChannel) -> None:

46

"""

47

Move to a different voice channel.

48

49

Parameters:

50

- channel: New voice channel to move to

51

"""

52

53

async def disconnect(self, **kwargs) -> None:

54

"""

55

Disconnect from the voice channel.

56

57

Parameters:

58

- **kwargs: Additional disconnection parameters

59

"""

60

```

61

62

### Playback Control

63

64

Core playback functionality including play, pause, seek, skip, and stop operations.

65

66

```python { .api }

67

class Player(discord.VoiceProtocol):

68

async def play(

69

self,

70

track: Playable,

71

*,

72

replace: bool = True,

73

start: int = 0,

74

end: int | None = None,

75

volume: int | None = None,

76

paused: bool | None = None,

77

add_history: bool = True,

78

filters: Filters | None = None,

79

populate: bool = False,

80

max_populate: int = 5

81

) -> Playable:

82

"""

83

Play a track.

84

85

Parameters:

86

- track: The track to play

87

- replace: Whether to replace the current track

88

- start: Start position in milliseconds

89

- end: End position in milliseconds (None for full track)

90

- volume: Playback volume (0-100)

91

- paused: Whether to start paused

92

- add_history: Whether to add current track to history

93

- filters: Filters to apply when playing

94

- populate: Whether to populate AutoPlay queue

95

- max_populate: Maximum tracks to populate for AutoPlay

96

97

Returns:

98

Playable: The track that is now playing

99

"""

100

101

async def pause(self, value: bool) -> None:

102

"""

103

Pause or unpause playback.

104

105

Parameters:

106

- value: True to pause, False to unpause

107

"""

108

109

async def seek(self, position: int = 0) -> None:

110

"""

111

Seek to a specific position in the current track.

112

113

Parameters:

114

- position: Position to seek to in milliseconds

115

116

Raises:

117

ValueError: If track is not seekable

118

"""

119

120

async def stop(self, *, force: bool = True) -> Playable | None:

121

"""

122

Stop the current track.

123

124

Parameters:

125

- force: Whether to force stop immediately

126

127

Returns:

128

Playable | None: The stopped track, if any

129

"""

130

131

async def skip(self, *, force: bool = True) -> Playable | None:

132

"""

133

Skip to the next track in the queue.

134

135

Parameters:

136

- force: Whether to force skip immediately

137

138

Returns:

139

Playable | None: The skipped track, if any

140

"""

141

```

142

143

### Player State & Properties

144

145

Properties for monitoring and controlling player state, volume, and playback information.

146

147

```python { .api }

148

class Player(discord.VoiceProtocol):

149

@property

150

def inactive_channel_tokens(self) -> int | None:

151

"""

152

Token limit for the amount of tracks to play before firing

153

the on_wavelink_inactive_player event when a channel is inactive.

154

155

Returns None if the check has been disabled. A channel is

156

considered inactive when no real members are in the voice channel.

157

Default value is 3. Setting to <= 0 or None disables the check.

158

"""

159

160

@inactive_channel_tokens.setter

161

def inactive_channel_tokens(self, value: int | None) -> None:

162

"""Set the inactive channel token limit."""

163

164

@property

165

def inactive_timeout(self) -> int | None:

166

"""

167

Time in seconds to wait before dispatching the

168

on_wavelink_inactive_player event for inactive players.

169

170

Returns None if no timeout is set. An inactive player is one

171

that has not been playing anything for the specified seconds.

172

The countdown starts when a track ends and cancels when a track starts.

173

"""

174

175

@inactive_timeout.setter

176

def inactive_timeout(self, value: int | None) -> None:

177

"""Set the inactive timeout in seconds."""

178

179

@property

180

def autoplay(self) -> AutoPlayMode:

181

"""Current AutoPlay mode setting."""

182

183

@autoplay.setter

184

def autoplay(self, value: AutoPlayMode) -> None:

185

"""Set the AutoPlay mode."""

186

187

@property

188

def node(self) -> Node:

189

"""The Lavalink node this player is connected to."""

190

191

@property

192

def guild(self) -> discord.Guild | None:

193

"""The Discord guild this player belongs to."""

194

195

@property

196

def connected(self) -> bool:

197

"""Whether the player is connected to a voice channel."""

198

199

@property

200

def current(self) -> Playable | None:

201

"""The currently playing track."""

202

203

@property

204

def volume(self) -> int:

205

"""Current player volume (0-100)."""

206

207

@property

208

def filters(self) -> Filters:

209

"""Currently applied audio filters."""

210

211

@property

212

def paused(self) -> bool:

213

"""Whether playback is currently paused."""

214

215

@property

216

def ping(self) -> int:

217

"""WebSocket ping to the Lavalink server in milliseconds."""

218

219

@property

220

def playing(self) -> bool:

221

"""Whether the player is currently playing a track."""

222

223

@property

224

def position(self) -> int:

225

"""Current playback position in milliseconds."""

226

```

227

228

### Volume & Filter Control

229

230

Methods for controlling audio volume and applying audio filters to enhance playback.

231

232

```python { .api }

233

class Player(discord.VoiceProtocol):

234

async def set_volume(self, value: int = 100) -> None:

235

"""

236

Set the player volume.

237

238

Parameters:

239

- value: Volume level (0-100)

240

241

Raises:

242

ValueError: If volume is outside valid range

243

"""

244

245

async def set_filters(

246

self,

247

filters: Filters | None = None,

248

*,

249

seek: bool = False

250

) -> None:

251

"""

252

Apply audio filters to the player.

253

254

Parameters:

255

- filters: Filters object to apply (None to reset all filters)

256

- seek: Whether to seek to current position after applying filters

257

"""

258

```

259

260

### Event Handlers

261

262

Event handler methods that can be overridden to respond to player events.

263

264

```python { .api }

265

class Player(discord.VoiceProtocol):

266

async def on_voice_state_update(self, data) -> None:

267

"""

268

Handle voice state updates from Discord.

269

270

Parameters:

271

- data: Voice state update data

272

"""

273

274

async def on_voice_server_update(self, data) -> None:

275

"""

276

Handle voice server updates from Discord.

277

278

Parameters:

279

- data: Voice server update data

280

"""

281

```

282

283

## Usage Examples

284

285

### Basic Player Setup

286

287

```python

288

import discord

289

import wavelink

290

from discord.ext import commands

291

292

bot = commands.Bot(command_prefix='!', intents=discord.Intents.all())

293

294

@bot.command()

295

async def join(ctx):

296

"""Join the user's voice channel."""

297

if not ctx.author.voice:

298

return await ctx.send("You're not in a voice channel!")

299

300

channel = ctx.author.voice.channel

301

player = await channel.connect(cls=wavelink.Player)

302

await ctx.send(f"Connected to {channel.name}")

303

304

@bot.command()

305

async def leave(ctx):

306

"""Leave the voice channel."""

307

player = ctx.voice_client

308

if player:

309

await player.disconnect()

310

await ctx.send("Disconnected!")

311

```

312

313

### Playback Control

314

315

```python

316

@bot.command()

317

async def play(ctx, *, query: str):

318

"""Play a track or add to queue."""

319

if not ctx.voice_client:

320

player = await ctx.author.voice.channel.connect(cls=wavelink.Player)

321

else:

322

player = ctx.voice_client

323

324

# Search for tracks

325

tracks = await wavelink.Pool.fetch_tracks(query)

326

if not tracks:

327

return await ctx.send("No tracks found!")

328

329

track = tracks[0] if isinstance(tracks, list) else tracks.tracks[0]

330

331

if player.playing:

332

# Add to queue if already playing

333

player.queue.put(track)

334

await ctx.send(f"Added to queue: {track.title}")

335

else:

336

# Start playing immediately

337

await player.play(track)

338

await ctx.send(f"Now playing: {track.title}")

339

340

@bot.command()

341

async def pause(ctx):

342

"""Pause or unpause playback."""

343

player = ctx.voice_client

344

if not player:

345

return await ctx.send("Not connected to a voice channel!")

346

347

await player.pause(not player.paused)

348

action = "Paused" if player.paused else "Resumed"

349

await ctx.send(f"{action} playback!")

350

351

@bot.command()

352

async def skip(ctx):

353

"""Skip the current track."""

354

player = ctx.voice_client

355

if not player or not player.playing:

356

return await ctx.send("Nothing is playing!")

357

358

skipped_track = await player.skip()

359

await ctx.send(f"Skipped: {skipped_track.title}")

360

361

@bot.command()

362

async def seek(ctx, seconds: int):

363

"""Seek to a position in the current track."""

364

player = ctx.voice_client

365

if not player or not player.current:

366

return await ctx.send("Nothing is playing!")

367

368

if not player.current.is_seekable:

369

return await ctx.send("This track is not seekable!")

370

371

position = seconds * 1000 # Convert to milliseconds

372

await player.seek(position)

373

await ctx.send(f"Seeked to {seconds} seconds")

374

```

375

376

### Volume Control

377

378

```python

379

@bot.command()

380

async def volume(ctx, level: int = None):

381

"""Get or set the player volume."""

382

player = ctx.voice_client

383

if not player:

384

return await ctx.send("Not connected to a voice channel!")

385

386

if level is None:

387

await ctx.send(f"Current volume: {player.volume}%")

388

else:

389

if not 0 <= level <= 100:

390

return await ctx.send("Volume must be between 0 and 100!")

391

392

await player.set_volume(level)

393

await ctx.send(f"Volume set to {level}%")

394

```

395

396

### AutoPlay Configuration

397

398

```python

399

@bot.command()

400

async def autoplay(ctx, mode: str = None):

401

"""Configure AutoPlay mode."""

402

player = ctx.voice_client

403

if not player:

404

return await ctx.send("Not connected to a voice channel!")

405

406

if mode is None:

407

current = player.autoplay.name

408

await ctx.send(f"AutoPlay mode: {current}")

409

return

410

411

mode_map = {

412

'enabled': wavelink.AutoPlayMode.enabled,

413

'partial': wavelink.AutoPlayMode.partial,

414

'disabled': wavelink.AutoPlayMode.disabled

415

}

416

417

if mode.lower() not in mode_map:

418

return await ctx.send("Valid modes: enabled, partial, disabled")

419

420

player.autoplay = mode_map[mode.lower()]

421

await ctx.send(f"AutoPlay mode set to: {mode}")

422

```

423

424

### Player Information

425

426

```python

427

@bot.command()

428

async def now_playing(ctx):

429

"""Show information about the current track."""

430

player = ctx.voice_client

431

if not player or not player.current:

432

return await ctx.send("Nothing is playing!")

433

434

track = player.current

435

embed = discord.Embed(

436

title="Now Playing",

437

description=f"**{track.title}**\nby {track.author}",

438

color=discord.Color.blue()

439

)

440

441

embed.add_field(

442

name="Duration",

443

value=f"{track.length // 60000}:{(track.length // 1000) % 60:02d}",

444

inline=True

445

)

446

embed.add_field(

447

name="Position",

448

value=f"{player.position // 60000}:{(player.position // 1000) % 60:02d}",

449

inline=True

450

)

451

embed.add_field(name="Volume", value=f"{player.volume}%", inline=True)

452

embed.add_field(name="Source", value=track.source.name, inline=True)

453

embed.add_field(name="Paused", value=player.paused, inline=True)

454

embed.add_field(name="Queue Size", value=player.queue.count, inline=True)

455

456

if track.artwork:

457

embed.set_thumbnail(url=track.artwork)

458

459

await ctx.send(embed=embed)

460

```