I’m working on a project that has to load a MP3 file and play it along with loaded images and videos. I stumped on the fact that OPENRNDR doesn’t handle MP3 files and came up with a workaround. I don’t think this is the ideal solution, but it works.
In build.gradle.kts
we should add:
plugins {
id("org.openjfx.javafxplugin") version "0.1.0"
}
javafx {
version = "22.0.1"
}
And here is the code for a simple program that plays the audio file. Note that as JavaFX doesn’t have native MP3 support, I’m using FFmpeg to convert the MP3 file to a WAV file and play it.
The program also checks if there is already a WAV file with the same name of the MP3 file. If there is, it plays the WAV file directly, without converting.
import org.openrndr.application
import javax.sound.sampled.*
import java.io.File
import java.io.IOException
import kotlin.concurrent.thread
class AudioPlayer(private val mp3FilePath: String) {
private var clip: Clip? = null
private var isPlaying = false
private val wavFilePath: String
init {
val mp3File = File(mp3FilePath)
wavFilePath = mp3File.parent + File.separator + mp3File.nameWithoutExtension + ".wav"
}
fun play() {
if (!isPlaying) {
thread {
try {
if (!File(wavFilePath).exists()) {
convertToWav()
}
val audioInputStream = AudioSystem.getAudioInputStream(File(wavFilePath))
clip = AudioSystem.getClip()
clip?.open(audioInputStream)
clip?.start()
isPlaying = true
println("Playing audio: $wavFilePath")
clip?.addLineListener { event ->
if (event.type == LineEvent.Type.STOP) {
isPlaying = false
clip?.close()
println("Audio playback finished")
}
}
} catch (e: Exception) {
println("Error playing audio: ${e.message}")
e.printStackTrace()
}
}
}
}
private fun convertToWav() {
try {
println("Converting MP3 to WAV...")
val process = ProcessBuilder("ffmpeg", "-i", mp3FilePath, wavFilePath)
.redirectErrorStream(true)
.start()
process.inputStream.bufferedReader().use { it.readText() }
process.waitFor()
println("Conversion completed: $wavFilePath")
} catch (e: IOException) {
println("Error converting file: ${e.message}")
e.printStackTrace()
}
}
fun stop() {
clip?.stop()
clip?.close()
isPlaying = false
println("Audio playback stopped")
}
}
fun main() = application {
var audioPlayer: AudioPlayer? = null
program {
extend {
if (audioPlayer == null) {
audioPlayer = AudioPlayer("C:\\videos\\godgangs\\godgangs.mp3")
audioPlayer?.play()
}
}
keyboard.keyDown.listen {
if (it.name == "q") {
audioPlayer?.stop()
application.exit()
}
}
}
}
It’s really simple and experimental but it can lead somewhere. Hope somebody finds it useful. Remember to replace the file paths!