Skip to content

AudioStreamHandlerManager

tartaric_acid edited this page May 5, 2026 · 1 revision

AudioStreamHandlerManager

AudioStreamHandlerManager 用于管理音频流处理器。你可以通过实现 IAudioStreamHandler,接管某类 URL 的打开方式,并返回可被 Net Music 解码的 AudioInputStream。

适用场景

如果你的模组需要让 Net Music 播放以下类型的音频源,可以扩展这个 API:

  • 需要附加自定义 HTTP 头、Cookie 或签名参数的音频请求。
  • 需要先做跳转、鉴权或换源才能取得真实音频流的链接。
  • 特定平台或协议下的特殊直播流、分片流或私有流格式。

接口定义

管理器路径:src/main/java/com/github/tartaricacid/netmusic/client/api/AudioStreamHandlerManager.java

接口路径:src/main/java/com/github/tartaricacid/netmusic/client/api/IAudioStreamHandler.java

public interface IAudioStreamHandler {
    boolean canHandle(URL url);

    AudioInputStream handle(URL url) throws UnsupportedAudioFileException, IOException;

    default int getPriority() {
        return 0;
    }
}
方法 说明
canHandle(URL url) 判断当前处理器是否应接管该 URL。
handle(URL url) 建立连接并返回可正常解码的 AudioInputStream。
getPriority() 处理器优先级。数值越大,越早参与匹配。

注册方式

注册方式是直接调用管理器:

AudioStreamHandlerManager.registerHandler(new YourAudioStreamHandler());

这是一个纯客户端扩展点。推荐在客户端初始化阶段完成注册,并且必须早于 FMLLoadCompleteEvent。AudioStreamHandlerManager.init() 会在客户端加载完成阶段注册内置 Handler、排序并冻结列表,之后再调用 registerHandler(...) 会被拒绝并记录错误日志。

示例:

@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class YourClientEvents {
    @SubscribeEvent
    public static void onClientSetup(FMLClientSetupEvent event) {
        event.enqueueWork(() ->
                AudioStreamHandlerManager.registerHandler(new YourAudioStreamHandler()));
    }
}

示例:注入鉴权请求头

以下示例展示了如何接管特定域名的音频地址,并在请求时补充 Authorization 鉴权头:

public class ExampleProtectedHttpHandler implements IAudioStreamHandler {
    @Override
    public boolean canHandle(URL url) {
        return "https".equalsIgnoreCase(url.getProtocol())
               && "example.com".equalsIgnoreCase(url.getHost())
               && url.getPath().startsWith("/protected-audio/");
    }

    @Override
    public AudioInputStream handle(URL url) throws UnsupportedAudioFileException, IOException {
        URLConnection connection = url.openConnection();
        connection.setRequestProperty("Authorization", "Bearer <token>");
        connection.setRequestProperty("User-Agent", "Your Mod");

        BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
        return AudioSystem.getAudioInputStream(stream);
    }

    @Override
    public int getPriority() {
        return 50;
    }
}

优先级与匹配流程

播放音频时,Net Music 会按优先级从高到低遍历所有已注册 Handler。第一个 canHandle(url) 返回 true 的处理器会独占处理该 URL;如果都不匹配,则抛出 UnsupportedAudioFileException。

当前内置 Handler 优先级参考:

内置处理器 优先级 定位
CnrM3u8Handler 200 央广云听页面转 m3u8 广播流
M3u8Handler 100 通用 m3u8 音频流解析
NetEaseHttpHandler 10 网易云相关 HTTP 音源处理
LocalFileHandler 0 本地文件兜底
DirectHttpHandler 0 通用 HTTP/HTTPS 直链兜底

优先级建议:

  • 针对特定域名或特定协议的专用 Handler,应高于通用逻辑。
  • 通用兜底型 Handler 应尽量保持较低优先级,避免误抢更精确的处理器。

开发注意事项

  1. 该接口仅限客户端注册,服务端不要调用。
  2. canHandle(...) 应尽可能严格,避免误抢本应交给其他 Handler 的 URL。
  3. 如果无法处理某 URL,请在 canHandle(...) 直接返回 false,不要在 handle(...) 内做模糊兜底。
  4. 需要注入 Header、Cookie 等信息时,只在当前 Handler 自己创建的连接对象上操作,不要修改全局网络配置。
  5. handle(...) 返回的流必须能够被后续解码流程正常读取,否则会在播放阶段失败。