2

I want to record audio in a Discord Voice Channel and save it to a file using a Discord Bot.

I receive the Audio every 20 milliseconds as an pcm-encoded byte[], that I want to save to a file. MP3 is prefered but I don't have problems with other file formats like ogg (It may be easier) too.

I am using JDA version 4.ALPHA.0_82 and I also included lavaplayer version 1.3.17 for other features. It would be helpful, if these libraries are anough, but it's no problem if I have to include more.

dan1st
  • 12,568
  • 8
  • 34
  • 67
  • 1
    I dump the PCM into a file and send it back through discord to hear it. Granted, the files are massive, but it works :^) Also note that JDA gives you PCM data, not opus (unless they changed something in v4) – Benjamin Urquhart May 06 '19 at 12:51
  • I thought of the same approach, isn't there an easy way to save it in an compressed audio format? – dan1st May 06 '19 at 13:14
  • 1
    I once got told to pipe it through ffmpeg. I'm assuming you want a cross-platform/self-contained solution though – Benjamin Urquhart May 06 '19 at 13:15

1 Answers1

2

This question explains how to convert pcm to wav. I copied the Discord audio into a List<byte[]> by overriding the Method AudioReceiveHandler#handleCombinedAudio:

private List<byte[]> rescievedBytes=new ArrayList<>();
@Override
public void handleCombinedAudio(CombinedAudio combinedAudio) {
    try {
        rescievedBytes.add(combinedAudio.getAudioData(VOLUME));
    }catch (OutOfMemoryError e) {
        //close connection
    }
}

After that, I copied the List into a byte[] and created the wav file.

try {
        int size=0;
        for (byte[] bs : rescievedBytes) {
            size+=bs.length;
        }
        byte[] decodedData=new byte[size];
        int i=0;
        for (byte[] bs : rescievedBytes) {
            for (int j = 0; j < bs.length; j++) {
                decodedData[i++]=bs[j];
            }
        }
        getWavFile(getNextFile(), decodedData);
    } catch (IOException|OutOfMemoryError e) {
        e.printStackTrace();
    }

private void getWavFile(File outFile, byte[] decodedData) throws IOException {
    AudioFormat format = new AudioFormat(8000, 16, 1, true, false);
    AudioSystem.write(new AudioInputStream(new ByteArrayInputStream(
            decodedData), format, decodedData.length), AudioFileFormat.Type.WAVE, outFile);
}

In case that the rescieved audio gets too big (OutOfMemoryError) the conversion is aborted.

dan1st
  • 12,568
  • 8
  • 34
  • 67
  • You forgot to increment i. – Gabor Szita Aug 23 '20 at 09:17
  • 1
    Why didn't you use the format provided by the [AudioReceiveHandler](https://github.com/DV8FromTheWorld/JDA/blob/ac3f1a78355bb3cb799dd91adb62432b1473978c/src/main/java/net/dv8tion/jda/api/audio/AudioReceiveHandler.java#L32)? – Minn Apr 09 '21 at 08:18