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.pswp.cn/web/75423.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75423.shtml
英文地址,請注明出處:http://en.pswp.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.…