Index: applications/editors/josm/plugins/openjfx/build.xml
===================================================================
--- applications/editors/josm/plugins/openjfx/build.xml	(revision 34602)
+++ applications/editors/josm/plugins/openjfx/build.xml	(revision 34603)
@@ -4,5 +4,5 @@
     <property name="commit.message" value="Commit message"/>
     <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
-    <property name="plugin.main.version" value="14153"/>
+    <property name="plugin.main.version" value="14183"/>
 
 	<!-- Configure these properties (replace "..." accordingly).
Index: applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/OpenJfxPlugin.java
===================================================================
--- applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/OpenJfxPlugin.java	(revision 34602)
+++ applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/OpenJfxPlugin.java	(revision 34603)
@@ -2,6 +2,8 @@
 package org.openstreetmap.josm.plugins.openjfx;
 
+import org.openstreetmap.josm.io.audio.AudioPlayer;
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.openjfx.io.audio.JavaFxMediaPlayer;
 
 /**
@@ -16,4 +18,5 @@
     public OpenJfxPlugin(PluginInformation info) {
         super(info);
+        AudioPlayer.setSoundPlayerClass(JavaFxMediaPlayer.class);
     }
 }
Index: applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/io/audio/JavaFxMediaPlayer.java
===================================================================
--- applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/io/audio/JavaFxMediaPlayer.java	(revision 34603)
+++ applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/io/audio/JavaFxMediaPlayer.java	(revision 34603)
@@ -0,0 +1,125 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.openjfx.io.audio;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.concurrent.CountDownLatch;
+
+import org.openstreetmap.josm.io.audio.AudioException;
+import org.openstreetmap.josm.io.audio.AudioListener;
+import org.openstreetmap.josm.io.audio.AudioPlayer.Execute;
+import org.openstreetmap.josm.io.audio.AudioPlayer.State;
+import org.openstreetmap.josm.io.audio.SoundPlayer;
+import org.openstreetmap.josm.tools.JosmRuntimeException;
+import org.openstreetmap.josm.tools.ListenerList;
+
+import com.sun.javafx.application.PlatformImpl;
+
+import javafx.scene.media.Media;
+import javafx.scene.media.MediaException;
+import javafx.scene.media.MediaPlayer;
+import javafx.scene.media.MediaPlayer.Status;
+import javafx.util.Duration;
+
+/**
+ * Default sound player based on the Java FX Media API.
+ * It supports the following audio codecs:<ul>
+ * <li>MP3</li>
+ * <li>AIFF containing uncompressed PCM</li>
+ * <li>WAV containing uncompressed PCM</li>
+ * <li>MPEG-4 multimedia container with Advanced Audio Coding (AAC) audio</li>
+ * </ul>
+ */
+public class JavaFxMediaPlayer implements SoundPlayer {
+
+    private final ListenerList<AudioListener> listeners = ListenerList.create();
+
+    private MediaPlayer mediaPlayer;
+
+    JavaFxMediaPlayer() {
+        try {
+            initFxPlatform();
+        } catch (InterruptedException e) {
+            throw new JosmRuntimeException(e);
+        }
+    }
+
+    /**
+     * Initializes the JavaFX platform runtime.
+     * @throws InterruptedException if the current thread is interrupted while waiting
+     */
+    public static void initFxPlatform() throws InterruptedException {
+        final CountDownLatch startupLatch = new CountDownLatch(1);
+
+        // Note, this method is called on the FX Application Thread
+        PlatformImpl.startup(startupLatch::countDown);
+
+        // Wait for FX platform to start
+        startupLatch.await();
+    }
+
+    @Override
+    public synchronized void play(Execute command, State stateChange, URL playingUrl) throws AudioException, IOException {
+        try {
+            final URL url = command.url();
+            if (playingUrl != url) {
+                if (mediaPlayer != null) {
+                    mediaPlayer.stop();
+                }
+                // Fail fast in case of invalid local URI (JavaFX Media locator retries 5 times with a 1 second delay)
+                if ("file".equals(url.getProtocol()) && !new File(url.toURI()).exists()) {
+                    throw new FileNotFoundException(url.toString());
+                }
+                mediaPlayer = new MediaPlayer(new Media(url.toString()));
+                mediaPlayer.setOnPlaying(() ->
+                    listeners.fireEvent(l -> l.playing(url))
+                );
+            }
+            mediaPlayer.setRate(command.speed());
+            if (Status.PLAYING == mediaPlayer.getStatus()) {
+                Duration seekTime = Duration.seconds(command.offset());
+                if (!seekTime.equals(mediaPlayer.getCurrentTime())) {
+                    mediaPlayer.seek(seekTime);
+                }
+            }
+            mediaPlayer.play();
+        } catch (MediaException | URISyntaxException e) {
+            throw new AudioException(e);
+        }
+    }
+
+    @Override
+    public synchronized void pause(Execute command, State stateChange, URL playingUrl) throws AudioException, IOException {
+        if (mediaPlayer != null) {
+            try {
+                mediaPlayer.pause();
+            } catch (MediaException e) {
+                throw new AudioException(e);
+            }
+        }
+    }
+
+    @Override
+    public boolean playing(Execute command) throws AudioException, IOException, InterruptedException {
+        // Not used: JavaFX handles the low-level audio playback
+        return false;
+    }
+
+    @Override
+    public synchronized double position() {
+        return mediaPlayer != null ? mediaPlayer.getCurrentTime().toSeconds() : -1;
+    }
+
+    @Override
+    public synchronized double speed() {
+        return mediaPlayer != null ? mediaPlayer.getCurrentRate() : -1;
+    }
+
+    @Override
+    public void addAudioListener(AudioListener listener) {
+        listeners.addWeakListener(listener);
+    }
+}
Index: applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/io/audio/package-info.java
===================================================================
--- applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/io/audio/package-info.java	(revision 34603)
+++ applications/editors/josm/plugins/openjfx/src/org/openstreetmap/josm/plugins/openjfx/io/audio/package-info.java	(revision 34603)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * Provides the classes for Audio mapping features requiring JavaFX.
+ */
+package org.openstreetmap.josm.plugins.openjfx.io.audio;
