Skip to main content

Lyra

PyPI downloads Python License

A modern Lavalink v4 and NodeLink v3 wrapper supporting both Py-cord and Discord.py, based on the excellent Pomice library by cloudwithax.

Quick Links

What's New in Lyra

Lyra is a complete refactor of Pomice for Lavalink v4.X or NodeLink v3.X, bringing significant improvements:

  • Full Lavalink v4 and NodeLink v3 REST API support
  • Server-side plugin integration (LavaSrc, YouTube plugin, etc.)
  • Simplified setup - No more API credentials needed in client
  • Better error handling and plugin support
  • Removed deprecated modules (client-side Spotify/Apple Music parsing)
  • Optimized for Py-cord and Discord.py
  • Improved documentation and examples

Key Differences from Pomice

Feature Pomice (v2.x) Lyra (v2.x)
Lavalink Support v3.x & v4.x v4.x
Nodelink Support Unknown v3.x
Discord Library discord.py py-cord or discord.py
Spotify Support Client-side API Server plugin
Apple Music Support Client-side API Server plugin
Setup Complexity API keys required Plugin configuration only
Architecture Mixed client/server Pure server-side

Quick Start

Installation

pip install lava-lyra

Lyra doesn't bundle a Discord library by default — install it as an extra alongside Lyra, depending on which one you use:

pip install lava-lyra[py-cord]
# or
pip install lava-lyra[discord.py]

For faster networking (aiohttp speedups, aiodns, orjson), install the speed extra:

pip install lava-lyra[speed]

Basic Usage

Py-cord Example

import discord
import lava_lyra


class Bot(discord.Bot):
    def __init__(self):
        super().__init__(intents=discord.Intents.default())
        self.node = None

    async def on_ready(self):
        print(f"Logged in as {self.user}")

        # Create Lavalink nodes - much simpler than before!
        node = await lava_lyra.NodePool.create_node(
            bot=self,
            host="localhost",
            port=2333,
            password="youshallnotpass",
            identifier="MAIN",
            lyrics=False,
            search=True,  # Enable LavaSearch plugin support
            fallback=True,
        )
        print(f"Created node: {node.identifier}")


bot = Bot()
bot.run("your_bot_token")

Discord.py Example

import discord
from discord.ext import commands
import lava_lyra


class Bot(commands.Bot):
    def __init__(self):
        super().__init__(intents=discord.Intents.default(), command_prefix="!")
        self.node = None

    async def on_ready(self):
        print(f"Logged in as {self.user}")

        # Create Lavalink nodes - much simpler than before!
        node = await lava_lyra.NodePool.create_node(
            bot=self,
            host="localhost",
            port=2333,
            password="youshallnotpass",
            identifier="MAIN",
            lyrics=False,
            search=True,  # Enable LavaSearch plugin support
            fallback=True,
        )
        print(f"Created node: {node.identifier}")


bot = Bot()
bot.run("your_bot_token")

Playing Music

Py-cord Example

@bot.slash_command(description="Play music")
async def play(ctx, query: str):
    # Connect to voice channel
    if not ctx.author.voice:
        return await ctx.respond("You need to be in a voice channel!")

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

    # Search for tracks (supports Spotify, YouTube, Apple Music via plugins!)
    results = await player.get_tracks(query)

    if not results:
        return await ctx.respond("No tracks found!")

    # Play the track
    track = results[0]
    await player.play(track)
    await ctx.respond(f"Now playing: **{track.title}**")

Discord.py Example

@bot.tree.command(description="Play music")
async def play(interaction, query: str):
    # Connect to voice channel
    if not interaction.user.voice:
        return await interaction.response.send_message("You need to be in a voice channel!")

    player = await interaction.user.voice.channel.connect(cls=lava_lyra.Player)

    # Search for tracks (supports Spotify, YouTube, Apple Music via plugins!)
    results = await player.get_tracks(query)

    if not results:
        return await interaction.response.send_message("No tracks found!")

    # Play the track
    track = results[0]
    await player.play(track)
    await interaction.response.send_message(f"Now playing: **{track.title}**")

Advanced Search with LavaSearch

LavaSearch plugin provides advanced search capabilities across tracks, albums, artists, playlists, and text suggestions.

Important: You must enable LavaSearch when creating the node by setting search=True:

node = await lava_lyra.NodePool.create_node(
    bot=bot,
    host="localhost",
    port=2333,
    password="youshallnotpass",
    identifier="MAIN",
    search=True,  # Enable LavaSearch support
)

Py-cord Example

@bot.slash_command(description="Search for music")
async def search(ctx, query: str, platform: str = "youtube"):
    # Get the node
    node = lava_lyra.NodePool.get_node()

    # Map platform to search type
    search_types = {
        "youtube": lava_lyra.SearchType.ytsearch,
        "spotify": lava_lyra.SearchType.spsearch,
        "soundcloud": lava_lyra.SearchType.scsearch,
        "apple_music": lava_lyra.SearchType.amsearch,
    }

    # Search for tracks, albums, artists, playlists, and text
    result = await node.load_search(
        query=query,
        types=[
            lava_lyra.LavaSearchType.TRACK,
            lava_lyra.LavaSearchType.ALBUM,
            lava_lyra.LavaSearchType.ARTIST,
            lava_lyra.LavaSearchType.PLAYLIST,
            lava_lyra.LavaSearchType.TEXT,
        ],
        search_type=search_types.get(platform, lava_lyra.SearchType.ytsearch),
        ctx=ctx,
    )

    if not result:
        return await ctx.respond("No results found!")

    # Display results
    response = [f"**Search results for '{query}' on {platform}:**\n"]

    if result.tracks:
        response.append(f"**Tracks ({len(result.tracks)}):**")
        for track in result.tracks[:3]:  # Show first 3
            response.append(f"  - {track.title} by {track.author}")

    if result.albums:
        response.append(f"\n**Albums ({len(result.albums)}):**")
        for album in result.albums[:3]:
            response.append(f"  - {album.name}")

    if result.artists:
        response.append(f"\n**Artists ({len(result.artists)}):**")
        for artist in result.artists[:3]:
            response.append(f"  - {artist.name}")

    if result.playlists:
        response.append(f"\n**Playlists ({len(result.playlists)}):**")
        for playlist in result.playlists[:3]:
            response.append(f"  - {playlist.name}")

    if result.texts:
        response.append(f"\n**Suggestions:**")
        for text in result.texts[:5]:
            response.append(f"  - {text.text}")

    await ctx.respond("\n".join(response))

Discord.py Example

@bot.tree.command(description="Search for music")
async def search(interaction, query: str, platform: str = "youtube"):
    # Get the node
    node = lava_lyra.NodePool.get_node()

    # Map platform to search type
    search_types = {
        "youtube": lava_lyra.SearchType.ytsearch,
        "spotify": lava_lyra.SearchType.spsearch,
        "soundcloud": lava_lyra.SearchType.scsearch,
        "apple_music": lava_lyra.SearchType.amsearch,
    }

    # Search for tracks, albums, artists, playlists, and text
    result = await node.load_search(
        query=query,
        types=[
            lava_lyra.LavaSearchType.TRACK,
            lava_lyra.LavaSearchType.ALBUM,
            lava_lyra.LavaSearchType.ARTIST,
            lava_lyra.LavaSearchType.PLAYLIST,
            lava_lyra.LavaSearchType.TEXT,
        ],
        search_type=search_types.get(platform, lava_lyra.SearchType.ytsearch),
    )

    if not result:
        return await interaction.response.send_message("No results found!")

    # Display results
    response = [f"**Search results for '{query}' on {platform}:**\n"]

    if result.tracks:
        response.append(f"**Tracks ({len(result.tracks)}):**")
        for track in result.tracks[:3]:  # Show first 3
            response.append(f"  - {track.title} by {track.author}")

    if result.albums:
        response.append(f"\n**Albums ({len(result.albums)}):**")
        for album in result.albums[:3]:
            response.append(f"  - {album.name}")

    if result.artists:
        response.append(f"\n**Artists ({len(result.artists)}):**")
        for artist in result.artists[:3]:
            response.append(f"  - {artist.name}")

    if result.playlists:
        response.append(f"\n**Playlists ({len(result.playlists)}):**")
        for playlist in result.playlists[:3]:
            response.append(f"  - {playlist.name}")

    if result.texts:
        response.append(f"\n**Suggestions:**")
        for text in result.texts[:5]:
            response.append(f"  - {text.text}")

    await interaction.response.send_message("\n".join(response))

Note: The LavaSearch plugin must be installed on your Lavalink server for this feature to work. See the server setup section below.

Lavalink v4 Server Setup

Lyra requires a Lavalink v4 server with plugins. Here's a basic application.yml:

server:
  port: 2333
  address: 127.0.0.1

lavalink:
  plugins:
    # Required for YouTube support
    - dependency: "dev.lavalink.youtube:youtube-plugin:x.y.z"
      repository: "https://maven.lavalink.dev/releases"

    # Required for Spotify, Apple Music, Deezer, etc.
    - dependency: "com.github.topi314.lavasrc:lavasrc-plugin:x.y.z"
      repository: "https://maven.lavalink.dev/releases"

    # Optional: LavaSearch for advanced search functionality
    - dependency: "com.github.topi314.lavasearch:lavasearch-plugin:x.y.z"
      repository: "https://maven.lavalink.dev/releases"

  server:
    password: "youshallnotpass"

plugins:
  youtube:
    enabled: true
    allowSearch: true

  lavasrc:
    sources:
      spotify: true
      applemusic: true
      deezer: true

    spotify:
      clientId: "your_spotify_client_id"
      clientSecret: "your_spotify_client_secret"
      countryCode: "US"

Replace x.y.z with the latest version:

Supported Platforms

All platforms are now supported via Lavalink server plugins:

  • YouTube - via YouTube plugin
  • Spotify - via LavaSrc plugin
  • Apple Music - via LavaSrc plugin
  • Bilibili - via Lavabili plugin
  • SoundCloud - built-in Lavalink
  • And many more via community plugins!

LavaSearch Plugin Support

Lyra now includes full support for the LavaSearch plugin, which provides advanced search capabilities:

Features

  • Multi-type Search: Search for tracks, albums, artists, playlists, and text suggestions in a single query
  • Rich Results: Get comprehensive search results with detailed metadata
  • Plugin Integration: Works seamlessly with LavaSrc and other Lavalink plugins

Installation

Add LavaSearch to your Lavalink server's application.yml:

lavalink:
  plugins:
    - dependency: "com.github.topi314.lavasearch:lavasearch-plugin:x.y.z"
      repository: "https://maven.lavalink.dev/releases"

Replace x.y.z with the latest version.

Example:

# Search YouTube for everything
result = await node.load_search(
    query="architects animals",
    types=[
        lava_lyra.LavaSearchType.TRACK,
        lava_lyra.LavaSearchType.ALBUM,
        lava_lyra.LavaSearchType.ARTIST,
        lava_lyra.LavaSearchType.PLAYLIST,
        lava_lyra.LavaSearchType.TEXT,
    ],
    search_type=lava_lyra.SearchType.ytsearch,
)

# Search Spotify for tracks and artists
result = await node.load_search(
    query="metallica",
    types=[lava_lyra.LavaSearchType.TRACK, lava_lyra.LavaSearchType.ARTIST],
    search_type=lava_lyra.SearchType.spsearch,
)

# Search Apple Music for albums
result = await node.load_search(
    query="taylor swift",
    types=[lava_lyra.LavaSearchType.ALBUM],
    search_type=lava_lyra.SearchType.amsearch,
)

License and Credits

License

This project is licensed under the GPL-3.0 License - see the LICENSE file for details.

Credits and Attribution

Lyra is based on the excellent Pomice library:

We extend our heartfelt thanks to cloudwithax and all Pomice contributors for creating the solid foundation that made Lyra possible. This project builds upon their excellent work to provide Lavalink v4 compatibility and modern server-side plugin support.

Key Contributors

  • cloudwithax - Original Pomice library creator
  • ParrotXray - Lavalink v4 refactoring and Lyra development
  • GDjkhp - Fixes and improvements to issue handling
  • Akinori107 - Fixes and improvements to issue handling
  • Community contributors - Bug reports, features, and improvements

Links

Star History

If you find Lyra useful, please consider giving it a star!


Made with love for the Discord music bot community

Metadata

Release files for lava-lyra 2.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lava-lyra 2.2.4
File Size Uploaded Provenance Actions
lava_lyra-2.2.4.tar.gz 68.3 kB With provenance Details for lava_lyra-2.2.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for lava-lyra 2.2.4
File Interpreter ABI Platform Actions
lava_lyra-2.2.4-py3-none-any.whl Python 3 none any Details for lava_lyra-2.2.4-py3-none-any.whl

Total release size: 137.7 kB

Release files / lava_lyra-2.2.4.tar.gz

Download URL lava_lyra-2.2.4.tar.gz
Size 68.3 kB
Tags Source
SHA-256 checksum
How to use checksums
37ec1104145fe480ccd3229044f9b3639699d107de5c4abfbec3867988610b0c
BLAKE2b-256 checksum
How to use checksums
cdad63c11393dfceb302e984bebfa481530e5dd17eb1fe4ca898882aa53237bc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 25, 2026.

Transparency log

Release files / lava_lyra-2.2.4-py3-none-any.whl

Download URL lava_lyra-2.2.4-py3-none-any.whl
Size 69.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bfea43a8d648879a32fa448d2ced162684dd82e8e5127625f544fb12c962b4e4
BLAKE2b-256 checksum
How to use checksums
6e0abe9b9fcf7ed7ae3afcf0864637f906964447e1a5c35cf557a6dffec63853
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 25, 2026.

Transparency log

Security for lava-lyra 2.2.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for lava_lyra-2.2.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.2.4 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page