Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
sonolink 1.0.0 documentation
Light Logo Dark Logo

Main

  • Home
  • Installation
  • Guides
    • Lavalink Setup
    • Migrating From Wavelink
    • Working With Players
    • Filters And Playback State
  • API Reference
    • Core API
    • Models
    • Enums
    • Events
    • Exceptions
    • Advanced
      • Gateway API
      • REST API
      • Supplementary

Meta

  • Changelog
  • Version Guarantees

Content Width

Back to top
View this page

Migrating From Wavelink¶

This guide is for users coming from Wavelink.

What stays familiar¶

  • Lavalink remains the backend.

  • All three supported Discord libraries (discord.py, py-cord, disnake) use a custom discord.VoiceProtocol for voice integration.

  • The main runtime objects are still a client-level coordinator, nodes, players, queues, tracks, playlists, and filters.

What changes¶

The migration is mostly about replacing the old global Wavelink entry points with explicit SonoLink objects and adapting to different return types.

Concept mapping¶

Wavelink

SonoLink

wavelink.Pool

sonolink.Client

wavelink.Node

sonolink.Node

wavelink.Player

sonolink.Player

wavelink.Playable.search(...)

sonolink.Client.search_track()

wavelink.Pool.fetch_tracks(...)

sonolink.Node.search_track()

wavelink.Search

sonolink.models.SearchResult

wavelink.Filters

sonolink.models.Filters

Connection lifecycle¶

In Wavelink, node management is centered on the class-level pool API. The Wavelink docs show connecting with wavelink.Pool.connect(...) after building wavelink.Node(...) objects.

In SonoLink, the equivalent flow is explicit and instance-based:

import sonolink

sl_client = sonolink.Client(bot)

sl_client.create_node(
    uri="http://localhost:2333",
    password="youshallnotpass",
    id="main",
)

async def setup_hook() -> None:
    await sl_client.start()

Note

sonolink.Client.start() should be called once your Discord client is ready, typically in discord.Client.setup_hook() (discord.py), discord.on_connect() (py-cord) or disnake.on_connect() (disnake) rather than in the on_ready event.

Settings¶

SonoLink introduces a settings system with no direct Wavelink equivalent. Settings are dataclass-like objects passed at node or player creation time, giving you structured control over behavior that Wavelink left to ad-hoc configuration:

  • sonolink.models.InactivitySettings — controls how long a player waits before disconnecting when the channel is inactive, and what counts as inactive.

  • sonolink.models.CacheSettings — configures the node-level LFU search result cache.

  • sonolink.models.AutoPlaySettings — configures autoplay mode, search provider, discovery count, and seed limits.

  • sonolink.models.HistorySettings — enables or limits the track history that previous and autoplay depend on.

from sonolink.models.settings import AutoPlaySettings, CacheSettings, HistorySettings, InactivitySettings
from sonolink.gateway.enums import AutoPlayMode, InactivityMode

sl_client.create_node(
    uri="http://localhost:2333",
    password="youshallnotpass",
    inactivity_settings=InactivitySettings(
        timeout=300,
        mode=InactivityMode.ALL_BOTS,
    ),
    cache_settings=CacheSettings(
        enabled=True,
        max_items=1000,
    ),
)

player = sl_client.get_best_node().create_player(
    autoplay_settings=AutoPlaySettings(
        mode=AutoPlayMode.ENABLED,
        discovery_count=10,
    ),
    history_settings=HistorySettings(
        enabled=True,
        max_items=100,
    ),
)

Searching¶

In Wavelink 3, the documented search flow is usually:

# Wavelink
tracks = await wavelink.Playable.search(query)
if not tracks:
    return

if isinstance(tracks, wavelink.Playlist):
    track = tracks.tracks[0]
else:
    track = tracks[0]

In SonoLink, searching returns a wrapper object that makes the result type explicit:

# SonoLink
result = await sl_client.search_track(query)
if result.is_error() or result.is_empty() or result.result is None:
    return

data = result.result
rest = []

if isinstance(data, list):
    play_track = data[0]
elif isinstance(data, sonolink.models.Playlist):
    play_track = data.tracks[0]
    rest = data.tracks[1:]
else:
    play_track = data

sonolink.models.SearchResult covers all possible outcomes: a single track, a playlist, a search result list, an empty result, or an error result.

Players and voice connection¶

You still connect through Discord with:

player = await voice_channel.connect(cls=sonolink.Player)

If you need to pre-configure a player with volume, filters, queue mode, autoplay, or history settings before connecting, you can either instantiate sonolink.Player directly or use sonolink.Node.create_player() — both are equivalent:

from sonolink.models import Filters, Karaoke

player = sonolink.Player(
    node=node,
    volume=100,
    filters=Filters(
        karaoke=Karaoke(level=0.5),
    ),
)

# or

player = node.create_player(
    volume=100,
    filters=Filters(
        karaoke=Karaoke(level=0.5),
    ),
)

await voice_channel.connect(cls=player)

See Working With Players for the full player reference.

Playback flow¶

SonoLink does not expose a playing property. The common pattern is to call sonolink.Player.play() directly when nothing is currently playing, and put remaining tracks into the queue. Queue progression after a track ends is handled automatically:

if not vc.current:
    await vc.play(play_track)
else:
    rest = [play_track, *rest]

for track in rest:
    await vc.queue.put_wait(track)

When a track ends, SonoLink automatically calls sonolink.Player.skip() internally, which pulls the next track from the queue, falls back to autoplay if the queue is empty, and stops the player if neither applies. You do not need to drive this manually.

Filters¶

SonoLink applies filters with the same player method name, but the type is different:

from sonolink.models import Filters

filters = Filters()
await player.set_filters(filters, seek=True)

See Filters And Playback State for the full filter reference.

Events¶

Wavelink has documented public event names such as on_wavelink_node_ready and on_wavelink_track_start in its docs.

SonoLink dispatches events through the underlying Discord client using the sonolink_ prefix. The available events are:

  • on_sonolink_node_ready() — a node has connected and is ready to use.

  • on_sonolink_node_close() — a node connection was closed.

  • on_sonolink_player_update() — periodic position and state sync from the node.

  • on_sonolink_track_start() — a track has started playing.

  • on_sonolink_track_end() — a track finished, was stopped, or was replaced.

  • on_sonolink_track_exception() — a track encountered a playback error.

  • on_sonolink_track_stuck() — a track stalled and could not continue.

  • on_sonolink_unknown_event() — an unrecognized event type was received from the node.

When migrating, keep playback flow explicit in commands and services first, then reintroduce event-driven logic where still needed.

Autoplay¶

Wavelink exposes an auto_queue concept in its public docs. SonoLink’s autoplay is configured through sonolink.models.AutoPlaySettings at player creation time and toggled via sonolink.Player.autoplay, which accepts an sonolink.AutoPlayMode value:

  • sonolink.AutoPlayMode.DISABLED — autoplay is completely disabled. The player stops when the queue empties.

  • sonolink.AutoPlayMode.PARTIAL — SonoLink manages progression autonomously but does not fill the queue with recommended tracks.

  • sonolink.AutoPlayMode.ENABLED — when the queue empties, SonoLink discovers related tracks and fills the queue automatically. Tracks added to the standard queue are treated as priority.

The search provider used for discovery is configured via sonolink.SearchProvider in sonolink.models.AutoPlaySettings:

  • sonolink.SearchProvider.YOUTUBE — YouTube Radio mix based on the track identifier.

  • sonolink.SearchProvider.SPOTIFY — Spotify recommendations based on the track identifier.

  • sonolink.SearchProvider.DEEZER — Deezer track or artist radio based on the identifier.

Warning

Autoplay uses the track history as its seed. Ensure sonolink.models.HistorySettings has history enabled, otherwise autoplay will have no reference track to discover from.

State helpers¶

Wavelink exposes player.playing and similar helpers. SonoLink does not have a playing property. The public player state is:

  • sonolink.Player.current — the track currently playing, or None.

  • sonolink.Player.paused — whether the player is paused.

  • sonolink.Player.position — the current playback position in milliseconds.

  • sonolink.Player.volume — the current volume, between 0 and 1000.

  • sonolink.Player.queue — the sonolink.Queue holding upcoming and historical tracks.

  • sonolink.Player.autoplay — the current sonolink.AutoPlayMode for this player.

Useful references¶

  • Wavelink repository

  • Wavelink migrating guide

  • Wavelink API reference

Next
Working With Players
Previous
Lavalink Setup
Copyright © 2026, vmphase, Soheab, DA-344
Made with Sphinx and @pradyunsg's Furo
On this page
  • Migrating From Wavelink
    • What stays familiar
    • What changes
    • Concept mapping
    • Connection lifecycle
    • Settings
    • Searching
    • Players and voice connection
    • Playback flow
    • Filters
    • Events
    • Autoplay
    • State helpers
    • Useful references