提问人:kofiy 提问时间:7/21/2023 最后编辑:kofiy 更新时间:7/21/2023 访问量:103
播放音频的 JavaFX 问题:不支持的协议“文件”
JavaFX problem with playing audio: Unsupported protocol "file"
问:
我正在尝试使用javafx.scene.media.AudioClip播放.jar文件中包含的音频,但是我经常遇到此错误:
Exception in thread "main" java.lang.UnsupportedOperationException: Unsupported protocol "file"
at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:241)
at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.<init>(NativeMediaAudioClip.java:53)
at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.load(NativeMediaAudioClip.java:63)
at com.sun.media.jfxmediaimpl.AudioClipProvider.load(AudioClipProvider.java:66)
at com.sun.media.jfxmedia.AudioClip.load(AudioClip.java:135)
at javafx.scene.media.AudioClip.<init>(AudioClip.java:83)
at main.Main.main(Main.java:77)
我尽可能地简化了我的代码,省略了抽象和其他方法,以确保错误实际上存在于 AudioClip 中:
package main;
import javafx.scene.media.AudioClip;
public class Main {
public static void main(String[] args) {
AudioClip clip = new AudioClip(Main.class.getResource("/sound/ambience/testSound.mp3").toExternalForm());
clip.play();
}
}
(我也尝试使用.toString()而不是toExternalForm())
我确保声音文件实际上包含在正确路径的 .jar 中。例如,这种通过 JavaX AudioInputStream 和 Clip 播放音频的方式就可以正常工作:
public static void main(String[] args) throws LineUnavailableException, IOException, UnsupportedAudioFileException, InterruptedException {
AudioInputStream ais = AudioSystem.getAudioInputStream(Main.class.getResource("/sound/ambience/randomScare.wav"));
Clip clip = AudioSystem.getClip();
clip.open(ais);
ais.close();
clip.start();
Thread.sleep()
}
(但我不能在最终产品中使用它,因为它仅支持未压缩的 .wav 格式)
我不知道是什么原因导致了这个问题,因为即使是官方的 javadoc 也指出:
source
- 要从中加载音频剪辑的 URL 字符串。这可以是 HTTP、文件或 jar 源。
一些可能有助于找到解决方案的更多信息:
我正在使用 maven 中央存储库中的版本(我也尝试切换回版本):org.openjfx:javafx-media
21-ea+24
20.0.1
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>21-ea+24</version>
</dependency>
Maven 项目是使用 java 版本 1.17 设置的:
<properties>
<maven.compiler.source>1.17</maven.compiler.source>
<maven.compiler.target>1.17</maven.compiler.target>
<exec.mainClass>main.Main</exec.mainClass>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
我在 Windows 18 上使用 Zulu 10 () 运行它 (Zulu18.32+13-CA (build 18.0.2.1+1)
Build 19044
)
我将不胜感激任何帮助(并希望我已经提供了所有需要的信息)。
更新:我尝试使用 github 工作区运行 .jar 构建(该 .jar 对我的朋友来说效果很好),并出现不同的错误:
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: no glib-lite in java.library.path: C:\Program Files\Zulu\zulu-18\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\Zulu\zulu-18\bin\;C:\Program Files\Zulu\zulu-19\bin\;C:\ProgramData\Oracle\Java\javapath;C:\Program Files\Common Files\Oracle\Java\javapath;C:\ProgramData\Oracle\Java\jdk-16.0.1;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\Common Files\Autodesk Shared\;C:\Program Files\dotnet\;C:\Program Files\spwn\;C:\Program Files\Kotlin\kotlinc_1_6_10;C:\Program Files\Kotlin\kotlinc_1_6_10\bin;C:\Program Files\Kotlin\konaco_1_6_10;C:\Program Files\Kotlin\konaco_1_6_10\bin;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\ffmpeg\bin;C:\Program Files\Git\cmd;C:\Program Files\PuTTY\;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310\Scripts\;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310\;C:\Users\Kofiy\AppData\Local\Microsoft\WindowsApps;C:\jdk-16.0.1\bin;C:\jdk-16.0.1\bin\;C:\jdk-16.0.1\bin\javac.exe;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.1.2\bin;C:\Users\Kofiy\AppData\Local\GitHubDesktop\bin;C:\Users\Kofiy\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.2\bin;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310\Scripts;C:\Users\Kofiy\.dotnet\tools;.
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2434)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:848)
at java.base/java.lang.System.loadLibrary(System.java:2015)
at com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:168)
at com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:56)
at com.sun.media.jfxmediaimpl.NativeMediaManager.lambda$new$0(NativeMediaManager.java:111)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)
at com.sun.media.jfxmediaimpl.NativeMediaManager.<init>(NativeMediaManager.java:108)
at com.sun.media.jfxmediaimpl.NativeMediaManager$NativeMediaManagerInitializer.<clinit>(NativeMediaManager.java:78)
at com.sun.media.jfxmediaimpl.NativeMediaManager.getDefaultInstance(NativeMediaManager.java:90)
at com.sun.media.jfxmedia.MediaManager.canPlayProtocol(MediaManager.java:78)
at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:240)
at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.<init>(NativeMediaAudioClip.java:53)
at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.load(NativeMediaAudioClip.java:63)
at com.sun.media.jfxmediaimpl.AudioClipProvider.load(AudioClipProvider.java:66)
at com.sun.media.jfxmedia.AudioClip.load(AudioClip.java:135)
at javafx.scene.media.AudioClip.<init>(AudioClip.java:83)
at main.Sound.playMP3(Sound.java:222)
at main.GamePanel.startGame(GamePanel.java:1624)
at main.KeyHandler.keyPressed(KeyHandler.java:126)
at java.desktop/java.awt.Component.processKeyEvent(Component.java:6574)
at java.desktop/javax.swing.JComponent.processKeyEvent(JComponent.java:2905)
at java.desktop/java.awt.Component.processEvent(Component.java:6393)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4991)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4823)
at java.desktop/java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1952)
at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:883)
at java.desktop/java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1146)
at java.desktop/java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:1020)
at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:848)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4823)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
(((现在在 AWT-EventQueue-0 中出现错误,因为它是项目的完整版本,而不是我之前编写的简化代码)))
我还尝试通过双击运行 .jar,通过 IntelJ IDEA 在我的系统上构建的 .jar 和在 GitHub 工作区上构建的 .jar 都显示此错误:
附言:每当我双击任何 .jar 时,实际上都会出现这个 JNI 视觉错误,这也很奇怪 PS 2:JNI 视觉错误是因为我搞砸了,并且将 Java 1.8 作为默认 JRE
所以它实际上看起来像是我的安装问题,所以我将尝试重新安装JDK,验证系统文件等。
答:
这不是一个答案,但我把它放在那里是为了向你展示我会发生什么。在这两种情况下,都会播放声音,我使用 your 打印到 stdout。从 jar 运行它时:toExternalForm
goose@t410:/tmp/sound$ java -cp /tmp/sound/target/sound-1.0-SNAPSHOT.jar fx.sound.App
jar:file:/tmp/sound/target/sound-1.0-SNAPSHOT.jar!/sound/ambience/testSound.mp3
然后使用 Maven:
goose@t410:/tmp/sound$ mvnt javafx:run
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< com.technojeeves:sound >-----------------------
[INFO] Building sound 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> javafx-maven-plugin:0.0.6:run (default-cli) > process-classes @ sound >>>
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ sound ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ sound ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< javafx-maven-plugin:0.0.6:run (default-cli) < process-classes @ sound <<<
[INFO]
[INFO]
[INFO] --- javafx-maven-plugin:0.0.6:run (default-cli) @ sound ---
[INFO] Toolchain in javafx-maven-plugin null
[WARNING] Module name not found in <mainClass>. Module name will be assumed from module-info.java
file:/tmp/sound/target/classes/sound/ambience/testSound.mp3
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.320 s
[INFO] Finished at: 2023-07-20T23:13:32+01:00
[INFO] ------------------------------------------------------------------------
goose@t410:/tmp/sound$
用于运行剪辑的代码:
package main;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.media.AudioClip;
public class Main extends Application {
@Override
public void start(Stage stage) {
AudioClip clip = new AudioClip(Main.class.getResource("/sound/ambience/testSound.mp3").toExternalForm());
System.out.println(Main.class.getResource("/sound/ambience/testSound.mp3").toExternalForm());
clip.play();
//Platform.exit();
}
public static void main(String[] args) {
launch();
}
}
评论
jlink
jrt:/…
jrt:/
方案在“JEP 220:模块化运行时映像”下的“用于命名存储模块、类和资源的新 URI 方案”一节中进行了讨论。
jar:file:/C:/Users/Kofiy/test.jar!/sound/ambience/testSound.mp3
最终,问题实际上是 JavaFX 没有被初始化。
作为一个简单的测试解决方法,我创建了非常简单的 JavaFX 应用程序,它只启动实际的 JavaX 应用程序。
(尽管将来我可能会重写一大段代码以避免这种非常糟糕的解决方法。(但至少它现在有效......
评论
AudioClip
Thread.sleep
AudioClip
AWT-EventQueue-0
AudioClip