SenseVoice-Small ONNX塑料制品:注塑语音→周期时间异常自动预警方案

1. 引言:当注塑机开始“说话”

想象一下,在一条繁忙的注塑生产线上,机器轰鸣,模具开合。操作员小王正紧盯着控制面板上的各种参数,试图从一堆数字中判断当前这模产品的周期时间是否正常。突然,对讲机里传来急促的声音:“3号机,周期好像变长了!” 小王赶紧跑过去,发现确实慢了2秒,但此时已经连续生产了50多件不良品。

这个场景每天都在无数工厂里上演。注塑生产的核心指标——周期时间,直接决定了产能、成本和产品质量。传统的人工监控方式,依赖操作员的经验和注意力,不仅效率低下,还容易因疲劳或疏忽导致批量性异常未被及时发现,造成巨大的物料和工时浪费。

有没有一种方法,能让机器自己“开口说话”,实时告诉我们每一模的生产状态是否健康?今天,我们就来探讨一个基于SenseVoice-Small ONNX语音识别工具的创新方案:通过识别注塑机运行时的环境语音,自动预警周期时间异常。这个方案的核心思路是:注塑机在不同运行阶段(合模、注射、保压、冷却、开模)会产生特征鲜明的机械噪音和气流声,这些“声音指纹”与周期时间强相关。通过实时识别和分析这些声音,我们就能在异常发生的第一时间发出警报。

2. 为什么选择声音分析?传统方案的痛点

在深入技术细节前,我们先看看为什么声音分析是一个值得尝试的方向,以及它解决了哪些传统方案的痛点。

2.1 传统周期时间监控的局限

目前,工厂监控注塑周期时间主要依靠以下几种方式:

  1. PLC/IoT传感器直读:最准确,但需要设备支持数据接口,改造成本高,且很多老旧设备不具备此功能。
  2. 视觉分析:在模具或机械臂上贴标记点,用摄像头分析运动周期。受现场光照、油污遮挡影响大,部署复杂。
  3. 人工掐表记录:最原始,依赖人力,无法做到7x24小时持续监控,数据样本少,且容易出错。
  4. 振动传感器分析:能有效监测机械状态,但对周期时间的细微变化(如冷却时间延长1-2秒)不敏感。

这些方法要么“太贵”(需要硬件改造),要么“太笨”(依赖人力),要么“太盲”(无法捕捉细微变化)。

2.2 声音分析的独特优势

相比之下,基于声音的分析方案展现出几个明显的优势:

  • 非侵入式部署:只需在设备附近放置一个麦克风,无需对机器进行任何物理改造,部署成本极低。
  • 信息维度丰富:声音信号包含了机器运行状态、液压系统、电机、气阀动作等综合信息,能反映更细微的异常。
  • 实时性强:声音采集和处理几乎是实时的,可以实现秒级甚至毫秒级的异常检测与预警。
  • 成本低廉:一个工业麦克风加一个边缘计算盒子(如树莓派)即可构成一个监测点,非常适合大规模铺开。

而实现这一方案的关键,就在于一个能在资源受限的工业边缘设备上稳定、准确、快速运行的语音识别引擎。这正是SenseVoice-Small ONNX量化版大显身手的地方。

3. 方案核心:SenseVoice-Small ONNX工具解析

我们的预警方案建立在之前介绍的SenseVoice-Small ONNX语音识别工具之上。在将其应用于工业场景前,我们先快速回顾一下这个工具的核心能力,并理解它为何是理想选择。

3.1 工具核心特性回顾

这个工具不是一个通用的语音转文字工具,而是为高效、轻量、本地化运行而优化的专用方案:

  • Int8量化加速:模型经过INT8量化处理,相比原始版本,内存和显存占用大幅降低(约75%)。这意味着它可以在普通的工控机、边缘计算盒子甚至高性能树莓派上流畅运行,无需昂贵的GPU。
  • 纯本地运行:所有推理过程均在本地完成,音频数据无需上传至云端,保障了生产数据的安全与隐私,也避免了网络延迟或中断带来的影响。
  • 高精度与后处理:基于FunASR框架,对中文及混合语音识别准确率高。集成了逆文本正则化(将“一百五十秒”转为“150秒”)和CT-Transformer标点恢复,输出结果规整,便于后续程序处理。
  • 轻量化交互与部署:通过Streamlit提供简洁的Web界面,但更关键的是其易于集成的API。我们可以轻松地将识别引擎封装成一个服务,供其他系统调用。

3.2 从“语义识别”到“声学事件检测”的思维转换

在注塑机预警场景中,我们并不需要工具理解语音的“语义”(即说的是什么话),而是需要它成为一个高精度的**“声学事件检测器”**。

我们的目标不是转写出“现在是合模阶段”,而是需要识别出代表特定阶段开始的独特声音特征。例如:

  • “砰”的一声闷响 → 可能代表模具闭合到位。
  • 持续的高频电机声 → 可能代表注射螺杆前进。
  • 气流泄压的“嘶嘶”声 → 可能代表开模开始。

SenseVoice-Small的声学模型部分,正是为了捕捉和区分这类声音特征而训练的。我们将其输出的“音素”或“声学特征向量”序列,作为我们判断当前机器处于哪个运行阶段的依据。

4. 实战构建:注塑周期时间异常预警系统

接下来,我们一步步构建这个预警系统。整个架构可以分为数据采集层、边缘处理层和业务预警层

4.1 系统架构与数据流

[工业麦克风] --> (音频流) --> [边缘计算设备]
                                      |
                                      v
                              [SenseVoice-Small ONNX 引擎]
                                      |
                                      v
                           (声学特征序列/时间戳) --> [时序事件检测算法]
                                      |
                                      v
                            (阶段开始/结束时间戳) --> [周期计算与异常判断逻辑]
                                      |
                                      v
                              [本地预警] --> [看板显示]
                                      |
                                      v
                              [可选]上报至[MES/云平台]

4.2 第一步:环境部署与工具集成

首先,在边缘计算设备(以Ubuntu系统为例)上部署我们的核心识别工具。

# 1. 克隆项目(假设工具已打包为项目)
git clone <your_sensevoice_onnx_tool_repo>
cd sensevoice-onnx-tool

# 2. 安装依赖(参考项目requirements.txt)
pip install -r requirements.txt
# 主要包含:onnxruntime, funasr, streamlit, librosa等

# 3. 下载模型(如果工具未包含)
# 通常工具会包含或提供脚本自动下载SenseVoice-Small ONNX量化模型和标点模型

# 4. 测试工具基础功能
python app_streamlit.py
# 访问 http://localhost:8501 确认上传音频和识别功能正常

部署成功后,我们需要将其从交互式工具改造成可编程调用的服务。我们可以创建一个简单的recognizer_service.py

# recognizer_service.py
import os
import numpy as np
import soundfile as sf
from funasr import AutoModel

class SenseVoiceRecognizer:
    def __init__(self, model_dir="./models/sensevoice-small-onnx"):
        """初始化识别器,加载量化模型"""
        # 注意:这里使用工具中配置好的量化模型路径
        self.model = AutoModel(
            model=model_dir,
            model_revision="v2.0.4",
            disable_update=True,
            use_itn=True,  # 开启逆文本正则化,对数字处理有用
            quantize=True,  # 启用量化模式
            batch_size=1    # 适配流式或单文件处理
        )
        print(f"模型加载完成,运行在量化(INT8)模式。")

    def recognize_from_file(self, audio_path):
        """从音频文件识别,返回带标点的文本"""
        try:
            # 调用模型推理
            result = self.model.generate(
                input=audio_path,
                language="auto",  # 自动检测语种,但我们的场景主要是机械声
                use_itn=True,
                batch_size=1
            )
            # result[0] 包含识别文本等信息
            text = result[0]["text"] if result and len(result) > 0 else ""
            return text.strip()
        except Exception as e:
            print(f"识别失败: {e}")
            return ""

    def recognize_from_buffer(self, audio_numpy_array, sample_rate=16000):
        """从内存中的音频数据(numpy数组)识别"""
        # 先将音频数据保存为临时文件,因为当前ONNX接口可能需文件路径
        import tempfile
        with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as tmpfile:
            tmp_path = tmpfile.name
            sf.write(tmp_path, audio_numpy_array, sample_rate)
            text = self.recognize_from_file(tmp_path)
            os.unlink(tmp_path)  # 删除临时文件
            return text

# 实例化,供其他模块调用
recognizer = SenseVoiceRecognizer()

4.3 第二步:音频采集与预处理

在注塑机旁部署一个指向性工业麦克风,连接至边缘计算设备的音频输入接口。我们需要一个脚本来持续采集音频流,并将其切割成与注塑周期相匹配的分析片段。

# audio_capture.py
import pyaudio
import numpy as np
import threading
import queue
import time

class AudioStreamCapture:
    def __init__(self, chunk_duration=1.0, sample_rate=16000):
        self.CHUNK = int(sample_rate * chunk_duration)  # 每次读取1秒的音频
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 1
        self.RATE = sample_rate
        self.audio_queue = queue.Queue(maxsize=10)  # 缓冲队列
        self.is_recording = False

    def start(self):
        """开始后台录音线程"""
        self.is_recording = True
        self.thread = threading.Thread(target=self._record_loop)
        self.thread.start()
        print("音频采集已启动...")

    def _record_loop(self):
        p = pyaudio.PyAudio()
        stream = p.open(format=self.FORMAT,
                        channels=self.CHANNELS,
                        rate=self.RATE,
                        input=True,
                        frames_per_buffer=self.CHUNK)
        while self.is_recording:
            data = stream.read(self.CHUNK, exception_on_overflow=False)
            audio_data = np.frombuffer(data, dtype=np.int16).astype(np.float32) / 32768.0
            if not self.audio_queue.full():
                self.audio_queue.put(audio_data)
            else:
                # 队列已满,丢弃最旧的数据(简单策略)
                try:
                    self.audio_queue.get_nowait()
                    self.audio_queue.put(audio_data)
                except queue.Empty:
                    pass
        stream.stop_stream()
        stream.close()
        p.terminate()

    def get_chunk(self):
        """获取最新的一段音频数据,如果没有则阻塞等待"""
        return self.audio_queue.get()

    def stop(self):
        self.is_recording = False
        if hasattr(self, 'thread'):
            self.thread.join()

4.4 第三步:核心逻辑——从声音到周期时间

这是最关键的环节。我们需要定义一个状态机,根据识别出的“声学事件”来划分注塑周期。

# cycle_detector.py
import time
import numpy as np
from collections import deque

class InjectionMoldingCycleDetector:
    def __init__(self, recognizer, threshold_db=-30, window_size=5):
        """
        recognizer: SenseVoiceRecognizer实例
        threshold_db: 判断为“有效事件”的音频能量阈值
        window_size: 用于平滑判断的事件窗口大小
        """
        self.recognizer = recognizer
        self.threshold = 10 ** (threshold_db / 20.0)  # 转换为幅度阈值
        self.event_window = deque(maxlen=window_size)
        self.current_state = "IDLE"  # IDLE, CLAMPING, INJECTING, COOLING, EJECTING
        self.last_state_change_time = time.time()
        self.cycle_start_time = None
        self.cycle_durations = []  # 记录历史周期时间

    def _extract_acoustic_feature(self, audio_chunk):
        """提取简单的声学特征,用于快速判断是否有事件发生"""
        # 1. 计算能量
        energy = np.mean(audio_chunk ** 2)
        # 2. 计算过零率(Zero-Crossing Rate),区分连续噪音和冲击声
        zcr = np.mean(np.abs(np.diff(np.sign(audio_chunk)))) / 2
        return energy, zcr

    def _classify_event(self, energy, zcr, recognized_text):
        """根据声学特征和识别文本(辅助)分类事件"""
        # 这是一个简化的逻辑,实际中需要基于大量标注数据训练一个分类器
        if energy > self.threshold:
            if zcr > 0.3:
                # 高频、冲击性声音,可能是合模撞击或开模撞击
                if "砰" in recognized_text or "bang" in recognized_text.lower(): # 识别文本可能包含拟声词
                    return "CLAMP_START" if self.current_state == "IDLE" else "OPEN_START"
            else:
                # 低频、持续性声音,可能是注射电机声
                return "INJECT_START"
        # 能量低于阈值,可能是冷却或保压静默期
        elif self.current_state == "INJECTING" and energy < self.threshold * 0.1:
            return "COOLING_START"
        return None

    def process_audio_chunk(self, audio_chunk):
        """处理一个音频片段,更新状态机"""
        energy, zcr = self._extract_acoustic_feature(audio_chunk)
        # 为了演示,我们这里简化:只对能量较高的片段做完整识别
        if energy > self.threshold:
            recognized_text = self.recognizer.recognize_from_buffer(audio_chunk)
        else:
            recognized_text = ""

        event = self._classify_event(energy, zcr, recognized_text)
        self.event_window.append(event)

        # 基于窗口内的事件进行决策,避免抖动
        if len(self.event_window) == self.event_window.maxlen:
            # 简单投票决策
            most_common_event = max(set(self.event_window), key=self.event_window.count) if self.event_window else None
            if most_common_event and most_common_event != self.current_state:
                self._handle_state_transition(most_common_event)

    def _handle_state_transition(self, new_event):
        """处理状态转移,计算周期时间"""
        now = time.time()
        old_state = self.current_state

        if new_event == "CLAMP_START":
            self.current_state = "CLAMPING"
            self.cycle_start_time = now  # 新周期开始
            print(f"[{now:.2f}] 周期开始: 合模")
        elif new_event == "INJECT_START" and self.current_state == "CLAMPING":
            self.current_state = "INJECTING"
            print(f"[{now:.2f}] 状态切换: 注射")
        elif new_event == "COOLING_START" and self.current_state == "INJECTING":
            self.current_state = "COOLING"
            print(f"[{now:.2f}] 状态切换: 冷却")
        elif new_event == "OPEN_START" and self.current_state == "COOLING":
            self.current_state = "EJECTING"
            print(f"[{now:.2f}] 状态切换: 开模")
        elif self.current_state == "EJECTING" and (now - self.last_state_change_time) > 2.0: # 开模后一段时间无事件
            self.current_state = "IDLE"
            # 周期结束!
            if self.cycle_start_time:
                cycle_time = now - self.cycle_start_time
                self.cycle_durations.append(cycle_time)
                print(f"[{now:.2f}] 周期结束! 周期时间: {cycle_time:.2f}秒")
                self._check_anomaly(cycle_time)
            self.cycle_start_time = None

        self.last_state_change_time = now

    def _check_anomaly(self, current_cycle_time):
        """检查当前周期时间是否异常"""
        if len(self.cycle_durations) < 5:
            return  # 数据太少,不判断

        historical_mean = np.mean(self.cycle_durations[-10:-1]) if len(self.cycle_durations) > 10 else np.mean(self.cycle_durations[:-1])
        threshold = historical_mean * 1.1  # 假设超过历史平均值的10%即为异常

        if current_cycle_time > threshold:
            print(f"⚠️  异常预警!当前周期 {current_cycle_time:.2f}s,超过平均周期 {historical_mean:.2f}s 的10%。")
            # 此处可以触发警报:点亮指示灯、发送消息到看板、推送通知等
            # trigger_alert(f"周期时间异常: {current_cycle_time:.2f}s")

4.5 第四步:主程序与预警输出

最后,我们将所有模块串联起来,形成一个完整的、持续运行的预警系统。

# main_monitor.py
import time
from audio_capture import AudioStreamCapture
from recognizer_service import recognizer
from cycle_detector import InjectionMoldingCycleDetector

def main():
    # 1. 初始化组件
    audio_capture = AudioStreamCapture(chunk_duration=0.5)  # 每0.5秒分析一次
    detector = InjectionMoldingCycleDetector(recognizer)

    # 2. 启动音频采集
    audio_capture.start()

    print("注塑机周期时间音频监控系统已启动。")
    try:
        while True:
            # 3. 持续获取音频并处理
            audio_chunk = audio_capture.get_chunk()
            detector.process_audio_chunk(audio_chunk)

            # 4. 可以在此处添加其他逻辑,如上传数据到数据库、更新Web界面等
            # upload_cycle_data(detector.cycle_durations)

            time.sleep(0.1)  # 控制循环频率
    except KeyboardInterrupt:
        print("\n正在停止监控...")
    finally:
        audio_capture.stop()
        print("系统已停止。")

if __name__ == "__main__":
    main()

运行这个主程序,系统就会开始监听环境声音,自动识别注塑周期,并在周期时间异常时在控制台打印预警信息。在实际部署中,你需要将print预警替换为触发声光报警器、发送消息到车间看板(MES系统)或推送通知到管理人员手机App。

5. 方案优化与挑战

以上是一个基础的原型。要让其在真实的、嘈杂的工厂环境中稳定工作,还需要考虑以下优化点:

5.1 模型与算法的优化

  • 定制化声学模型训练:使用在目标注塑机现场录制并标注好的声音数据,对SenseVoice-Small的声学前端进行微调(Fine-tuning),让它对“合模声”、“注射声”等特定事件的识别更加精准。
  • 更鲁棒的特征工程:除了能量和过零率,可以引入梅尔频谱图(Mel-spectrogram)、MFCC等更丰富的特征,并使用简单的机器学习模型(如SVM、随机森林)或轻量级神经网络进行分类。
  • 多机交叉验证:在有多台相同型号注塑机的车间,可以用一台正常机器的声音模型作为基准,去检测其他机器的偏差,消除产品工艺差异带来的影响。

5.2 工程部署的考量

  • 降噪与回声消除:使用定向麦克风和软件降噪算法(如谱减法),尽可能聚焦于目标机器的声音。
  • 断点续传与容错:边缘设备可能意外重启,程序需要具备从断点恢复监控的能力。
  • 配置化管理:通过配置文件来调整不同机台、不同产品的阈值参数,使系统易于维护和推广。

6. 总结

通过将SenseVoice-Small ONNX轻量化语音识别工具与工业场景结合,我们探索了一条低成本、非侵入式的注塑机周期时间智能监控路径。这个方案的核心价值在于:

  1. 降本增效:以极低的硬件和部署成本,实现了对关键生产参数的7x24小时无人化监控,避免了因异常发现不及时导致的批量废品和产能损失。
  2. 数据驱动:将老师傅“听音辨状”的经验转化为可量化、可分析、可追溯的数据,为生产过程的数字化和精细化管控奠定了基础。
  3. 灵活可扩展:该框架不仅可以用于周期时间监控,稍加改造即可用于设备异响预警(如轴承磨损)、泄漏检测、人员安全监控(如区域闯入警报)等场景。

技术的意义在于解决实际问题。SenseVoice-Small ONNX工具提供的强大而高效的本地语音识别能力,就像为我们打开了工厂的“耳朵”,让沉默的设备开始“说话”,帮助我们更早地发现隐患,更智能地管理生产。在工业4.0和智能制造的浪潮下,这类轻量、边缘化的AI解决方案,正成为推动传统制造业转型升级的重要力量。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐