springboot 处理编码的格式为opus的音频数据解决方案【java8】

opus编码的格式概念:

Opus是一个有损声音编码的格式,由Xiph.Org基金会开发,之后由IETF(互联网工程任务组)进行标准化,目标是希望用单一格式包含声音和语音,取代Speex和Vorbis,且适用于网络上低延迟的即时声音传输,标准格式定义于RFC 6716文件。Opus格式是一个开放格式,使用上没有任何专利或限制。

Opus集成了两种声音编码的技术:以语音编码为导向的SILK和低延迟的CELT。Opus可以无缝调节高低比特率。在编码器内部它在较低比特率时使用线性预测编码在高比特率时候使用变换编码(在高低比特率交界处也使用两者结合的编码方式)。Opus具有非常低的算法延迟(默认为22.5 ms),非常适合用于低延迟语音通话的编码,像是网上上的即时声音流、即时同步声音旁白等等,此外Opus也可以透过降低编码码率,达成更低的算法延迟,最低可以到5 ms。在多个听觉盲测中,Opus都比MP3、AAC、HE-AAC等常见格式,有更低的延迟和更好的声音压缩率。

需求场景:

最近我在对接一个可以接收声音的 硬件设备,通信模式为 websocket。
通过测试 ,接收到的音频格式为 :opus 格式。
我接收到这个格式的 音频后,首先需要给这个格式的音频进行解码,然后得到PCM编码格式的数据。
解码后的 PCM 数据则是还原后的音频信号,是原始音频的近似表示,可以直接输出音频信号。

PCM解释:

PCM(脉冲编码调制,Pulse Code Modulation)编码是一种将模拟信号转换为数字信号的方法,广泛用于音频、视频和通信系统中。PCM编码的主要目的是将模拟信号的幅度表示为一系列的数字值,这样可以在数字系统中更容易地存储、处理和传输。
PCM编码的基本过程
采样:首先,将模拟信号按一定的时间间隔进行采样。每次采样得到的值称为“采样点”。
量化:将每个采样点的模拟信号值转换成最接近的数字值。量化的精度由量化位数(通常是8位、16位或更高)决定,位数越高,表示的数字精度越高,信号的失真越小。
编码:将量化后的数字信号进行二进制编码,即将每个采样点的数字值转化为二进制形式,形成一串二进制代码。
PCM的常见应用
音频:例如CD音质的音频数据就是使用PCM编码的,通常采用44.1kHz的采样率和16位的量化深度。
通信:PCM也用于电话通信和其他语音传输领域。
视频:PCM有时也用于视频信号的音频部分编码。

对于做网站开发的我,也是第一次处理关于音频的数据,这篇文章就把我遇到的一些问题做一个分享,希望能帮助看到这篇文章的你。
这个设备提供的代码是python版本的。
但是我是使用 java语言,springboot 框架 来处理数据的。

在调试的过程中 遇到了一个问题:opus格式的音频解码的问题?
对于python来说 这个语言 有现成的包 opuslib 还是比较好处理的

# Opus音频解码
import opuslib
import opuslib.api.encoder
import opuslib.api.decoderclass OpusDecoder():def __init__(self, samplerate: int, channels: int, seq_time: float) -> None:self.samplerate = samplerate# 创建解码器self.decoder = opuslib.Decoder(fs=self.samplerate, channels=channels)self.seq_length = int(seq_time*self.samplerate*2)def decode(self, input_bytes: bytes):# 直接解码opus数据dec_output = self.decoder.decode(bytes(input_bytes), self.seq_length)# print('decode seq len: {}'.format(len(dec_output))) return dec_output

当我来使用java的时候 发现 网上java对于这个格式音频处理的相关文章非常的少,相关依赖也非常的少,至于找到的可以用的依赖,也没找到相关文档怎么使用。
通过我在 github上的搜索和 maven仓库里的寻找,终于找到了java对于 opus格式的音频的解决方案。
下面就直接上代码了:
第一步引入依赖:

      <dependency><groupId>club.minnced</groupId><artifactId>opus-java</artifactId><version>1.1.1</version></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>4.1.0</version></dependency>

第二步封装 工具类:

package com.agentai.base.utils;/**** opus 解码器工具类* User: Json* Date: 2025/4/11**/
import club.minnced.opus.util.OpusLibrary;
import com.sun.jna.ptr.PointerByReference;
import tomp2p.opuswrapper.Opus;import java.io.IOException;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Base64;public class OpusDecoder {private int samplerate;private int seqLength;private PointerByReference opusDecoder;// 加载 Opus 库  对于这个加载 opus库的 写法 文章下方 有截图的解释。static {try {// 尝试通过 OpusLibrary 加载 JAR 内的本地库if (!OpusLibrary.loadFromJar()) {throw new UnsatisfiedLinkError("未加载到 opus处理文件!");}} catch (IOException e1) {try {// 如果失败,尝试通过默认的 System.loadLibrary() 加载 找本地系统的System.loadLibrary("opus");} catch (UnsatisfiedLinkError e2) {e1.printStackTrace();}}}public OpusDecoder(int samplerate, int channels, float seqTime) {this.samplerate = samplerate;// 创建 Opus 解码器IntBuffer error = IntBuffer.allocate(4);this.opusDecoder = Opus.INSTANCE.opus_decoder_create(samplerate, channels, error);this.seqLength = (int) (seqTime * this.samplerate * 2);}public short[] decode(String base64Audio) {// 1. 解码 Base64 音频数据byte[] audioBytes = Base64.getDecoder().decode(base64Audio);// 2. 创建用于存储解码后的数据的 ShortBufferShortBuffer decodedData = ShortBuffer.allocate(1024 * 1024);// 3. 解码 Opus 数据int decoded = Opus.INSTANCE.opus_decode(opusDecoder, audioBytes, audioBytes.length, decodedData, seqLength, 0);// 4. 返回解码后的短音频数据short[] result = new short[decoded];decodedData.get(result, 0, decoded);return result;}public byte[] decodeToBytes(String base64Audio) {// 1. 解码 Base64 音频数据byte[] audioBytes = Base64.getDecoder().decode(base64Audio);// 2. 创建用于存储解码后的数据的 ShortBufferShortBuffer decodedData = ShortBuffer.allocate(1024 * 1024);// 3. 解码 Opus 数据int decoded = Opus.INSTANCE.opus_decode(opusDecoder, audioBytes, audioBytes.length, decodedData, seqLength, 0);// 4. 转换 short[] 为 byte[]short[] shortData = new short[decoded];decodedData.get(shortData, 0, decoded);byte[] byteData = convertShortToByte(shortData);return byteData; // 返回 byte[] 类型的音频数据}private byte[] convertShortToByte(short[] shortArray) {byte[] byteArray = new byte[shortArray.length * 2];for (int i = 0; i < shortArray.length; i++) {byteArray[i * 2] = (byte) (shortArray[i] & 0xFF);        // 低字节byteArray[i * 2 + 1] = (byte) ((shortArray[i] >> 8) & 0xFF); // 高字节}return byteArray;}// 销毁解码器,释放资源public void close() {Opus.INSTANCE.opus_decoder_destroy(opusDecoder);}// 测试解码功能public static void main(String[] args) {// 假设这是接收到的 Base64 编码的音频数据 // 因为我的音频是先base了一下 所以我需要先用base64 解码,//如果你的音频没有 base64 这个步骤跳过即可String base64Audio =  ""; // 你的音频数据流// 创建解码器对象OpusDecoder decoder = new OpusDecoder(16000, 1, 0.02f);// 解码音频byte[] decodedAudio = decoder.decodeToBytes(base64Audio);// 打印解码结果长度System.out.println("Decoded audio length: " + decodedAudio.length);// 关闭解码器decoder.close();}
}

这个工具类的封装 也是我找的依赖 看他们的源码 自己封装的,
因为 开源的相关依赖没有提供非常完整的 使用文档,所以只能自己看源码 。
下面就是我在源码里看到的:
我的理解:
java 没有现成处理这种opus格式音频的能力,也许这就是为啥网上关于java处理这个音频的的文章比较少的原因。
看到源码后,这个依赖的解决方案就是,把可以处理 opus格式的 扩展打包到 java的jar里,然后通过java 来加载 这些 扩展,然后通过java调用这些扩展里的方法从来 实现 opus格式的音频解码。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/75423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue项目引入tailwindcss

vue3项目引入tailwindcss vue3 vite tailwindcss3 版本 初始化项目 npm create vitelatest --template vue cd vue npm install npm run dev安装tailwindcss3 和 postcss 引入 npm install -D tailwindcss3 postcss autoprefixer // 初始化引用 npx tailwindcss init -p…

Google ADK(Agent Development Kit)简要示例说明

一、环境准备与依赖安装 1.1 系统 硬件&#xff1a; GPU NVIDIA 3070加速模型推理&#xff0c;内存64GB软件&#xff1a; Python 3.11Docker 28.04&#xff08;用于容器化部署&#xff09;Kubernetes 1.25&#xff08;可选&#xff0c;用于集群管理&#xff09; 1.2 安装 A…

批量给文件编排序号,支持数字序号及时间日期序号编排文件

当我们需要对文件进行编号的时候&#xff0c;我们可以通过这个工具来帮我们完成&#xff0c;它可以支持从 001 到 100 甚至更多的数字序号编号。也可以支持按照日期、时间等方式对文件进行编号操作。这是一种操作简单&#xff0c;处理起来也非常的高效文件编排序号的方法。 工作…

【系统架构】AI时代下,系统架构师如何修炼

在AI时代,系统架构师的角色正经历深刻变革,需在技术深度、工具应用与思维模式上全面升级。以下结合行业趋势与实践建议,总结系统架构师的修炼路径: 一、掌握AI工具,重构工作流 自动化文档与设计 利用生成式AI(如DeepSeek、ChatGPT)完成70%的需求文档、接口设计及架构图生…

图像颜色空间对比(Opencv)

1. 颜色转换 import cv2 import matplotlib.pyplot as plotimg cv2.imread("tmp.jpg") img_r cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_g cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img_h cv2.cvtColor(img, cv2.COLOR_BGR2HSV) img_l cv2.cvtColor(img, cv2.C…

JDBC驱动autosave缺陷的修复与配置指南

opengauss-jdbc-6.0.0.jar和opengauss-jdbc-6.0.0-og.jar版本修复了&#xff1a;autosavealways时&#xff0c;事务嵌套太深&#xff0c;导致栈溢出问题。如果使用的版本低于opengauss-jdbc-6.0.0版本&#xff0c;需要通过替换jdbc驱动和修改url参数来解决autosave缺陷。以下是…

K8S-证书过期更新

K8S证书过期问题 K8S证书过期处理方法 Unable to connect to the server: x509: certificate has expired or is not yet valid 1、查看证书有效期&#xff1a; # kubeadm certs check-expiration2、备份证书 # cp -rp /etc/kubernetes /etc/kubernetes.bak3、直接重建证书 …

2025 年网络安全终极指南

我们生活在一个科技已成为日常生活不可分割的一部分的时代。对数字世界的依赖性日益增强的也带来了更大的网络风险。 网络安全并不是IT专家的专属特权&#xff0c;而是所有用户的共同责任。通过简单的行动&#xff0c;我们可以保护我们的数据、隐私和财务&#xff0c;降低成为…

Python的那些事第四十九篇:基于Python的智能客服系统设计与实现

基于Python的智能客服系统设计与实现 摘要 随着人工智能技术的飞速发展,智能客服系统逐渐成为企业提升客户服务质量和效率的关键工具。本文详细介绍了基于Python的智能客服系统的设计与实现方案,涵盖了系统架构、核心功能、技术选型及优化建议,旨在为企业构建高效、智能的客…

第Y1周:调用YOLOv5官方权重进行检测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 1、前言2、下载源码3、运行代码 1、前言 YOLOv5分为YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x四个版本&#xff0c;这里以YOLOv5s为例。 2、下载源码 安…

Python小程序 - 文件处理3:正则表达式

正则表达式&#xff1a;文本年鉴表。遗留的问题很多。。。用AI再想想 需求&#xff1a;读入txt文件&#xff0c;过滤文件有关年记录 0&#xff09;读入txt文件 1&#xff09;以“。”&#xff0c;中文句号&#xff0c;为界区分一句&#xff0c;最小统计单位 2&#xff09;年格…

【antd + vue】Tree 树形控件:默认展开所有树节点 、点击文字可以“选中/取消选中”节点

一、defaultExpandAll 默认展开所有树节点 1、需求&#xff1a;默认展开所有树节点 2、问题&#xff1a; v-if"data.length"判断的层级不够&#xff0c;只判断到了物理那一层&#xff0c;所以只展开到那一层。 3、原因分析&#xff1a; 默认展开所有树节点, 如果是…

Notepad++安装Markdown实时预览插件

具体操作 打开notepad -> 插件 -> 插件管理 -> 可用 -> “Markdown Panel” -> 安装&#xff0c;安装完成后工具栏点击"Markdown Panel"按钮。 注意&#xff1a;由于网络等原因可能安装失败 导致工具栏没出现""Markdown Panel"按钮&am…

OpenHarmony如何编译安装系统应用(以settings设置为例)

开发环境 1.OpenHarmony 2.DevEco Studio 3 .Full Sdk 实现步骤 1.获取设置应用源码 https://gitee.com/openharmony/applications_settings/tree/OpenHarmony-v5.0.0-Release/ 2,使用 DevEco Studio 和 Full SDK对系统应用进行签名,默认工程是未配置签名的状态,所构建…

【ESP32-microros(vscode-Platformio)】

一、步骤 1、目前支持ESP32 2、同一个局域网 3、上位机要安装代理&#xff08;电脑或者linux设备&#xff09; 4、可直接通过USB下载&#xff0c;也可以使用官方烧录工具&#xff0c;具体的分区表地址要从USB烧录的时候日志查看&#xff0c;一共四个文件&#xff0c;第三个…

.NET MAUI教程2-利用.NET CommunityToolkit.Maui框架弹Toast

在上一篇博文的基础上继续操作&#xff1a; .NET MAUI教程1-入门并发布apk包安装到真机-CSDN博客 本文内容参考&#xff1a; Toast - .NET MAUI Community Toolkit - Community Toolkits for .NET | Microsoft Learn 1 在NuGet包管理器中安装 MAUI Community Toolkit&…

软件工程(应试版)图形工具总结(二)

遇到的问题,都有解决方案,希望我的博客能为你提供一点帮助。 教材参考《软件工程导论(第六版)》 七、 层次图(H图)与HIPO图 1、概述 1.1、层次图(Hierarchy Chart / H图) ​核心定义 ​目的:描述软件系统的层次结构,体现模块的从属关系。​适用阶段:自顶向下设计…

java基础 流(Stream)

Stream Stream 的核心概念核心特点 Stream 的操作分类中间操作&#xff08;Intermediate Operations&#xff09;终止操作&#xff08;Terminal Operations&#xff09; Stream 的流分类顺序流&#xff08;Sequential Stream&#xff09;并行流&#xff08;Parallel Stream&…

EAL4+ vs EAL7:高安全场景下的等级选择策略

在数字化浪潮席卷全球的当下&#xff0c;信息安全已然成为各行各业稳健发展的基石。特别是在高安全需求场景中&#xff0c;选择契合的安全等级成为保障信息资产安全的关键。EAL&#xff08;Evaluation Assurance Level&#xff09;评估保障级作为衡量信息技术产品安全保障能力的…

【Java集合】TreeSet、TreeMap源码解读

参考笔记&#xff1a;java TreeSet 和 TreeMap 源码解读-CSDN博客 目录 1.前言 2.红黑树 2.1 红黑树的五大性质 2.2 节点颜色的初始设置 2.3 插入新节后的调整 2.4 删除结构后的调整 2.5 排序规则 2.6 设计红黑树的原因 3.TreeSet简介、底层实现 3.1 TreeSet简介 3.…