3

这是我在此的头一篇博文。我目前正在 Apache-Karaf 3.0.0 上的 Scala 中开发一个简单的 http 音频 servlet。我正在将它部署为一些捆绑包中的功能,这些捆绑包是我使用 maven 项目构建的。我正在使用“javax.sound.sampled”库来获取音频,并且正在使用“java.io.File”从 AudioSystem 加载文件。

    val file = new File("audioFile.wav")
    val audioStream = AudioSystem.getAudioInputStream(file)

这显然不是真正的代码,因为我已经去掉了所有琐碎的部分。但这就是在“getAudioInputStream”调用中失败的地方。

当我将此代码部署到 Karaf 时,它会因“UnsupportedAudioFileException”而失败。该文件确实存在,并且是可读的,我已经验证了这一点。另外,我已确保此代码可以在以下情况下运行。- Scala 2.10.2、2.10.3 - Java 1.7.0_45(这与我的 Karaf 程序使用的 JRE 相同) - SBT 0.12.4(使用不同的 Scala 版本)

唯一失败的地方是当我将它部署到 Karaf 时。我不知道 Karaf 是否取消了一些随机音频支持,或者发生了什么,因为这在通过 SBT 或使用 Scala 命令行部署时可以正常工作。我也研究了替代库,但无济于事。大多数其他解决方案似乎都是基于通过声音驱动程序实际播放音频,这对我来说毫无用处。我需要实际的字节数据。

另外,请记住,仅发送文件对我来说也是无用的。另一个要求是我需要能够将多个音频文件合并到一个无缝音频流中。我已经完成了这项工作,我只需要将它移植到 OSGi,由于某种原因,我现在遇到了这个错误。我不知道 Karaf 是否与它有关,或者我通过 Maven 项目构建它是否破坏了某些东西。我环顾四周,发现问题可能出在哪里的提示很少。

我使用的音频文件是波形音频。8,000 采样率,每个采样 16 位。我不认为这实际上会有所作为,但我不是音频格式方面的专家。

我的 pom.xml 依赖项如下。我使用的唯一插件是 Scala 编译器,当然我的根 pom.xml 使用的是 org.apache.felix maven-bundle-plugin。这里真的没有太多的魔法,但谜团仍然存在。

    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>2.10.3</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>

任何线索将不胜感激,谢谢。

4

2 回答 2

3

我认为 AudioSystem 还没有完全准备好 OSGi。这是我在 Aries Spy Fly 文档中发现的。不知道你必须做什么才能让它工作,但这可能会有所帮助。

https://aries.apache.org/modules/spi-fly.html

特别案例

SPI Fly 可用于大多数使用 TCCL 模式获取实现的 SPI 提供程序/查找系统。但在某些情况下,需要进行一些特殊处理。当 API 本身与 META-INF/services 中的资源名称不匹配时,通常需要这种特殊处理,java.util.ServiceLoader 就是这种情况,但是 SPI-Fly 内置了 ServiceLoader 知识。下面列出了需要特殊处理的已知 API:

javax.sound.sampled.AudioSystem:这个类使用了 sun.misc.Service(通过 com.sun.media.sound.JDK13Services),它是 java.util.ServiceLoader 的前身。SPI Fly 中的 sun.misc.Service 没有特殊处理(还),但 AudioSystem.getAudioInputStream() API 可以通过在提供程序包中明确列出来使其工作(包含相关 META-INF/服务资源): SPI-Provider: javax.sound.sampled.AudioSystem 在消费者端你可以使用 SPI-Consumer: javax.sound.sampled.AudioSystem#getAudioInputStream

于 2014-04-09T22:34:14.150 回答
1

Christian 的回答是正确的,但我想提供指向spifly文档页面的更新链接。具体来说:

Java 的 java.util.ServiceLoader.load()、sun.misc.Service.providers() 等其他类似方法以及 FactoryFinder.find() 等其他静态查找方法尝试通过查找来定位“服务”实现线程上下文类加载器 (TCCL) 可见的所有 jar 的 META-INF/services 目录中的资源。

在 OSGi 中使用上述机制时存在许多问题:

  1. 线程上下文类加载器通常不在 OSGi 上下文中定义。它可以并且必须由调用者设置,而 OSGi 通常不能强制执行。
  2. 一个包不能 Import-Package META-INF/services,因为可能有许多包将包含这个伪包,并且 OSGi 框架只会将单个导出器绑定到给定包的导入器。
  3. 实例化 SPI 提供程序通常需要访问内部实现类,通过导出这些类,实现包会破坏其封装。
  4. 即使导出了一个实现类,在消费者捆绑包中导入这个类也会将其绑定到提供的具体实现包,这违反了松散耦合的原则。
  5. 捆绑包具有动态生命周期,这意味着在更新或卸载捆绑包时提供的服务可能会消失。java.util.ServiceLoader API 不提供将此类事件通知服务使用者的机制。

SPI Fly 项目使得在 OSGi 下使用使用 ServiceLoader.load() 和类似机制的现有代码成为可能。


请注意,截至 2016 年 5 月 20 日,新版本的com.googlecode.soundlibs工件已上传到 maven 中央存储库。这些新版本的工件是正确的 OSGi 包。这将帮助需要在 OSGi 容器中使用 Java Sound API 的每个人

在 github 上创建了一个简单的示例项目,演示了如何使用 Java Sound API 在 OSGi 容器中播放 MP3 文件。签出分支static-weavingdynamic-weaving查看相应的解决方案。

于 2016-06-01T06:41:46.980 回答