0

I have a Java method that loads chunked audio data for a podcast. From what I can tell, 2 or 3 users can access an audio (generally about 40MB) in the podcast and then my app runs out of memory and crashes (java.lang.OutOfMemoryError: null). I am using Java with the Play Framework.

@With(MP3Headers.class)
public static Result getAudioByChunk(Integer audioId) {
    try {
        final Audio requestedAudio = Audio.findById.byId(audioId);
        int songLength = Files.readAllBytes(Paths.get(requestedAudio.filePath)).length;

        final int begin, end;
        final boolean isRangeReq;
        response().setHeader("Accept-Ranges", "bytes");
        if (request().hasHeader("RANGE")) {
            isRangeReq = true;
            String[] range = request().getHeader("RANGE").split("=")[1].split("-");
            begin = Integer.parseInt(range[0]);
            if (range.length > 1) {
                end = Integer.parseInt(range[1]);
            } else {
                end = songLength - 1;
            }
            response().setHeader("Content-Range", String.format("bytes %d-%d/%d", begin, end, songLength));
        } else {
            isRangeReq = false;
            begin = 0;
            end = songLength - 1;
        }

        Chunks<byte[]> chunks = new ByteChunks() {
            public void onReady(Chunks.Out<byte[]> out) {
                try {
                    if (isRangeReq) {
                        out.write(Arrays.copyOfRange(Files.readAllBytes(Paths.get(requestedAudio.filePath)), begin, end));
                    } else {
                        out.write(Files.readAllBytes(Paths.get(requestedAudio.filePath)));
                    }
                } catch (IOException ioe) {
                } finally {
                    out.close();
                }
            }
        };
        response().setHeader("Content-Length", (end - begin + 1) + "");
        if (isRangeReq) {
            return status(206, chunks);
        } else {
            return status(200, chunks);
        }
    } catch (Exception e) {
        return ok();
    }
}

I have already tried increasing my JVM memory (I only have a gigabyte of total memory to work with on the server). Out of desperation I have tried nullifying 'chunks' and calling the garbage collector in a finally block after the return statements.

I think I am missing a command to release the memory after the chunks have been written to the Result, what exactly am I missing?

If more details are needed please let me know.

1 Answers1

1

You may need to use streaming mode instead of loading the entire audio into memory.

Take a look at this answer for help:

https://stackoverflow.com/a/32865159/5430900

Community
  • 1
  • 1
Prem
  • 157
  • 7
  • This worked, thanks! The only problem I'm running into now is that the stream has little blips and imperfections throughout the audio. Any thoughts on how to make the stream more smooth? – Jonathan Cameron Oct 28 '15 at 17:34