基于TeaVM在Java中生成音频无输出问题求助
TeaVM编译后无法生成音频的问题修复
问题描述:已适配Java类并通过TeaVM编译成功,页面文本输出正常,但无法生成音频,相关代码如下:
package com.xyz; import org.teavm.jso.dom.html.HTMLDocument; import org.teavm.jso.webaudio.AudioContext; import org.teavm.jso.webaudio.OscillatorNode; public class Client { public static void main(String[] args) throws InterruptedException { var document = HTMLDocument.current(); var div = document.createElement("div"); div.appendChild(document.createTextNode("TeaVM generated element 3")); document.getBody().appendChild(div); var audioContext = AudioContext.create(); OscillatorNode oscillator = audioContext.createOscillator(); var g = audioContext.createGain(); oscillator.setType(OscillatorNode.TYPE_SINE); oscillator.connect(g); g.connect(audioContext.getDestination()); oscillator.start(0); Thread.sleep(10000); oscillator.stop(20000); Thread.sleep(10000); } }
问题原因
- 浏览器AudioContext交互限制:现代浏览器要求AudioContext必须由用户主动交互(如点击、触摸)触发,不能在页面加载时自动初始化播放,这是防止自动播放音频扰民的安全策略。
- Thread.sleep()不兼容Web环境:TeaVM编译后的Java Thread.sleep()不会真正阻塞JavaScript事件循环,会导致音频播放逻辑时序混乱,比如oscillator.stop的时机错误,甚至AudioContext状态异常。
修复后的代码
package com.xyz; import org.teavm.jso.dom.events.MouseEvent; import org.teavm.jso.dom.html.HTMLButtonElement; import org.teavm.jso.dom.html.HTMLDocument; import org.teavm.jso.webaudio.AudioContext; import org.teavm.jso.webaudio.OscillatorNode; import org.teavm.jso.Window; public class Client { public static void main(String[] args) { var document = HTMLDocument.current(); var div = document.createElement("div"); div.appendChild(document.createTextNode("TeaVM generated element 3")); document.getBody().appendChild(div); // 创建触发按钮 HTMLButtonElement playBtn = (HTMLButtonElement) document.createElement("button"); playBtn.setTextContent("播放音频"); playBtn.addEventListener("click", Client::playAudio); document.getBody().appendChild(playBtn); } private static void playAudio(MouseEvent event) { var audioContext = AudioContext.create(); OscillatorNode oscillator = audioContext.createOscillator(); var g = audioContext.createGain(); oscillator.setType(OscillatorNode.TYPE_SINE); oscillator.connect(g); g.connect(audioContext.getDestination()); oscillator.start(); // 使用定时器替代Thread.sleep() Window.current().setTimeout(() -> oscillator.stop(), 10000); Window.current().setTimeout(() -> audioContext.close(), 11000); } }
修改说明
- 新增了一个按钮,通过用户点击事件触发音频播放,满足浏览器的交互要求。
- 用Web环境的
setTimeout替代Java的Thread.sleep(),保证音频播放和停止的时序正确,同时不阻塞页面事件循环。 - 播放10秒后停止振荡器,11秒后关闭AudioContext,释放资源。
内容的提问来源于stack exchange,提问作者spl
相关产品推荐
相关产品推荐

