You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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);
    }
}

问题原因

  1. 浏览器AudioContext交互限制:现代浏览器要求AudioContext必须由用户主动交互(如点击、触摸)触发,不能在页面加载时自动初始化播放,这是防止自动播放音频扰民的安全策略。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 05:22:53