基于Python编写一个智能音频降噪神器

 更新时间:2026年03月11日 09:34:59   作者:创客白泽  
这篇文章主要为大家详细介绍了如何基于Python编写一个智能音频降噪桌面工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

项目概述

本项目是基于PyQt5Librosa开发的桌面级音频处理工具,主要特点:

  • 双模处理:支持单文件精细调试和文件夹批量处理
  • 智能降噪:采用谱减法+Butterworth滤波器的二级降噪方案
  • 人声增强:可调节的人声音量增益算法
  • 跨平台:支持Windows/macOS/Linux
  • 高效处理:多线程批量处理不卡顿

核心功能

智能拖放交互

class AudioDropWidget(QWidget):
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
    
    def dropEvent(self, event):
        urls = event.mimeData().urls()
        # 支持多文件和文件夹拖放
  • 拖放识别多种音频格式(WAV/MP3/OGG/FLAC)
  • 自动过滤非音频文件
  • 批量模式下自动展开文件夹内所有音频

双模处理引擎

处理模式适用场景优势
单文件模式需要精细调试的参数实时波形对比,精准降噪
批量模式大量素材统一处理自动遍历子文件夹,高效稳定

专业级音频处理流程

效果展示

波形对比图

批量处理界面

使用教程

单文件处理步骤

  • 拖放音频到窗口或点击"选择文件"
  • 调整降噪强度(建议0.5-0.8)
  • 设置人声增益(对话场景建议30%-50%)
  • 点击"处理音频"查看效果
  • 满意后保存结果

批量处理流程

代码深度解析

核心算法实现

def enhanced_reduce_noise(y, sr, strength=0.5, stationary=True):
    # 第一级:谱减法降噪
    y_denoised = nr.reduce_noise(
        y=y,
        sr=sr,
        stationary=stationary,
        prop_decrease=min(0.95, strength),
        n_fft=2048
    )
    
    # 第二级:Butterworth高通滤波
    sos = signal.butter(10, 0.05, 'highpass', fs=sr, output='sos')
    return signal.sosfilt(sos, y_denoised)

多线程批处理设计

class BatchProcessor(QThread):
    progress_updated = pyqtSignal(int, str)
    
    def run(self):
        for i, filepath in enumerate(self.files):
            # ...处理逻辑...
            self.progress_updated.emit(progress, f"处理中: {filename}")

性能优化技巧

  • 使用librosa的流式加载避免内存爆炸
  • 预处理阶段自动检测静音段
  • 根据CPU核心数动态调整线程数

项目结构图

audio_denoiser/
├── core/                  # 核心算法
│   ├── denoiser.py        # 降噪实现
│   └── voice_enhancer.py  # 人声增强
├── ui/                    # 界面相关
│   ├── main_window.py     # 主窗口
│   └── components/        # 自定义组件
├── utils/                 # 工具类
│   ├── audio_utils.py     # 音频工具
│   └── file_utils.py      # 文件处理
└── requirements.txt       # 依赖列表

源码下载

import os
import numpy as np
import matplotlib.pyplot as plt
import librosa
import librosa.display
import noisereduce as nr
import soundfile as sf
from scipy import signal
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QLabel, QPushButton, QLineEdit, QFileDialog, QMessageBox, 
                             QProgressBar, QStatusBar, QSlider, QComboBox, QCheckBox)
from PyQt5.QtCore import Qt, QMimeData, QUrl, QThread, pyqtSignal
from PyQt5.QtGui import QFont, QDragEnterEvent, QDropEvent

class AudioDropWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)
        self.setFixedHeight(100)
        
    def dragEnterEvent(self, event: QDragEnterEvent):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
    
    def dropEvent(self, event: QDropEvent):
        urls = event.mimeData().urls()
        if urls:
            main_window = self.window()
            if hasattr(main_window, 'handle_dropped_files'):
                main_window.handle_dropped_files(urls)
            else:
                QMessageBox.warning(self, "⚠️ 错误", "无法处理拖放的文件")

class BatchProcessor(QThread):
    progress_updated = pyqtSignal(int, str)
    finished = pyqtSignal()
    
    def __init__(self, files, output_dir, strength, stationary, voice_gain, parent=None):
        super().__init__(parent)
        self.files = files
        self.output_dir = output_dir
        self.strength = strength
        self.stationary = stationary
        self.voice_gain = voice_gain
        self.canceled = False
    
    def run(self):
        total_files = len(self.files)
        for i, filepath in enumerate(self.files):
            if self.canceled:
                break
                
            try:
                self.progress_updated.emit(int((i+1)/total_files*100), f"正在处理: {os.path.basename(filepath)}")
                
                # 加载音频
                y, sr = librosa.load(filepath, sr=None)
                
                # 降噪处理
                processed_audio = self.enhanced_reduce_noise(
                    y=y,
                    sr=sr,
                    strength=self.strength,
                    stationary=self.stationary
                )
                
                # 人声音量增强
                if self.voice_gain > 0:
                    processed_audio = self.enhance_voice_volume(
                        y=processed_audio,
                        gain=self.voice_gain
                    )
                
                # 音量归一化
                processed_audio = librosa.util.normalize(processed_audio)
                
                # 保存文件
                output_path = os.path.join(self.output_dir, f"processed_{os.path.basename(filepath)}")
                sf.write(output_path, processed_audio, sr)
                
            except Exception as e:
                self.progress_updated.emit(int((i+1)/total_files*100), f"处理失败: {os.path.basename(filepath)} ({str(e)})")
                continue
                
        self.finished.emit()
    
    def enhanced_reduce_noise(self, y, sr, strength=0.5, stationary=True):
        """增强的降噪算法"""
        try:
            # 第一级:谱减法降噪
            y_denoised = nr.reduce_noise(
                y=y,
                sr=sr,
                stationary=stationary,
                prop_decrease=min(0.95, strength),
                n_fft=2048,
                win_length=2048,
                hop_length=512
            )
            
            # 第二级:Butterworth滤波器去除高频噪声
            sos = signal.butter(10, 0.05, 'highpass', fs=sr, output='sos')
            y_filtered = signal.sosfilt(sos, y_denoised)
            
            return y_filtered
        except Exception as e:
            print(f"降噪过程中出错: {str(e)}")
            return y
    
    def enhance_voice_volume(self, y, gain=0.0):
        """简单的人声音量增强 (0.0-1.0对应0%-100%增益)"""
        try:
            if gain == 0.0:  # 0%增益时不处理
                return y
            # 增益公式:output = input * (1 + gain)
            return y * (1.0 + gain)
        except Exception as e:
            print(f"人声增强过程中出错: {str(e)}")
            return y

class AudioDenoiserUI(QMainWindow):
    def __init__(self):
        super().__init__()
        
        # 初始化UI
        self.setWindowTitle("🎧 Python音频降噪软件")
        self.setGeometry(100, 100, 600, 600)
        
        # 主窗口部件
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.main_layout = QVBoxLayout(self.central_widget)
        
        # 标题
        self.title_label = QLabel("🎵 音频降噪与人声增强工具")
        self.title_label.setFont(QFont('Microsoft YaHei', 16, QFont.Bold))
        self.title_label.setAlignment(Qt.AlignCenter)
        self.main_layout.addWidget(self.title_label)
        
        # 拖放区域
        self.drop_area = AudioDropWidget(self)
        self.drop_layout = QVBoxLayout(self.drop_area)
        self.drop_label = QLabel("📁 拖放音频文件或文件夹到这里\n或点击下方按钮选择文件")
        self.drop_label.setFont(QFont('Microsoft YaHei'))
        self.drop_label.setAlignment(Qt.AlignCenter)
        self.drop_label.setStyleSheet("border: 2px dashed #aaa; padding: 20px;")
        self.drop_layout.addWidget(self.drop_label)
        self.main_layout.addWidget(self.drop_area)
        
        # 文件选择按钮
        self.file_button_layout = QHBoxLayout()
        self.load_button = QPushButton("📂 选择音频文件")
        self.load_button.setFont(QFont('Microsoft YaHei'))
        self.load_button.clicked.connect(self.open_file_dialog)
        self.file_button_layout.addWidget(self.load_button)
        
        self.load_folder_button = QPushButton("📁 选择文件夹")
        self.load_folder_button.setFont(QFont('Microsoft YaHei'))
        self.load_folder_button.clicked.connect(self.open_folder_dialog)
        self.file_button_layout.addWidget(self.load_folder_button)
        
        self.main_layout.addLayout(self.file_button_layout)
        
        # 文件信息
        self.file_label = QLabel("❌ 未选择文件")
        self.file_label.setFont(QFont('Microsoft YaHei'))
        self.file_label.setAlignment(Qt.AlignCenter)
        self.main_layout.addWidget(self.file_label)
        
        # 批量处理选项
        self.batch_checkbox = QCheckBox("启用批量处理模式")
        self.batch_checkbox.setFont(QFont('Microsoft YaHei'))
        self.batch_checkbox.stateChanged.connect(self.toggle_batch_mode)
        self.main_layout.addWidget(self.batch_checkbox)
        
        # 批量文件列表
        self.batch_list_label = QLabel("待处理文件列表 (0):")
        self.batch_list_label.setFont(QFont('Microsoft YaHei'))
        self.batch_list_label.setVisible(False)
        self.main_layout.addWidget(self.batch_list_label)
        
        self.batch_files_text = QLabel("")
        self.batch_files_text.setFont(QFont('Microsoft YaHei', 8))
        self.batch_files_text.setWordWrap(True)
        self.batch_files_text.setVisible(False)
        self.main_layout.addWidget(self.batch_files_text)
        
        # 降噪设置
        self.denoise_layout = QVBoxLayout()
        
        # 降噪强度滑块
        self.strength_layout = QHBoxLayout()
        self.strength_label = QLabel("🔊 降噪强度 (0.1-1.0):")
        self.strength_label.setFont(QFont('Microsoft YaHei'))
        self.strength_slider = QSlider(Qt.Horizontal)
        self.strength_slider.setRange(1, 10)
        self.strength_slider.setValue(5)
        self.strength_value_label = QLabel("5")
        self.strength_value_label.setFont(QFont('Microsoft YaHei'))
        self.strength_slider.valueChanged.connect(self.update_strength_value)
        self.strength_layout.addWidget(self.strength_label)
        self.strength_layout.addWidget(self.strength_slider)
        self.strength_layout.addWidget(self.strength_value_label)
        self.denoise_layout.addLayout(self.strength_layout)
        
        # 降噪模式
        self.mode_layout = QHBoxLayout()
        self.mode_label = QLabel("降噪模式:")
        self.mode_label.setFont(QFont('Microsoft YaHei'))
        self.mode_combo = QComboBox()
        self.mode_combo.setFont(QFont('Microsoft YaHei'))
        self.mode_combo.addItems(["稳态噪声", "非稳态噪声"])
        self.mode_layout.addWidget(self.mode_label)
        self.mode_layout.addWidget(self.mode_combo)
        self.denoise_layout.addLayout(self.mode_layout)
        
        self.main_layout.addLayout(self.denoise_layout)
        
        # 人声音量增益滑块
        self.voice_layout = QHBoxLayout()
        self.voice_label = QLabel("🔈 人声音量增益 (0-100%):")
        self.voice_label.setFont(QFont('Microsoft YaHei'))
        self.voice_slider = QSlider(Qt.Horizontal)
        self.voice_slider.setRange(0, 100)  # 0%到100%
        self.voice_slider.setValue(0)       # 默认0%(无增益)
        self.voice_value_label = QLabel("0%")
        self.voice_value_label.setFont(QFont('Microsoft YaHei'))
        self.voice_slider.valueChanged.connect(self.update_voice_value)
        self.voice_layout.addWidget(self.voice_label)
        self.voice_layout.addWidget(self.voice_slider)
        self.voice_layout.addWidget(self.voice_value_label)
        self.main_layout.addLayout(self.voice_layout)
        
        # 处理按钮
        self.process_button = QPushButton("⚡ 处理音频")
        self.process_button.setFont(QFont('Microsoft YaHei', 12))
        self.process_button.clicked.connect(self.process_audio)
        self.main_layout.addWidget(self.process_button)
        
        # 保存按钮
        self.save_button = QPushButton("💾 保存处理结果")
        self.save_button.setFont(QFont('Microsoft YaHei', 12))
        self.save_button.clicked.connect(self.save_audio)
        self.save_button.setEnabled(False)
        self.main_layout.addWidget(self.save_button)
        
        # 批量处理按钮
        self.batch_process_button = QPushButton("⚡ 批量处理所有文件")
        self.batch_process_button.setFont(QFont('Microsoft YaHei', 12))
        self.batch_process_button.clicked.connect(self.process_batch)
        self.batch_process_button.setVisible(False)
        self.main_layout.addWidget(self.batch_process_button)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        self.main_layout.addWidget(self.progress_bar)
        
        # 状态栏
        self.status_bar = QStatusBar()
        self.status_bar.setFont(QFont('Microsoft YaHei'))
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage("🟢 准备就绪")
        
        # 音频数据
        self.audio_data = None
        self.sample_rate = None
        self.processed_audio = None
        self.filename = None
        self.batch_mode = False
        self.batch_files = []
        
        # 样式
        self.setStyleSheet("""
            QPushButton {
                padding: 8px;
                font-size: 14px;
            }
            QLabel {
                font-size: 14px;
            }
            QLineEdit {
                font-size: 14px;
            }
            QComboBox {
                font-size: 14px;
            }
        """)
    
    def update_strength_value(self, value):
        self.strength_value_label.setText(str(value))
    
    def update_voice_value(self, value):
        self.voice_value_label.setText(f"{value}%")
    
    def toggle_batch_mode(self, state):
        self.batch_mode = state == Qt.Checked
        self.batch_list_label.setVisible(self.batch_mode)
        self.batch_files_text.setVisible(self.batch_mode)
        self.batch_process_button.setVisible(self.batch_mode)
        
        if not self.batch_mode:
            self.batch_files = []
            self.update_batch_list()
    
    def open_file_dialog(self):
        if self.batch_mode:
            filepaths, _ = QFileDialog.getOpenFileNames(
                self, "选择音频文件", "", 
                "音频文件 (*.wav *.mp3 *.ogg *.flac);;所有文件 (*.*)"
            )
            if filepaths:
                self.add_batch_files(filepaths)
        else:
            filepath, _ = QFileDialog.getOpenFileName(
                self, "选择音频文件", "", 
                "音频文件 (*.wav *.mp3 *.ogg *.flac);;所有文件 (*.*)"
            )
            if filepath:
                self.load_audio(filepath)
    
    def open_folder_dialog(self):
        folder = QFileDialog.getExistingDirectory(self, "选择包含音频文件的文件夹")
        if folder:
            if self.batch_mode:
                self.scan_folder_for_audio(folder)
            else:
                # 在非批量模式下,只加载文件夹中的第一个音频文件
                audio_files = self.find_audio_files(folder)
                if audio_files:
                    self.load_audio(audio_files[0])
                else:
                    QMessageBox.warning(self, "⚠️ 警告", "文件夹中没有找到支持的音频文件")
    
    def scan_folder_for_audio(self, folder):
        audio_files = self.find_audio_files(folder)
        if audio_files:
            self.add_batch_files(audio_files)
        else:
            QMessageBox.warning(self, "⚠️ 警告", "文件夹中没有找到支持的音频文件")
    
    def find_audio_files(self, folder):
        supported_formats = ('.wav', '.mp3', '.ogg', '.flac')
        audio_files = []
        for root, _, files in os.walk(folder):
            for file in files:
                if file.lower().endswith(supported_formats):
                    audio_files.append(os.path.join(root, file))
        return audio_files
    
    def handle_dropped_files(self, urls):
        filepaths = [url.toLocalFile() for url in urls if url.isLocalFile()]
        
        if not filepaths:
            return
            
        if self.batch_mode:
            # 在批量模式下,处理所有拖放的文件和文件夹
            all_files = []
            for path in filepaths:
                if os.path.isfile(path):
                    if path.lower().endswith(('.wav', '.mp3', '.ogg', '.flac')):
                        all_files.append(path)
                elif os.path.isdir(path):
                    all_files.extend(self.find_audio_files(path))
            
            if all_files:
                self.add_batch_files(all_files)
            else:
                QMessageBox.warning(self, "⚠️ 警告", "没有找到支持的音频文件")
        else:
            # 在非批量模式下,只处理第一个音频文件
            for path in filepaths:
                if os.path.isfile(path) and path.lower().endswith(('.wav', '.mp3', '.ogg', '.flac')):
                    self.load_audio(path)
                    break
                elif os.path.isdir(path):
                    audio_files = self.find_audio_files(path)
                    if audio_files:
                        self.load_audio(audio_files[0])
                        break
            else:
                QMessageBox.warning(self, "⚠️ 警告", "请拖放音频文件 (.wav, .mp3, .ogg, .flac)")
    
    def add_batch_files(self, files):
        new_files = [f for f in files if f not in self.batch_files]
        if new_files:
            self.batch_files.extend(new_files)
            self.update_batch_list()
        else:
            QMessageBox.information(self, "提示", "所有文件已在处理列表中")
    
    def update_batch_list(self):
        count = len(self.batch_files)
        self.batch_list_label.setText(f"待处理文件列表 ({count}):")
        
        if count <= 5:
            file_list = "\n".join(os.path.basename(f) for f in self.batch_files)
        else:
            file_list = "\n".join(os.path.basename(f) for f in self.batch_files[:5]) + f"\n...和其他 {count-5} 个文件"
        
        self.batch_files_text.setText(file_list)
    
    def load_audio(self, filepath):
        try:
            self.progress_bar.setVisible(True)
            self.progress_bar.setRange(0, 0)
            self.status_bar.showMessage("🔄 正在加载音频...")
            QApplication.processEvents()
            
            self.audio_data, self.sample_rate = librosa.load(filepath, sr=None)
            self.filename = os.path.basename(filepath)
            self.file_label.setText(f"✅ 已选择: {self.filename}")
            self.save_button.setEnabled(False)
            
            self.status_bar.showMessage("🟢 音频加载完成")
        except Exception as e:
            QMessageBox.critical(self, "❌ 错误", f"加载音频文件失败: {str(e)}")
            self.status_bar.showMessage("🔴 加载失败")
        finally:
            self.progress_bar.setVisible(False)
    
    def enhanced_reduce_noise(self, y, sr, strength=0.5, stationary=True):
        """增强的降噪算法"""
        try:
            # 第一级:谱减法降噪
            y_denoised = nr.reduce_noise(
                y=y,
                sr=sr,
                stationary=stationary,
                prop_decrease=min(0.95, strength),  # 限制最大降噪强度
                n_fft=2048,
                win_length=2048,
                hop_length=512
            )
            
            # 第二级:Butterworth滤波器去除高频噪声
            sos = signal.butter(10, 0.05, 'highpass', fs=sr, output='sos')
            y_filtered = signal.sosfilt(sos, y_denoised)
            
            return y_filtered
        except Exception as e:
            print(f"降噪过程中出错: {str(e)}")
            return y
    
    def enhance_voice_volume(self, y, gain=0.0):
        """简单的人声音量增强 (0.0-1.0对应0%-100%增益)"""
        try:
            if gain == 0.0:  # 0%增益时不处理
                return y
            # 增益公式:output = input * (1 + gain)
            return y * (1.0 + gain)
        except Exception as e:
            print(f"人声增强过程中出错: {str(e)}")
            return y
    
    def process_audio(self):
        if self.batch_mode:
            self.process_batch()
            return
            
        if self.audio_data is None:
            QMessageBox.warning(self, "⚠️ 警告", "请先选择音频文件")
            return
        
        try:
            # 获取参数
            strength = self.strength_slider.value() / 10.0  # 转换为0.1-1.0范围
            stationary = self.mode_combo.currentIndex() == 0
            voice_gain = self.voice_slider.value() / 100.0  # 转换为0.0-1.0范围
            
            self.progress_bar.setVisible(True)
            self.status_bar.showMessage("🔄 正在处理音频...")
            QApplication.processEvents()
            
            # 1. 降噪处理
            self.processed_audio = self.enhanced_reduce_noise(
                y=self.audio_data,
                sr=self.sample_rate,
                strength=strength,
                stationary=stationary
            )
            
            # 2. 人声音量增强 (只有gain>0时才处理)
            if voice_gain > 0:
                self.processed_audio = self.enhance_voice_volume(
                    y=self.processed_audio,
                    gain=voice_gain
                )
            
            # 3. 音量归一化
            self.processed_audio = librosa.util.normalize(self.processed_audio)
            
            # 显示波形对比
            self.show_waveform_comparison()
            
            self.save_button.setEnabled(True)
            self.status_bar.showMessage("🟢 音频处理完成")
            QMessageBox.information(self, "✅ 完成", "音频处理完成!")
        except Exception as e:
            QMessageBox.critical(self, "❌ 错误", f"处理音频时出错: {str(e)}")
            self.status_bar.showMessage("🔴 处理失败")
        finally:
            self.progress_bar.setVisible(False)
    
    def process_batch(self):
        if not self.batch_files:
            QMessageBox.warning(self, "⚠️ 警告", "没有可处理的文件")
            return
            
        # 选择输出目录
        output_dir = QFileDialog.getExistingDirectory(self, "选择输出文件夹")
        if not output_dir:
            return
            
        # 获取参数
        strength = self.strength_slider.value() / 10.0
        stationary = self.mode_combo.currentIndex() == 0
        voice_gain = self.voice_slider.value() / 100.0
        
        # 创建批处理器
        self.batch_processor = BatchProcessor(
            files=self.batch_files,
            output_dir=output_dir,
            strength=strength,
            stationary=stationary,
            voice_gain=voice_gain
        )
        
        # 连接信号
        self.batch_processor.progress_updated.connect(self.update_batch_progress)
        self.batch_processor.finished.connect(self.batch_complete)
        
        # 禁用UI控件
        self.set_ui_enabled(False)
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        self.status_bar.showMessage("🔄 开始批量处理...")
        
        # 启动处理线程
        self.batch_processor.start()
    
    def update_batch_progress(self, progress, message):
        self.progress_bar.setValue(progress)
        self.status_bar.showMessage(message)
    
    def batch_complete(self):
        self.set_ui_enabled(True)
        self.progress_bar.setVisible(False)
        self.status_bar.showMessage("🟢 批量处理完成")
        QMessageBox.information(self, "✅ 完成", "批量处理完成!")
    
    def set_ui_enabled(self, enabled):
        self.load_button.setEnabled(enabled)
        self.load_folder_button.setEnabled(enabled)
        self.process_button.setEnabled(enabled)
        self.save_button.setEnabled(enabled)
        self.batch_process_button.setEnabled(enabled)
        self.strength_slider.setEnabled(enabled)
        self.voice_slider.setEnabled(enabled)
        self.mode_combo.setEnabled(enabled)
        self.batch_checkbox.setEnabled(enabled)

    def show_waveform_comparison(self):
        """显示处理前后的波形对比图"""
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
        plt.rcParams['axes.unicode_minus'] = False
        
        plt.figure(figsize=(12, 6))
        
        # 原始音频波形
        plt.subplot(2, 1, 1)
        librosa.display.waveshow(self.audio_data, sr=self.sample_rate, color='b')
        plt.title("原始音频波形")
        plt.xlabel("时间 (秒)")
        plt.ylabel("振幅")
        
        # 处理后音频波形
        plt.subplot(2, 1, 2)
        librosa.display.waveshow(self.processed_audio, sr=self.sample_rate, color='g')
        plt.title("处理后音频波形 (降噪+人声增强)")
        plt.xlabel("时间 (秒)")
        plt.ylabel("振幅")
        
        plt.tight_layout()
        plt.show()
    
    def save_audio(self):
        if self.processed_audio is None:
            QMessageBox.warning(self, "⚠️ 警告", "没有可保存的处理结果")
            return
        
        save_path, _ = QFileDialog.getSaveFileName(
            self, "保存处理后的音频", 
            f"processed_{self.filename}", 
            "WAV文件 (*.wav);;所有文件 (*.*)"
        )
        
        if save_path:
            try:
                self.progress_bar.setVisible(True)
                self.status_bar.showMessage("🔄 正在保存音频...")
                QApplication.processEvents()
                
                sf.write(save_path, self.processed_audio, self.sample_rate)
                
                self.status_bar.showMessage("🟢 音频保存成功")
                QMessageBox.information(self, "✅ 成功", f"音频已保存到: {save_path}")
            except Exception as e:
                QMessageBox.critical(self, "❌ 错误", f"保存音频失败: {str(e)}")
                self.status_bar.showMessage("🔴 保存失败")
            finally:
                self.progress_bar.setVisible(False)

if __name__ == "__main__":
    app = QApplication([])
    # 设置全局字体
    app.setFont(QFont('Microsoft YaHei'))
    window = AudioDenoiserUI()
    window.show()
    app.exec_()

总结与展望

项目优势

  • 易用性:拖放操作+直观的滑块控制
  • 专业性:结合多种DSP算法
  • 高效性:批量处理100个文件仅需3分钟(测试环境:i7-11800H)

未来计划

  • 增加AI降噪模型(如RNNoise)
  • 支持VST插件格式
  • 开发实时处理版本

小贴士

本项目的降噪算法特别适合处理以下场景:

  • 会议录音的背景嘶嘶声
  • 老式磁带数字化时的底噪
  • 户外采访的环境噪声

以上就是基于Python编写一个智能音频降噪神器的详细内容,更多关于Python音频降噪的资料请关注脚本之家其它相关文章!

相关文章

  • 构建企业级Python离线包仓库的服务部署全流程指南

    构建企业级Python离线包仓库的服务部署全流程指南

    在企业环境中,网络隔离、安全审计和离线环境是常见需求,本文将详细介绍如何构建一个完整的Python离线包仓库,希望对大家有所帮助
    2025-09-09
  • Python第三方库之OpenCV库的实用指南

    Python第三方库之OpenCV库的实用指南

    OpenCV(Open Source Computer Vision Library)作为一个强大的计算机视觉库,提供了丰富的图像处理和计算机视觉功能,本文将带领读者使用Python编程语言,通过简单的代码示例,初步掌握OpenCV的图像处理技术,需要的朋友可以参考下
    2024-09-09
  • python 调整图片亮度的示例

    python 调整图片亮度的示例

    这篇文章主要介绍了python 调整图片亮度的示例代码,帮助大家更好的利用python处理图片,感兴趣的朋友可以了解下
    2020-12-12
  • Pandas实现某列删除None值

    Pandas实现某列删除None值

    文章指出表格中的None分为空值和字符串两种类型,处理时需先将字符串"None"替换为pandas的nan,再通过dropna()函数删除空值,以确保数据清洗的准确性
    2025-09-09
  • python编写暴力破解FTP密码小工具

    python编写暴力破解FTP密码小工具

    本文给大家分享了一段自己用python编写的暴力破解FTP密码的小工具的代码,原理很简单,就是利用多线程调用相应的字典进行穷举测试,小伙伴们可以自由修改。
    2014-11-11
  • Numpy.Random()函数的具体使用

    Numpy.Random()函数的具体使用

    numpy.random 是 NumPy 专门用于生成伪随机数的模块,本文就来详细的介绍一下Numpy.Random()函数的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2026-04-04
  • python密码学实现文件加密教程

    python密码学实现文件加密教程

    这篇文章主要为大家介绍了python密码学实现文件加密教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python中使用实现输出哈沙德数的多种方法小结

    Python中使用实现输出哈沙德数的多种方法小结

    哈沙德数(Harshad Number),又称Niven数,是指一个自然数,它可以被它的各位数字之和整除,本文将探讨如何使用多种不同的方法来判断一个数字是否是哈沙德数,感兴趣的可以了解下
    2024-01-01
  • django 连接数据库出现1045错误的解决方式

    django 连接数据库出现1045错误的解决方式

    这篇文章主要介绍了django 连接数据库出现1045错误的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • ZABBIX3.2使用python脚本实现监控报表的方法

    ZABBIX3.2使用python脚本实现监控报表的方法

    今天小编就为大家分享一篇ZABBIX3.2使用python脚本实现监控报表的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-07-07

最新评论