TensorFlow音频分类修复
原先传wav格式,后来发现前端生成的wav格式不完整 后端改mp3 其实是mp3和wav都可以接收
前端MP3和wav格式不正确,导致可以接收,但都无法计算时长
该文作废,可能导致音频分类不准确
修复TensorFlow放到生产后报错问题-CSDN博客
依赖
<dependency><groupId>org.tensorflow</groupId><artifactId>tensorflow-core-api</artifactId><version>0.4.2</version></dependency><dependency><groupId>org.tensorflow</groupId><artifactId>tensorflow-core-api</artifactId><version>0.4.2</version><classifier>linux-x86_64</classifier></dependency><dependency><groupId>org.tensorflow</groupId><artifactId>tensorflow-core-api</artifactId><version>0.4.2</version><classifier>windows-x86_64</classifier></dependency><!-- https://mvnrepository.com/artifact/com.googlecode.soundlibs/jlayer --><dependency><groupId>com.googlecode.soundlibs</groupId><artifactId>jlayer</artifactId><version>1.0.1.4</version></dependency>
TensorFlow工具类
package com.ruoyi.webapp.tensorflow;import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.sound.sampled.*;
import java.io.*;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.tensorflow.*;
import org.tensorflow.ndarray.*;
import org.tensorflow.proto.framework.MetaGraphDef;
import org.tensorflow.proto.framework.SignatureDef;
import org.tensorflow.types.TFloat32;
import com.google.protobuf.InvalidProtocolBufferException;import javazoom.jl.decoder.Bitstream;
import javazoom.jl.decoder.BitstreamException;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.decoder.SampleBuffer;
import javazoom.jl.decoder.Header;@Component
public class YamnetUtils3 {private static final int SAMPLE_RATE = 16000;private static final int FRAME_SIZE_IN_MS = 96;private static final int HOP_SIZE_IN_MS = 48;//private static final String MODEL_PATH = "C:\\Users\\user\\Downloads\\archive";private static final String MODEL_PATH = "/usr/local/develop/archive"; // TensorFlow 模型路径private static Map<String, SignatureDef> signatureDefMap;static {try (SavedModelBundle savedModelBundle = SavedModelBundle.load(MODEL_PATH, "serve")) {signatureDefMap = MetaGraphDef.parseFrom(savedModelBundle.metaGraphDef().toByteArray()).getSignatureDefMap();} catch (InvalidProtocolBufferException e) {e.printStackTrace();}}private static final SignatureDef modelSig = signatureDefMap.get("serving_default");private static final String inputTensorName = modelSig.getInputsMap().get("waveform").getName();private static final String outputTensorName = modelSig.getOutputsMap().get("output_0").getName();private static Map<String, String> map = new ConcurrentHashMap<>();static {//String csvFile = "C:\\Users\\user\\Downloads\\archive\\assets\\yamnet_class_map.csv";String csvFile = "/usr/local/develop/archive/assets/yamnet_class_map.csv";try {List<String> lines = Files.readAllLines(Paths.get(csvFile));for (String line : lines) {String[] values = line.split(",");map.put(values[0], values[2]);}} catch (IOException e) {e.printStackTrace();}}public String classifyAudio(MultipartFile file) throws IOException, UnsupportedAudioFileException {// Convert the MP3 file to a supported format (WAV)File wavFile = convertMp3ToWav(file);// Process the converted filereturn yamnetPare(wavFile);}private File convertMp3ToWav(MultipartFile file) throws IOException {File tempFile = File.createTempFile("temp", ".wav");File mp3File = File.createTempFile("temp", ".mp3");file.transferTo(mp3File);try (FileInputStream mp3Stream = new FileInputStream(mp3File);FileOutputStream wavStream = new FileOutputStream(tempFile)) {Bitstream bitstream = new Bitstream(mp3Stream);Decoder decoder = new Decoder();// Write WAV headerwriteWavHeader(wavStream, 0, 1, SAMPLE_RATE, 16);Header header;while ((header = bitstream.readFrame()) != null) {SampleBuffer output = (SampleBuffer) decoder.decodeFrame(header, bitstream);short[] samples = output.getBuffer();for (short sample : samples) {wavStream.write(shortToBytes(sample));}bitstream.closeFrame();}// Update WAV header with data sizeupdateWavHeader(tempFile);} catch (Exception e) {throw new IOException("Failed to convert MP3 to WAV", e);}return tempFile;}private void writeWavHeader(OutputStream out, long totalAudioLen, int channels, long sampleRate, int bitDepth) throws IOException {long totalDataLen = totalAudioLen + 36;long byteRate = sampleRate * channels * bitDepth / 8;byte[] header = new byte[44];header[0] = 'R'; // RIFF/WAVE headerheader[1] = 'I';header[2] = 'F';header[3] = 'F';header[4] = (byte) (totalDataLen & 0xff);header[5] = (byte) ((totalDataLen >> 8) & 0xff);header[6] = (byte) ((totalDataLen >> 16) & 0xff);header[7] = (byte) ((totalDataLen >> 24) & 0xff);header[8] = 'W';header[9] = 'A';header[10] = 'V';header[11] = 'E';header[12] = 'f'; // 'fmt ' chunkheader[13] = 'm';header[14] = 't';header[15] = ' ';header[16] = 16; // 4 bytes: size of 'fmt ' chunkheader[17] = 0;header[18] = 0;header[19] = 0;header[20] = 1; // format = 1header[21] = 0;header[22] = (byte) channels;header[23] = 0;header[24] = (byte) (sampleRate & 0xff);header[25] = (byte) ((sampleRate >> 8) & 0xff);header[26] = (byte) ((sampleRate >> 16) & 0xff);header[27] = (byte) ((sampleRate >> 24) & 0xff);header[28] = (byte) (byteRate & 0xff);header[29] = (byte) ((byteRate >> 8) & 0xff);header[30] = (byte) ((byteRate >> 16) & 0xff);header[31] = (byte) ((byteRate >> 24) & 0xff);header[32] = (byte) (2 * 16 / 8); // block alignheader[33] = 0;header[34] = (byte) bitDepth; // bits per sampleheader[35] = 0;header[36] = 'd';header[37] = 'a';header[38] = 't';header[39] = 'a';header[40] = (byte) (totalAudioLen & 0xff);header[41] = (byte) ((totalAudioLen >> 8) & 0xff);header[42] = (byte) ((totalAudioLen >> 16) & 0xff);header[43] = (byte) ((totalAudioLen >> 24) & 0xff);out.write(header, 0, 44);}private void updateWavHeader(File wavFile) throws IOException {RandomAccessFile wavRAF = new RandomAccessFile(wavFile, "rw");wavRAF.seek(4);wavRAF.write(intToBytes((int) (wavRAF.length() - 8)));wavRAF.seek(40);wavRAF.write(intToBytes((int) (wavRAF.length() - 44)));wavRAF.close();}private byte[] intToBytes(int value) {return new byte[]{(byte) (value & 0xFF),(byte) ((value >> 8) & 0xFF),(byte) ((value >> 16) & 0xFF),(byte) ((value >> 24) & 0xFF)};}private byte[] shortToBytes(short value) {return new byte[]{(byte) (value & 0xFF),(byte) ((value >> 8) & 0xFF)};}private FloatNdArray processAudio(File file) throws IOException, UnsupportedAudioFileException {try (AudioInputStream audioStream = AudioSystem.getAudioInputStream(file)) {AudioFormat format = audioStream.getFormat();if (format.getSampleRate() != SAMPLE_RATE || format.getChannels() != 1) {System.out.println("Warning: Audio must be 16kHz mono. Consider preprocessing.");}int frameSize = (int) (SAMPLE_RATE * FRAME_SIZE_IN_MS / 1000);int hopSize = (int) (SAMPLE_RATE * HOP_SIZE_IN_MS / 1000);byte[] buffer = new byte[frameSize * format.getFrameSize()];short[] audioSamples = new short[frameSize];List<Float> floatList = new ArrayList<>();while (true) {int bytesRead = audioStream.read(buffer);if (bytesRead == -1) {break;}for (int i = 0; i < bytesRead / format.getFrameSize(); i++) {audioSamples[i] = (short) ((buffer[i * 2] & 0xFF) | (buffer[i * 2 + 1] << 8));}float[] floats = normalizeAudio(audioSamples);for (float aFloat : floats) {floatList.add(aFloat);}System.arraycopy(audioSamples, hopSize, audioSamples, 0, frameSize - hopSize);}float[] floatArray = new float[floatList.size()];for (int i = 0; i < floatList.size(); i++) {floatArray[i] = floatList.get(i);}return StdArrays.ndCopyOf(floatArray);}}private float[] normalizeAudio(short[] frame) {float[] normalizedFrame = new float[frame.length];for (int i = 0; i < frame.length; i++) {normalizedFrame[i] = frame[i] / 32768f;}return normalizedFrame;}private String yamnetPare(File file) throws IOException, UnsupportedAudioFileException {FloatNdArray floatNdArray = processAudio(file);TFloat32 tFloat32 = TFloat32.tensorOf(floatNdArray);try (SavedModelBundle savedModelBundle = SavedModelBundle.load(MODEL_PATH, "serve")) {try (Session session = savedModelBundle.session()) {List<Tensor> run = session.runner().feed(inputTensorName, tFloat32).fetch(outputTensorName).run();Tensor tensor = run.get(0);Shape shape = tensor.shape();System.out.println(shape + "--------------------------------------------------");String key = String.valueOf(shape.asArray()[0]);String value = map.get(key);return value;}}}
}
文件接口
//记录文件@PostMapping("/reportUpload")//@RequireVip//睡眠监测时 文件上传接口public AjaxResult reportUpload(MultipartFile file) throws IOException {try {//获取文件名String originalFilename = file.getOriginalFilename();//获取时长秒//String wavDuration = getWavDuration(file);//String wavDuration = getWavDuration3(file);//String wavDuration = getWavDuration55(file);String filePath = RuoYiConfig.getUploadPath();///usr/local/nginx/html/upload/upload//上传并返回新文件路径String fileName = FileUploadUtils.upload(filePath, file);//获取音频类型//String s = yamnetUtils2.yamnetPare(file);String s = yamnetUtils3.classifyAudio(file);//获取时长秒//String wavDuration =getWavDuration(fileName);getMp3DurationString wavDuration =getMp3Duration(fileName);if(!StringUtils.isEmpty(s)){if (!s.equals("Speech") && !s.equals("Snoring") && !s.equals("Cough")) {s = "Other";}TReportFile tReportFile=new TReportFile();tReportFile.setUid(getLoginUser().getUserId());tReportFile.setFileType(s);tReportFile.setLengths(wavDuration);tReportFile.setFilePath(fileName);//tReportFile.setCreateTime(new Date());tReportFileService.insertTReportFile(tReportFile);}return success();}catch (Exception e){e.printStackTrace();return error();}}
//获取wav文件时长private String getWavDuration(String relativeFilePath) {String basePath = "/usr/local/nginx/html/upload";if (relativeFilePath.startsWith("/profile")) {relativeFilePath = relativeFilePath.substring(8);}String fullPath = basePath + relativeFilePath;File file = new File(fullPath);if (!file.exists()) {return "File not found";}try (AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file)) {AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);long frameLength = audioInputStream.getFrameLength();float frameRate = fileFormat.getFormat().getFrameRate();float durationInSeconds = frameLength / frameRate;return Math.round(durationInSeconds) + "s";} catch (UnsupportedAudioFileException | IOException e) {e.printStackTrace();return "Error";}}//获取Mp3文件时长public static String getMp3Duration(String relativeFilePath) {String basePath = "/usr/local/nginx/html/upload";if (relativeFilePath.startsWith("/profile")) {relativeFilePath = relativeFilePath.substring(8);}String fullPath = basePath + relativeFilePath;File file = new File(fullPath);if (!file.exists()) {return "File not found";}try (FileInputStream fileInputStream = new FileInputStream(file)) {Bitstream bitstream = new Bitstream(fileInputStream);Header header;int totalFrames = 0;float totalDuration = 0;while ((header = bitstream.readFrame()) != null) {totalDuration += header.ms_per_frame();totalFrames++;bitstream.closeFrame();}float durationInSeconds = totalDuration / 1000.0f;return Math.round(durationInSeconds) + "s";} catch (IOException | BitstreamException e) {e.printStackTrace();return "Error";}}
相关文章:
TensorFlow音频分类修复
原先传wav格式,后来发现前端生成的wav格式不完整 后端改mp3 其实是mp3和wav都可以接收 前端MP3和wav格式不正确,导致可以接收,但都无法计算时长 该文作废,可能导致音频分类不准确 修复TensorFlow放到生产后报错问题-CSDN博客 依赖 <dependency><groupId>or…...
C#学习系列之ListView垂直滚动
C#学习系列之ListView垂直滚动 前言垂直滚动总结 前言 当ListView中不断增加新内容,经常是纵向滚动。 垂直滚动 这个是关键:<VirtualizingStackPanel/> <ListView.ItemsPanel><ItemsPanelTemplate><VirtualizingStackPanel/>&…...
MySQL 常用函数总结
MySQL 提供了丰富的内置函数,用于在查询中进行各种计算、字符串处理、日期和时间操作等。这些函数可以帮助我们更有效地从数据库中检索和处理数据。下面将总结一些 MySQL 中常用的函数及其用法。 1. 数值函数 1.1 ROUND() ROUND() 函数用于对数值进行四舍五入操作…...

SpingBoot快速入门下
响应HttpServietResponse 介绍 将ResponseBody 加到Controller方法/类上 作用:将方法返回值直接响应,如果返回值是 实体对象/集合,将会自动转JSON格式响应 RestController Controller ResponseBody; 一般响应 统一响应 在实际开发中一般…...
什么是symbol?
在ES6(ECMAScript 2015)中,Symbol是一种新的基本数据类型,它的主要特点是独一无二且不可变。以下是关于ES6中Symbol的详细解释: 定义与特性: Symbol是ES6引入的一种基本数据类型,用于表示独一无…...

Tailwind CSS 响应式设计实战指南
title: Tailwind CSS 响应式设计实战指南 date: 2024/6/13 updated: 2024/6/13 author: cmdragon excerpt: 这篇文章介绍了如何运用Tailwind CSS框架创建响应式网页设计,涵盖博客、电商网站及企业官网的布局实例,包括头部导航、内容区域、侧边栏、页脚…...

如何把模糊的图片修复变清晰,怎么做?有那些方法?
模糊照片怎么修复清晰?有些照片可能会因为保存不当或其他原因而变得模糊,这些照片删掉又觉得可惜,那么如何让这些照片焕然一新呢?今天就给大家分享几种可以将这些珍贵的模糊照片修复为高清照片的方法。接下来,给大家演…...
思科路由器密码恢复方法
1.密码恢复原理 Cisco路由器保存了几种不同的配置参数,并存放在不同的内存模块中。 Cisco系列路由器的内存有:ROM,闪存(Flashmemory),RAM,不可变RAM和动态内存(DRAM)等5种。 一般情况…...
HTML某联招聘
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!-- 一些其他说明: 不写form的话,表单内容也是可以正常显示的࿰…...

第一百一十六节 Java 面向对象设计 - Java 终止块
Java 面向对象设计 - Java 终止块 try 块也可以有零个或一个 finally 块。 finally 块总是与 try 块一起使用。 语法 使用 finally 块的语法是 finally {// Code for finally block }finally 块以关键字 finally 开始,后面紧跟一对…...

YOLOv10改进 | 注意力篇 | YOLOv10引入YOLO-Face提出的SEAM注意力机制优化物体遮挡检测
1. SEAM介绍 1.1 摘要:近年来,基于深度学习的人脸检测算法取得了长足的进步。 这些算法通常可以分为两类,即像 Faster R-CNN 这样的两级检测器和像 YOLO 这样的一级检测器。 由于精度和速度之间具有更好的平衡,一级探测器已广泛应用于许多应用中。 在本文中,我们提出了一…...

问题解决:Problem exceeding maximum token in azure openai (with java)
问题背景: Im doing a chat that returns queries based on the question you ask it in reference to a specific database. For this I use azure openai and Java in Spring Boot. 我正在开发一个聊天功能,该功能根据您针对特定数据库的提问返回查询…...

eNSP学习——OSPF在帧中继网络中的配置
目录 主要命令 原理概述 实验目的 实验场景 实验拓扑 实验编址 实验步骤 1、基本配置 2、在帧中继上搭建OSPF网络 主要命令 //检查帧中继的虚电路状态 display fr pvc-info//检查帧中继的映射表 display fr map-info//手工指定OSPF邻居,采用单播方式发送报文 [R1]os…...

PHP转Go系列 | 条件循环的使用姿势
大家好,我是码农先森。 条件 在 PHP 语言中条件控制语句,主要有 if、elseif、else 和 switch 语句 // if、elseif、else 语句 $word "a"; if ($word "a") {echo "a"; } elseif ($word "b") {echo "b&…...

八大经典排序算法
前言 本片博客主要讲解一下八大排序算法的思想和排序的代码 💓 个人主页:普通young man-CSDN博客 ⏩ 文章专栏:排序_普通young man的博客-CSDN博客 若有问题 评论区见📝 🎉欢迎大家点赞👍收藏⭐文章 目录 …...
【LeetCode热题 100】三数之和
leetcode原地址:https://leetcode.cn/problems/3sum/description 描述 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和…...
【深度学习驱动流体力学】完整配置安装 OpenFOAM 及其所需的ThirdParty与QT5工具
OpenFOAM 简介 OpenFOAM(Open Field Operation and Manipulation)是一个领先的开源计算流体动力学(CFD)软件包,由 OpenFOAM Foundation 开发和维护。作为一个高度模块化和可扩展的软件工具箱,OpenFOAM 支持模拟多种物理现象,包括流体流动、传热、混合、燃烧、声学等。由…...

YOLOv10改进 | Neck | 添加双向特征金字塔BiFPN【含二次独家创新】
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录:《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40篇内容,内含各种Head检测头、损失函数Loss、B…...
PostgreSQL源码分析——pg_basebackup
涉及到的代码主要在src/backend/replication以及bin/pg_basebackup中。 我们知道pg_basebackup是一个进行基础备份的工具,除了使用这个工具,还可以用底层API的方式进行基础备份,主要过程如下: 连接到数据库执行select pg_start_…...

QT基础 - 常见图表绘制
目录 零. 前言 一. 添加模块 折线图 三. 树状图 四. 饼图 五. 堆叠柱状图 六. 百分比柱状图 七. 散点图和光滑曲线图 散点图 光滑曲线图 零. 前言 Qt Charts 是 Qt 框架的一个模块,用于创建各种类型的图表和数据可视化。它为开发者提供了一套功能强大的工…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...