Skip to content

jonas747/dca

Repository files navigation

dca Go report Build Status

dca is a audio file format that uses opus packets and json metadata.

This package implements a decoder, encoder and a helper streamer for dca v0 and v1.

Docs on GoDoc

There's also a standalone command you can use here

Usage

Encoding

// Encoding a file and saving it to disk
encodeSession := dca.EncodeFile("path/to/file.mp3", dca.StdEncodeOptions)
// Make sure everything is cleaned up, that for example the encoding process if any issues happened isnt lingering around
defer encodeSession.Cleanup()

output, err := os.Create("output.dca")
if err != nil {
    // Handle the error
}

io.Copy(output, encodeSession)

Decoding, the decoder automatically detects dca version aswell as if metadata was available

// inputReader is an io.Reader, like a file for example
decoder := dca.NewDecoder(inputReader)

for {
    frame, err := decoder.OpusFrame()
    if err != nil {
        if err != io.EOF {
            // Handle the error
        }
        
        break
    }
    
    // Do something with the frame, in this example were sending it to discord
    select{
        case voiceConnection.OpusSend <- frame:
        case <-time.After(time.Second):
            // We haven't been able to send a frame in a second, assume the connection is borked
            return
    }
}

Using the helper streamer, the streamer creates a pausable stream to Discord.

// Source is an OpusReader, both EncodeSession and decoder implements opusreader
done := make(chan error)
streamer := dca.NewStreamer(source, voiceConnection, done)
err := <- done
if err != nil && err != io.EOF {
    // Handle the error
}

Using this youtube-dl Go package, one can stream music to Discord from Youtube

// Change these accordingly
options := dca.StdEncodeOptions
options.RawOutput = true
options.Bitrate = 96
options.Application = "lowdelay"

videoInfo, err := ytdl.GetVideoInfo(videoURL)
if err != nil {
    // Handle the error
}

format := videoInfo.Formats.Extremes(ytdl.FormatAudioBitrateKey, true)[0]
downloadURL, err := videoInfo.GetDownloadURL(format)
if err != nil {
    // Handle the error
}

encodingSession, err := dca.EncodeFile(downloadURL.String(), options)
if err != nil {
    // Handle the error
}
defer encodingSession.Cleanup()
    
done := make(chan error)    
dca.NewStream(encodingSession, voiceConnection, done)
err := <- done
if err != nil && err != io.EOF {
    // Handle the error
}

Official Specifications