python_检测音频人声片段

python_检测音频人声片段

对声源有要求,不一定所有音频的识别结果都是我们想要的

python 复制代码
# 使用此指令前,请确保安装必要的Python库,例如使用以下命令安装:
# pip install librosa numpy

import librosa
import numpy as np

from typing import *
try:
    from xbot.app.logging import trace as print
except:
    from xbot import print


def detect_voice_segments(audio_path):
    """
    title: 检测音频人声片段
    description: 检测音频文件中所有人声片段的起止时间,基于短时能量算法识别有效人声区域,过滤噪声干扰,返回以微秒为单位的时间段列表。
    inputs:
        - audio_path (file): 音频文件路径,eg: "audio.mp3"
    outputs:
        - voice_segments (list): 人声片段时间列表,每个元素为[起始微秒, 结束微秒],eg: "[[1000000, 3500000], [5000000, 8200000]]"
    """
    
    def _seconds_to_microseconds(seconds):
        """
        将秒数转换为微秒(1秒 = 1000000微秒)
        """
        seconds = float(seconds)
        return int(round(seconds * 1000000))
    
    # 检测参数配置
    threshold = 0.05        # 能量阈值,低于则视为静音
    min_voice_dur = 0.1     # 最小有效人声时长(秒),过滤噪声

    try:
        # 1. 加载音频
        y, sr = librosa.load(audio_path, sr=None)
        total_samples = len(y)
        total_seconds = total_samples / sr

        # 2. 计算短时能量(RMS)
        frame_length = 2048
        hop_length = 512
        energy = librosa.feature.rms(y=y, frame_length=frame_length, hop_length=hop_length).flatten()
        times = librosa.frames_to_time(np.arange(len(energy)), sr=sr, hop_length=hop_length)

        # 3. 判断每帧是否为人声
        is_voice = energy > threshold

        # 4. 合并连续人声段(简单状态机)
        segments = []
        in_voice = False
        start_frame = None

        for i, voice in enumerate(is_voice):
            if voice and not in_voice:
                # 进入人声
                in_voice = True
                start_frame = i
            elif not voice and in_voice:
                # 离开人声
                end_frame = i - 1
                segments.append((start_frame, end_frame))
                in_voice = False

        # 处理结尾仍为人声的情况
        if in_voice:
            segments.append((start_frame, len(is_voice) - 1))

        # 5. 转换为时间并过滤太短的段
        valid_segments = []

        for start_f, end_f in segments:
            start_t = times[start_f]
            end_t = times[end_f] + hop_length / sr  # 补偿最后一帧的时间偏移
            # 确保不超出总时长
            end_t = min(end_t, total_seconds)
            
            if (end_t - start_t) >= min_voice_dur:
                start_us = _seconds_to_microseconds(start_t)
                end_us = _seconds_to_microseconds(end_t)
                valid_segments.append([start_us, end_us])

        return valid_segments

    except Exception as e:
        raise Exception(f"处理音频文件时出错:{str(e)}")
相关推荐
小徐不徐说5 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
ragnwang6 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
王中阳Go6 小时前
后端转 Agent 岗面试怎么答:8 个高频问题与应答口径
人工智能·后端·python·大语言模型
Wang's Blog6 小时前
Java 项目实战: 交友项目 - 搜索附近的功能概述和分析
java·开发语言·交友
骑着蜗牛撵大象3276 小时前
大模型 Agent 的沙箱护栏:gVisor 隔离、出口白名单与审计闭环
java·开发语言·jvm·安全·agent沙箱·gvisor·microvm
weixin_307779137 小时前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
Dxy12393102167 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷7 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
云和数据.ChenGuang7 小时前
深入解析 Python 的 dir():从用法到 CPython 源码实现
开发语言·人工智能·python·langchain
nice_lcj5208 小时前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试