ComfyUI可视化流程集成:SenseVoice-Small语音识别节点开发教程

你是不是已经用ComfyUI玩转各种文生图、图生图,甚至搭建了复杂的AI绘画工作流?有没有想过,如果能让你的工作流“听懂”语音指令,或者自动把一段播客、会议录音转成文字,再交给AI去生成对应的画面,那该多酷?

今天,我们就来点不一样的。不聊怎么用现成的节点,而是教你如何自己动手,在ComfyUI里“造”一个节点。我们要造的,是一个能集成SenseVoice-Small语音识别模型的节点。SenseVoice-Small是一个轻量但效果不错的语音转文字模型,把它塞进ComfyUI,你的工作流就能直接从音频里提取文本,开启“声控作画”或者“音频驱动内容生成”的新玩法。

听起来有点技术含量?别担心,这篇教程就是给ComfyUI的“高级玩家”准备的。我们会从零开始,一步步带你走通自定义节点开发的全过程。你不需要是Python大神,但需要对ComfyUI的节点系统有基本了解,并且愿意动手敲点代码。学完这篇,你不仅能拥有一个语音识别节点,更重要的是,你会掌握在ComfyUI里创造任何你想要的功能节点的能力。

1. 开发前的准备:理清思路与环境搭建

在开始写代码之前,我们得先想明白这个节点要干什么,以及需要准备哪些东西。

简单来说,我们的目标是:创建一个ComfyUI节点,它接收一个音频文件的路径作为输入,调用SenseVoice-Small模型进行识别,最后输出识别出的文本字符串。

为了实现这个目标,我们需要搞定三件事:

  1. 模型本身:如何让Python代码调用SenseVoice-Small。
  2. 节点框架:如何遵循ComfyUI的规则,创建一个能被识别和使用的节点。
  3. 流程集成:如何设计输入输出,让这个节点能无缝嵌入到其他工作流中。

1.1 环境与依赖安装

首先,确保你的ComfyUI运行环境是正常的。然后,我们需要安装SenseVoice-Small模型所依赖的Python包。打开你的终端(或ComfyUI启动命令所在的环境),执行以下命令:

pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu118  # 如果你用CUDA 11.8
pip install modelscope funasr

这里解释一下:

  • torchtorchaudio:PyTorch深度学习框架及其音频处理库,是模型运行的基础。
  • modelscopefunasr:ModelScope是阿里开源的模型社区,FunASR是专注于语音识别的工具包。SenseVoice-Small模型可以通过它们方便地加载和使用。

安装完成后,建议你单独写一个小的Python脚本测试一下模型是否能正常加载和推理,确保基础环境没问题。

1.2 理解ComfyUI节点的基础结构

ComfyUI的节点本质上是一个Python类。这个类必须定义一些特定的方法和属性,ComfyUI的图形化界面才能识别它、渲染它。最核心的几个部分包括:

  • FUNCTION:一个字符串属性,指定节点执行的主函数名。
  • CATEGORY:一个字符串属性,决定这个节点在节点菜单中被归类到哪个目录下,比如”audio””custom_nodes”
  • RETURN_TYPESRETURN_NAMES:这两个属性定义了节点的输出。RETURN_TYPES 是一个元组,指定每个输出的数据类型(如”STRING”);RETURN_NAMES 也是一个元组,给每个输出起一个显示名称。
  • INPUT_TYPES 静态方法:这个方法返回一个字典,用来定义节点的所有输入参数(也就是那些可以连接线的小插座)。字典的键是参数名,值是这个参数的配置(比如类型、默认值等)。
  • 一个主执行方法:方法名由FUNCTION属性指定。这个方法接收INPUT_TYPES中定义的参数,执行核心逻辑,并返回一个元组,其元素顺序和类型要与RETURN_TYPES严格对应。

理清了这些,我们就可以开始动手创建了。

2. 核心代码编写:从模型调用到节点封装

接下来,我们进入核心环节,一步步构建我们的SenseVoiceSmall节点。

2.1 创建节点文件与目录结构

在ComfyUI的安装目录下,有一个custom_nodes文件夹。所有第三方节点都放在这里。我们在其中创建一个属于自己的目录,比如comfyui-sensevoice-node

ComfyUI/
├── custom_nodes/
│   └── comfyui-sensevoice-node/
│       ├── __init__.py
│       └── nodes.py
├── ...
  • __init__.py:可以是一个空文件,它告诉Python这个目录是一个包。
  • nodes.py:我们将在这里编写节点的所有代码。

2.2 编写节点类代码

打开nodes.py,开始编写代码。我会分段解释,你可以跟着一起写。

第一部分:导入依赖和定义节点类

import torch
import torchaudio
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
import os
import numpy as np
import folder_paths
import comfy.utils

class SenseVoiceSmall:
    """
    ComfyUI自定义节点:使用SenseVoice-Small模型进行语音识别。
    输入音频文件路径,输出识别文本。
    """
    
    # 定义节点在ComfyUI中的行为标识
    FUNCTION = “process_audio”
    # 定义节点在菜单中的分类,可以自定义,这里放在“audio”类别
    CATEGORY = “audio”
    # 定义输出类型,这里只有一个字符串输出
    RETURN_TYPES = (“STRING”,)
    # 定义输出名称,方便在界面上识别
    RETURN_NAMES = (“text”,)
    
    # 模型管道对象,作为类变量,实现懒加载(第一次使用时加载)
    _pipe = None

这里我们导入了必要的库,并定义了节点类SenseVoiceSmall。注意FUNCTIONCATEGORY的设置。_pipe是一个类变量,用于缓存加载的模型管道,避免每次执行节点都重新加载模型,这很耗时。

第二部分:定义输入参数 (INPUT_TYPES)

    @staticmethod
    def INPUT_TYPES():
        # 获取ComfyUI中预设的输入目录(如`input`文件夹)
        input_dir = folder_paths.get_input_directory()
        # 扫描该目录下的音频文件
        audio_files = [f for f in os.listdir(input_dir) if f.lower().endswith((‘.wav’, ‘.mp3’, ‘.flac’, ‘.m4a’))]
        
        return {
            “required”: {
                “audio_file”: (audio_files, {“default”: audio_files[0] if audio_files else “”}), # 下拉选择框
            },
            “optional”: {
                “language”: ([“auto”, “zh”, “en”], {“default”: “auto”}), # 可选语言参数
            }
        }

INPUT_TYPES方法返回一个字典,定义了节点的输入插座。

  • ”required”字典里是必须连接的参数。这里我们定义了一个audio_file参数,类型是列表audio_files,这会让ComfyUI将它渲染成一个下拉选择框,列出input文件夹下的所有音频文件。
  • ”optional”字典里是可选的参数。这里我们添加了一个language参数,让用户可以选择识别语言(自动、中文、英文)。

第三部分:实现模型加载与推理 (process_audio)

    def process_audio(self, audio_file, language=“auto”):
        """
        核心处理函数:加载音频并调用模型进行识别。
        """
        # 1. 构建完整的音频文件路径
        input_dir = folder_paths.get_input_directory()
        audio_path = os.path.join(input_dir, audio_file)
        
        # 2. 检查文件是否存在
        if not os.path.exists(audio_path):
            raise FileNotFoundError(f“音频文件未找到: {audio_path}”)
        
        # 3. 懒加载模型管道
        if SenseVoiceSmall._pipe is None:
            print(“[SenseVoiceSmall] 正在加载模型,首次使用可能需要一些时间...”)
            try:
                # 使用ModelScope的pipeline加载SenseVoice-Small模型
                SenseVoiceSmall._pipe = pipeline(
                    task=Tasks.auto_speech_recognition,
                    model=“iic/SenseVoiceSmall”,
                    device=“cuda:0” if torch.cuda.is_available() else “cpu”,
                )
                print(“[SenseVoiceSmall] 模型加载完毕。”)
            except Exception as e:
                print(f“[SenseVoiceSmall] 模型加载失败: {e}”)
                return (“模型加载失败,请检查依赖和环境。”,)
        
        # 4. 执行语音识别
        print(f“[SenseVoiceSmall] 正在识别: {audio_file}, 语言: {language}”)
        try:
            # 调用管道进行识别,传入语言参数
            rec_result = SenseVoiceSmall._pipe(
                audio_in=audio_path,
                batch_size_s=300, # 批处理大小,影响内存和速度
                language=language if language != “auto” else None, # 模型内部处理auto
            )
            # 提取识别文本
            recognized_text = rec_result.get(“text”, “”)
            print(f“[SenseVoiceSmall] 识别完成: {recognized_text[:50]}...” if len(recognized_text) > 50 else f”...“)
        except Exception as e:
            print(f“[SenseVoiceSmall] 识别过程出错: {e}”)
            recognized_text = f“识别出错: {e}”
        
        # 5. 返回结果,必须是一个元组,且与RETURN_TYPES对应
        return (recognized_text,)

这是节点的核心逻辑:

  1. 拼接出音频文件的绝对路径。
  2. 进行基本的文件检查。
  3. 懒加载模型:只有第一次运行节点时才会加载模型,后续调用会复用,极大提升工作流执行效率。
  4. 调用pipeline进行语音识别。batch_size_s参数可以根据你的硬件调整,值越大处理越快,但占用内存越多。
  5. 从结果中提取文本并返回。返回的必须是一个元组(recognized_text,)

第四部分:节点注册与额外功能

为了让ComfyUI发现我们的节点,需要在文件末尾添加一个节点列表。

# 所有自定义节点都必须在这个列表中声明
NODE_CLASS_MAPPINGS = {
    “SenseVoiceSmall”: SenseVoiceSmall
}

# 节点显示名称的映射(可选)
NODE_DISPLAY_NAME_MAPPINGS = {
    “SenseVoiceSmall”: “SenseVoice Small 语音识别”
}

至此,一个功能完整的自定义节点就编写完成了。将nodes.py文件保存。

3. 测试与集成:让节点跑起来

代码写好了,但它真的能在ComfyUI里用吗?我们来测试一下。

3.1 启动ComfyUI并查找节点

  1. 重启你的ComfyUI服务。如果之前是启动状态,需要关闭后重新运行python main.py
  2. 打开ComfyUI的Web界面。
  3. 在节点菜单中,找到我们定义的CATEGORY,也就是”audio”分类。你应该能看到一个名为”SenseVoice Small 语音识别”的节点(如果你设置了NODE_DISPLAY_NAME_MAPPINGS),或者直接叫”SenseVoiceSmall”
  4. 把它拖到画布上。

3.2 配置节点并运行

  1. 准备音频:将你想要识别的音频文件(如my_audio.wav)放入ComfyUI根目录下的input文件夹。
  2. 配置节点:点击画布上的SenseVoiceSmall节点,在右侧的属性面板中,audio_file下拉框里应该会出现你刚放入的my_audio.wav文件,选择它。你还可以选择识别语言。
  3. 连接输出:从节点的输出插座text拉出一根线,可以连接到一个Show Text节点(用于在界面上显示文本),或者连接到任何其他接受字符串输入的节点,比如一个CLIP Text Encode节点,为文生图提供提示词!
  4. 执行:点击Queue Prompt按钮。在后台终端里,你应该能看到模型加载和识别的打印信息。稍等片刻,识别出的文本就会传递到下游节点。

3.3 集成到复杂工作流

这才是自定义节点的魅力所在。现在,你可以发挥创意,构建自动化流程了:

  • 声控AI绘画麦克风录音 -> 保存音频到input文件夹 -> SenseVoiceSmall节点 -> CLIP文本编码器 -> K采样器。对着麦克风说“一只在星空下奔跑的狐狸”,工作流就能自动生成这幅画。
  • 播客内容可视化:将一段播客音频切片,批量通过SenseVoiceSmall节点转成文字,再将每一段文字描述生成对应的概念图,快速制作播客的图文摘要。
  • 视频配音字幕提取与重绘:从视频中提取音频,识别成字幕文本,再用文本分析节点提取关键词,生成新的配图或视频风格化素材。

4. 进阶优化与问题排查

一个能跑的节点是基础,一个健壮、好用的节点才是目标。这里有一些进阶建议。

4.1 提升节点健壮性

我们的基础代码已经包含了错误处理,但还可以加强:

  • 音频格式兼容:可以集成pydubffmpeg库,在节点内部自动转换不支持的音频格式为WAV格式,再交给模型处理。
  • 进度提示:对于长音频,模型处理需要时间。可以尝试利用ComfyUI的进度条功能,给用户更友好的反馈。
  • 模型配置化:将model=“iic/SenseVoiceSmall”这类参数也放到INPUT_TYPES中作为可选参数,让高级用户可以切换不同的模型版本。

4.2 常见问题与解决

  • 节点不显示:检查custom_nodes目录结构是否正确,nodes.py文件名是否拼写准确,NODE_CLASS_MAPPINGS字典是否正确。重启ComfyUI。
  • 模型加载失败
    • 检查网络,首次加载需要从ModelScope下载模型。
    • 检查modelscopefunasr版本兼容性。
    • 查看终端完整的错误信息。
  • 识别结果为空或乱码
    • 检查音频文件是否损坏,或是否为静音文件。
    • 尝试调整language参数,明确指定”zh””en”
    • 对于嘈杂环境下的音频,识别效果会下降,这是模型本身的限制。

获取更多AI镜像

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

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐