Skip to content
This repository has been archived by the owner on Oct 24, 2020. It is now read-only.
/ Magma Public archive

A voice only API for Discord, focused on delivering music at scale.

License

Notifications You must be signed in to change notification settings

schnapster/Magma

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Archived

This library has been superseded by koe, please check it out for your Discord audio needs. koe has multiple advantages over Magma:

  • not built around inherited convoluted existing APIs
  • less complicated, therefore easier to maintain and contribute to

My main take-away from this library is to stay far away from reactive libraries and paradigms as possible. The added complexity is not worth the downsides, especially when alternatives are possible to achieve similar performance goals.

Magma

Release Build Status Master Branch License SonarCloud

A voice only API for Discord, focused on delivering music at scale.

Lava? Magma?

Notable features:

  • Event based and non-blocking at its core

Not supported:

  • Audio Receiving

Magma is a heavily modified fork of JDA-Audio (Apache 2.0)

Big shout-out to the to the original authors and maintainers for doing great work!

Besides making use of most of the code for handling audio packets, Magma reuses some of JDAs APIs, namely:

  • IAudioSendSystem
  • IAudioSendFactory
  • IPacketProvider
  • AudioSendHandler

Magma does not ship any implementations for IAudioSendSystem and IAudioSendFactory. It is important that the implementation you choose will never call any method of the packet provider but IPacketProvider#getNextPacket, because none of the others are supported by Magma. Recommended implementations:

Only AudioSendHandlers that provide packets in the opus format are supported. Recommended providers:

Get started

Add Magma to your project

  • JitPack for builds straight from github code

Replace x.y.z in the snippets below with the desired version. Latest: Release

Gradle build.gradle
    repositories {
        maven { url 'https://jitpack.io' }
    }

    dependencies {
        compile group: 'space.npstr.magma', name: 'magma', version: 'x.y.z'
    }
Maven pom.xml
    <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>        
    </repositories>

    <dependency>
        <groupId>space.npstr.magma</groupId>
        <artifactId>magma</artifactId>
        <version>x.z.y</version>
    </dependency>

Sample code

Discord supports one single audio connection per user and guild (also called a "member"). This means, an audio connection is exactly identified by those two datapoints, and all of the methods of Magma require those to correctly identify the connection that you want to open/close/change something about.

DSL

Magma uses immutables.org to ensure type and parameter safety, both internally and in the Api you are going to use. Concretely, the Api makes use of immutable Member and ServerUpdate objects.

    Member member = MagmaMember.builder()
        .userId("...")
        .guildId("...")
        .build();
    
    ServerUpdate = MagmaServerUpdate.builder()
        .sessionId("...")
        .endpoint("...")
        .token("...")
        .build();
    

Api

Typical usage of the methods offered by the MagmaApi:

    IAudioSendFactory audioSendFactory = <your implementation here>;
    AudioSendHandler sendHandler = <your implementation here>;

    MagmaApi magmaApi = MagmaFactory.of(__ -> audioSendFactory);
    magmaApi.provideVoiceServerUpdate(member, serverUpdate);
    magmaApi.setSendHandler(member, sendHandler);


    // music plays, then later:

    magmaApi.setSendHandler(member, someOtherHandler);

    // other handler plays music / sounds


    // to clean up:

    magmaApi.removeSendHandler(member);
    magmaApi.closeConnection(member);

    // on shutting down

    magmaApi.shutdown();

    // Calling any other methods of a MagmaApi object after having called shutdown() 
    // will result in undefined behaviour. Do not do this, create a new MagmaApi instead.
    // Please note that you are strongly encouraged to use a single MagmaApi object throughout 
    // the lifecycle of your application.

None of those calls are blocking, as they are translated into events to be processed as soon as possible. Currently, there is no feedback as to when and how these are processed.

You can subscribe to a stream of MagmaEvents through MagmaApi#getEventStream:

    ...
        magmaApi.getEventStream()
                .subscribe(this::handleMagmaEvent);
    ...

    
    private void handleMagmaEvent(MagmaEvent magmaEvent) {
        if (magmaEvent instanceof space.npstr.magma.events.api.WebSocketClosed) {
            WebSocketClosed wsClosedEvent = (WebSocketClosed) magmaEvent;
            log.info("WS in guild {} closed with code {} and reason {}", wsClosedEvent.getMember().getGuildId(),
                    wsClosedEvent.getCloseCode(), wsClosedEvent.getReason());
        }
    }

Who is using this?

Check out these open-source projects for some more real world usage examples:

Alternatives

Magma might for various reasons not fit your needs. Don't worry, there are alternatives for sending voice to Discord:

Numbers

(last updated for 0.2.1)

Magma has been written with Lavalink in mind, numbers shown here compare vanilla Lavalink to a Magma-based branch.

Graphs by courtesy of FredBoat.

CPU Usage

Click me

CPU Usage

Threads

Click me

Threads

Garbage Collection

Click me

GC Time Spent
GC Runs

Memory

Click me

JVM Memory
Process Memory

Audio Frames

Click me

Audio Frames Lost

Debugging

Enabling TRACE/DEBUG logs can help with pinpointing and reporting issues. To get the most out of these log levels, make sure your chosen logger implementation and configuration prints additional MDC information. The MDC keys that Magma uses can be found in the MdcKeys class.

If you are running Magma in a Spring Boot application with logback as the logger implementation (Lavalink does this), adding these following lines to your Spring Application's application.yaml will show the MDC information:

logging:
  pattern:
    level: "[%mdc] %5p"
  level:
    space.npstr.magma: TRACE 

Dependencies:

About

A voice only API for Discord, focused on delivering music at scale.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages