# 音频文件LUFS响度归一化工具 **Repository Path**: lswjx/SetLufs ## Basic Information - **Project Name**: 音频文件LUFS响度归一化工具 - **Description**: 一个基于 WPF + FFmpeg 的音频响度归一化工具,支持批量扫描和将音频文件调整到统一的 LUFS 响度标准。 - **Primary Language**: C# - **License**: MIT - **Default Branch**: master - **Homepage**: https://gitee.com/lswjx/SetLufs - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-07-06 - **Last Updated**: 2026-07-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: 音量, LUFS, 音量调整, 音乐, 音乐LUFS ## README # LUFS 响度归一化工具 SetLufs 是一款专业的音频响度归一化工具,基于 FFmpeg 的 loudnorm 滤镜实现精确的响度测量和调整,帮助您将音频文件统一到目标 LUFS 响度标准。 ### 主要功能 - 响度归一化:批量扫描和处理音频文件,支持 -23 至 -8 LUFS 范围的目标响度设置 - 多格式支持:支持 MP3、FLAC、WAV、DTS、APE 等 20+ 种音频格式 - 文件修复:自动检测并修复损坏的音频文件(MediaPlayer + FFmpeg 双重验证) - 格式转换:支持转换为 FLAC 无损格式或 WAV 无压缩格式 - 封面管理:查看、搜索、获取、浏览和嵌入音乐封面图片,支持批量扫描封面状态 - 音频播放:内置播放器,支持常见格式直接播放,特殊格式自动转码 - 多语言支持:中英文界面一键切换,文件元数据标签亦本地化显示 - 主题切换:支持亮色、暗色和跟随系统三种主题模式(基于 .NET 10 Fluent 主题) ### 技术特点 - 采用 FFmpeg loudnorm 两遍模式,实现高精度响度调整 - 支持 True Peak 限制,防止音频削波 - 根据文件大小自动优化并行处理线程数 - 全程异步处理,UI 流畅无卡顿 - 支持 DTS/APE 等特殊格式自动转换为 FLAC ## 功能特性 - **批量处理**:支持添加文件或整个目录,手动点击扫描开始测量 - **多格式支持**:MP3、FLAC、WAV、AAC、M4A、OGG、OPUS、WMA、AIFF、AU、AC3、DTS、EAC3、MKA、MP2、MPC、TTA、WV、MLP、THD、APE 等 20+ 种音频格式 - **响度扫描**:使用 FFmpeg `loudnorm` 滤镜测量当前响度和真峰值 - **自定义目标响度**:支持 -23 到 -8 LUFS 之间任意值,预置常用流媒体标准 - **自定义限制峰值**:支持 -2.0 到 -0.5 dBFS 之间任意值 - **三种输出模式**: - 输出到子目录(`_normalized`) - 覆盖原文件(带不可恢复提示,选否自动回退到子目录模式) - 输出到指定目录(可自定义输出路径,设置自动保存) - **音频播放**:支持直接播放常见格式(MP3/FLAC/WAV/AAC/M4A/OGG/WMA),DTS 等格式通过 FFmpeg 转码后播放 - **自动优化**:根据文件平均大小自动调整线程数和并发数 - **错误诊断**:处理失败时在状态列显示具体错误信息 - **特殊格式处理**:DTS、APE 文件自动转换为 FLAC 格式(无损压缩,音质相同)并提示用户 - **文件修复**:双重验证(MediaPlayer + FFmpeg 全量解码)检测损坏文件,修复流程为先尝试同格式重编码、失败再走 WAV 中间文件的两步修复法 - **格式转换**:支持批量转换为 FLAC 或 WAV 格式,保持原始采样率、采样大小和声道数 - **封面管理**:支持查看、搜索、获取、浏览和嵌入封面图片;DataGrid 封面列显示「有封面」/「无」状态;可右键「扫描封面」批量刷新封面状态;自动限制封面大小为 1200x1200 像素防止文件损坏 - **元数据保留**:所有处理操作(归一化、转换、修复)均通过 `-map_metadata` 和显式封面流映射保留原文件元数据 - **FFmpeg 自定义路径**:可手动指定 FFmpeg 可执行文件位置 - **多语言支持**:中英文界面一键切换,所有 UI 元素(含工具栏、状态栏、DataGrid 列头、右键菜单、元数据标签)实时更新 - **现代 UI**:基于 .NET 10 Fluent 主题(Mica 背景),菜单栏 + 工具栏 + 进度条 + 文件数显示 + 右键菜单 - **三种主题模式**:亮色 / 暗色 / 跟随系统,支持实时切换 - **自定义对话框**:内置主题适配的消息对话框,替代系统 MessageBox - **软件设置窗口**:集中管理自动扫描、子目录扫描、语言切换、主题切换、输出方式、FFmpeg 路径等设置 - **处理前确认**:开始处理前弹出对话框,显示文件数量和输出方式,确认后再执行 - **帮助文档**:内置 HTML 帮助文档,点击工具栏「帮助」按钮用默认浏览器打开 - **菜单栏 + 快捷键**:顶部菜单栏(文件/操作/转换/工具/帮助)提供完整功能入口,支持 15+ 个全局快捷键(如 Ctrl+O 添加文件、F6 扫描、Ctrl+Enter 处理、Esc 取消等) - **单元测试**:完整的测试覆盖(145 个测试),覆盖所有核心服务(FfmpegService、AudioPlayerService、MusicInfoApiService、LocalizationService) ## 界面布局 主窗口分为五个区域: - **顶部菜单栏**(5 个主菜单):文件(添加文件 / 添加目录 / 移除选中 / 清空列表 / 退出)/ 操作(扫描全部 / 刷新选中 / 开始处理 / 取消 / 修复所有损坏文件 / 扫描封面)/ 转换(转为 FLAC / 转为 WAV)/ 工具(设置 / 主题:亮色/暗色/跟随系统 / 语言:中文/English)/ 帮助(使用帮助 / 关于),菜单项右侧标注快捷键 - **工具栏**(WrapPanel 自动换行):添加文件 / 添加目录 / 删除选中 / 清空列表 | 扫描全部 / 开始处理 / 取消 | 目标响度 / 限制峰值 / 应用到全部 | 设置 / 帮助 / 关于 - **中部主区域**:左侧 DataGrid 文件列表(封面 / 文件名 / 格式 / 文件大小 / 当前响度 / 当前峰值 / 目标响度 / 限制峰值 / 状态,支持列排序;状态列文字颜色随主题和行选中状态自动调整,不再按状态类型着色),右侧封面预览面板(当前封面 + API 获取的封面 + 获取/浏览/应用按钮 + ← 切换 → + 文件元信息) - **底部播放器**:上一首 / 播放暂停 / 停止 / 下一首 + 进度条 + 音量 - **状态栏**:左侧 ℹ️ 图标 + 状态消息,右侧进度条 + 文件数(处理时显示)+ 流媒体响度提示 > 语言切换、输出模式、FFmpeg 状态等设置已迁移至「设置」窗口集中管理。 > 主题基于 .NET 10 官方 `PresentationFramework.Fluent`,窗口无 Background 时自动启用 Mica 背景。 ## 使用说明 ### 1. 准备 FFmpeg 和 FFprobe 程序需要同时配置 **FFmpeg** 和 **FFprobe** 才能运行。首次启动时,如果未找到工具,设置窗口会显示对应的状态。 **注意**:请从 [FFmpeg 官方下载页面](https://ffmpeg.org/download.html) 下载完整的 FFmpeg 包(通常包含 `ffmpeg.exe` 和 `ffprobe.exe`),不要只下载单独的 `ffmpeg.exe`。 **配置步骤**: 1. 打开「⚙️ 设置」→ FFmpeg 分组 2. 点击"浏览 FFmpeg..."按钮,选择 `ffmpeg.exe` 的路径 3. 程序会自动在同一目录下查找 `ffprobe.exe`,找到后会自动配置 4. 如果未找到 `ffprobe.exe`,会弹出提示,请点击"浏览 FFprobe..."按钮手动指定路径 5. 状态均变为绿色即配置成功 ### 2. 添加文件 - 点击"添加文件"选择一个或多个音频文件 - 或点击"添加目录"批量导入整个文件夹(包含子目录) - 添加后文件状态为"待扫描",需手动点击扫描 - 扫描文件时会同时通过 ffprobe 检测每个文件的 `HasCover` 元数据,封面列显示「有封面」/「无」 ### 3. 扫描响度 - 点击"扫描全部":批量测量所有文件的当前响度和真峰值 - 或右键选中多个文件,选择"刷新选中" - 或右键点击单个文件,选择"刷新选中" ### 4. 设置目标值 - **目标响度 (LUFS)**:推荐 -14 LUFS(Spotify / YouTube 标准) - **限制峰值 (dBFS)**:推荐 -1.0 dBTP(防止削波) - 点击"应用到全部"可将当前设置应用到所有文件 - 也可以在 DataGrid 中单独为每行设置 - 点击下拉框后的 "?" 按钮可查看详细说明 ### 5. 软件设置 点击工具栏「⚙️ 设置」按钮打开设置窗口: - **通用设置**: - 添加文件或目录时自动分析响度(默认关闭) - 添加目录时扫描子目录(默认开启) - 界面语言切换(中文/English) - 主题模式切换(亮色/暗色/跟随系统) - **输出设置**: - 输出方式:子目录 / 覆盖原文件 / 指定目录 - 自定义输出目录(仅指定目录模式可用) - **FFmpeg 设置**: - FFmpeg 状态显示(绿色=已找到,红色=未找到) - FFprobe 状态显示(绿色=已找到,红色=未找到) - 下载按钮:打开 FFmpeg 官方下载页(包含 ffmpeg.exe 和 ffprobe.exe) - 浏览 FFmpeg...:手动选择 ffmpeg.exe,程序会自动查找同目录下的 ffprobe.exe - 浏览 FFprobe...:手动选择 ffprobe.exe(当自动查找失败时使用) ### 6. 选择输出模式 在「设置」窗口中选择输出方式: - **输出到子目录**:在原文件所在目录创建 `_normalized` 子目录,输出文件放入其中 - **覆盖原文件**:直接修改原始音频文件(不可恢复,处理前有确认提示) - **输出到指定目录**:选择自定义文件夹作为输出路径,设置会自动保存 ### 7. 开始处理 - 点击"开始处理"处理全部文件 - 或右键选中多个文件,选择"处理选中" - 开始前会弹出确认对话框,显示文件数量和输出方式 - 如果有 DTS 格式文件,会弹出提示告知将转换为 FLAC 格式 - 覆盖模式下 DTS 文件会有额外确认对话框,选"否"自动回退到子目录模式 ### 8. 播放音频 - 右键点击文件,选择"播放" - 常见格式(MP3/FLAC/WAV/AAC/M4A/OGG/WMA)直接播放 - DTS 等格式通过 FFmpeg 转码为临时 WAV 后播放(自动清理临时文件) - 文件名列有图标标识:🎵 可直接播放,⚠ 需转码播放 ### 9. 文件修复 - 右键选中文件 → 「修复选中」:修复选中的损坏文件 - 右键 → 「修复所有损坏文件」:自动检测列表中所有损坏文件并提示修复 - 损坏检测采用双重验证:MediaPlayer 原生播放测试 + FFmpeg 全量解码,任一失败即判定为损坏 - 修复流程:先尝试同格式重编码(RepairDirectAsync),失败再走 WAV 中间文件两步修复(RepairViaWavAsync) - 输出方式:覆盖模式使用系统临时目录中转(保留原文件时间戳),非覆盖模式输出到 `_repaired` 子目录并自动打开 - 检测结果缓存至文件列表变更,避免重复检测 ### 10. 格式转换 - 右键选中文件 → 「转为 FLAC」或「转为 WAV」 - FLAC 输出到 `_flac` 子目录,WAV 输出到 `_wav` 子目录 - 自动通过 ffprobe 检测并保持原始采样格式(`-sample_fmt`)、采样率、声道数 - 源文件已是目标格式时提示并跳过 ### 11. 封面管理 - **查看封面**:选中文件后右侧面板上方显示当前封面 - **扫描封面**:右键 → 「扫描封面」可批量刷新列表中所有文件的「有封面」/「无」状态(仅检测,不扫描响度,速度快) - **获取封面**:右侧「获取」按钮或右键 → 「获取」,调用网易云音乐 API 搜索封面(需网络) - **浏览封面**:点击「浏览」可从本地选择图片作为封面 - **切换封面**:搜索到多个结果时可用 ← / → 按钮切换 - **应用封面**:点击「应用」将选中封面嵌入音频文件 - 支持嵌入封面的格式:MP3、MP2、M4A、AAC、FLAC、OGG、MKA - DTS、WAV 等格式不支持嵌入封面,尝试时会提示 - 封面图片自动限制为 1200x1200 像素,超过会等比例缩放,防止文件损坏 ### 12. 语言切换 - 在「设置」窗口中选择"中文"或"English" - 切换后所有界面元素实时更新,包括文件信息面板的元数据标签(歌手名/专辑名/曲目名) ### 13. 查看帮助 - 点击工具栏「❓ 帮助」按钮 - 或菜单栏「帮助 → 使用帮助」(快捷键 F1) - 使用系统默认浏览器打开 HTML 帮助文档 - 包含完整的功能说明、操作指南和常见问题解答 ### 14. 菜单栏与快捷键 顶部菜单栏提供 5 个主菜单(文件 / 操作 / 转换 / 工具 / 帮助),所有菜单项均与工具栏按钮共用同一命令,菜单项右侧显示对应快捷键。除菜单入口外,软件还通过 `Window.InputBindings` 注册了 15 个全局快捷键,无需打开菜单即可触发: | 功能 | 快捷键 | 所属菜单 | |------|--------|----------| | 添加文件 | Ctrl+O | 文件 | | 添加文件夹 | Ctrl+Shift+O | 文件 | | 移除选中 | Del | 文件 | | 清空列表 | Ctrl+Shift+Del | 文件 | | 退出 | Alt+F4 | 文件 | | 扫描全部 | F6 | 操作 | | 刷新选中 | F5 | 操作 | | 开始处理 | Ctrl+Enter | 操作 | | 取消 | Esc | 操作 | | 修复所有损坏文件 | Ctrl+R | 操作 | | 扫描封面 | Ctrl+Shift+K | 操作 | | 转为 FLAC | Ctrl+Shift+F | 转换 | | 转为 WAV | Ctrl+Shift+W | 转换 | | 设置 | Ctrl+, | 工具 | | 使用帮助 | F1 | 帮助 | > 「工具」菜单还提供主题(亮色/暗色/跟随系统)与语言(中文/English)的快捷切换入口,无需打开设置窗口。 > DataGrid 中的列表多选仍使用 Ctrl+点击 / Shift+点击,Ctrl+A 全选。 ## 技术栈 - .NET 10 / WPF(PresentationFramework.Fluent 主题) - CommunityToolkit.Mvvm 8.4.2(MVVM + 源生成器) - FFmpeg(loudnorm 滤镜、ffprobe 元数据检测、封面嵌入) - Newtonsoft.Json 13.0.4 - LocalizationService(字典+属性模式,多语言支持) - 第三方 API:网易云音乐搜索 API、TheAudioDB 曲目查询 API ## 项目结构 ``` SetLufs/ ├── Models/ # 数据模型 │ ├── AudioFileItem.cs # 含 HasCover、IsPlayable、NeedsTranscode 等属性 │ ├── LoudnessMeasurement.cs │ ├── OutputMode.cs │ ├── AppSettings.cs # 应用设置持久化(settings.json) │ ├── ThemeMode.cs # 主题模式枚举(Light/Dark/System) │ └── ThemeOptionItem.cs # 主题选项项(解决语言切换时选中状态丢失) ├── Services/ # 服务层 │ ├── FfmpegService.cs # 测量/归一化/转码/修复/转换/封面检测与嵌入/元数据提取 │ ├── LocalizationService.cs # 多语言服务(字典+属性模式,单例) │ ├── AudioPlayerService.cs # MediaPlayer 封装 + 损坏检测 │ ├── PlaybackFormatService.cs │ ├── MusicInfoApiService.cs # 网易云音乐专辑封面搜索 API │ └── AudioDbService.cs # TheAudioDB 曲目信息查询 API ├── ViewModels/ # MVVM ViewModel │ └── MainViewModel.cs ├── Views/ # WPF 视图 │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── AboutWindow.xaml │ ├── AboutWindow.xaml.cs │ ├── SettingsWindow.xaml │ ├── SettingsWindow.xaml.cs │ ├── MessageDialog.xaml │ └── MessageDialog.xaml.cs ├── Resources/ # 样式和资源 │ ├── Styles/ │ │ └── Shared.xaml # Fluent 主题的薄包装样式 + 10 个值转换器 │ ├── app.ico # 程序图标 │ └── help.html # 帮助文档(HTML) ├── App.xaml # 应用程序资源定义(静态合并 Fluent 主题 + Shared.xaml) ├── App.xaml.cs # Application 子类(主题/语言恢复) ├── SetLufs.csproj # 项目配置文件(net10.0-windows, NoWarn WPF0001) ├── SetLufs.Tests/ # 单元测试项目 │ ├── SetLufs.Tests.csproj # 测试项目配置(xUnit + coverlet) │ ├── FfmpegServiceTests.cs # FfmpegService 单元测试(47 个测试) │ ├── AudioPlayerServiceTests.cs # AudioPlayerService 单元测试(20 个测试) │ ├── MusicInfoApiServiceTests.cs # MusicInfoApiService 单元测试(15 个测试) │ ├── LocalizationServiceTests.cs # LocalizationService 单元测试(7 个测试) │ ├── MainViewModelParsingTests.cs # MainViewModel 解析方法测试(31 个测试) │ └── TestResults/ # 测试结果和覆盖率报告 ├── LICENSE # MIT 许可证 ├── README.md # 项目说明 └── code-wiki.md # 代码文档 ``` ## 注意事项 ### 性能优化 - 程序根据文件平均大小自动调整线程数: - 小文件(<10MB):单线程,高并发 - 中等文件(10-50MB):2线程 - 大文件(50-200MB):4线程 - 超大文件(>200MB):8线程,单并发 - **音频处理无法使用 GPU 加速**(loudnorm 滤镜和音频编码器均为纯 CPU 实现) - DTS 等多声道高码率文件扫描速度较慢(loudnorm 需全量解码所有声道) ### 特殊格式处理 - DTS 和 APE(Monkey's Audio)格式文件处理后自动转换为 FLAC 格式(这些格式只有解码器没有编码器,无法回写原格式) - FLAC 为无损压缩,音质与原文件相同,体积约为 WAV 的 50-60% - 处理前会弹出提示告知用户 - 所有处理操作通过 ffprobe 检测原文件 `sample_fmt`,无损格式显式指定 `-sample_fmt` 保持原始采样格式 - 封面流通过 `BuildMapAndCoverArgs` 按格式类型映射(WAV/AU 用 `-map 0:a`,M4A/AAC 用 `-map 0`,MP3/MP2 用 `-map 0 -disposition:v attached_pic -metadata:s:v comment="Cover (front)" -id3v2_version 3`,其他格式用 `-map 0 -disposition:v attached_pic`) ### 右键菜单顺序 文件列表右键菜单从上到下依次为: 1. 播放 2. 刷新选中 3. 处理选中 4. 转为 FLAC 5. 转为 WAV 6. 扫描封面(批量刷新封面状态) 7. 获取(调用网易云 API 搜索封面) 8. 修复选中 9. 修复所有损坏文件 10. 打开文件位置 ### 输出目录对应关系 | 操作 | 输出位置 | 自动打开目录 | |------|---------|------------| | 响度归一化(子目录模式) | `原目录/_normalized/` | 否 | | 响度归一化(覆盖模式) | 原位置(临时目录中转) | 否 | | 响度归一化(指定目录) | 自定义路径 | 否 | | 文件修复(非覆盖) | `原目录/_repaired/` | 是 | | 文件修复(覆盖) | 原位置(临时目录中转,保留时间戳) | 否 | | 转为 FLAC | `原目录/_flac/` | 是 | | 转为 WAV | `原目录/_wav/` | 是 | | 封面嵌入 | 原位置(直接修改) | 否 | ### 错误处理 - 处理失败时状态列显示具体错误信息(鼠标悬停查看完整内容) - 失败时自动清理空输出文件和空 `_normalized` 目录 - 覆盖模式使用临时目录方案,避免 FFmpeg 读写同文件失败 - 处理过程中禁止关闭窗口,防止文件写入中断导致损坏 ### 其他 - 浮点参数使用 InvariantCulture 格式化,避免中文系统下小数分隔符问题 - 处理前建议先扫描,未扫描的文件会提示"未扫描,跳过" - 语言设置自动保存到 `%LocalAppData%\SetLufs\lang.txt`,下次启动恢复 - 主题模式自动保存到 `%LocalAppData%\SetLufs\settings.json`,下次启动恢复 - FFmpeg 路径保存到 `%LocalAppData%\SetLufs\ffmpegpath.txt` - 自定义输出目录自动保存到 `%LocalAppData%\SetLufs\outputdir.txt` - 软件设置保存到 `%LocalAppData%\SetLufs\settings.json`,包括自动扫描、子目录扫描、主题模式等选项 - 处理前会弹出输出位置确认对话框,避免误操作 - DataGrid 按文件加载顺序显示(初始化时清空 SortDescriptions,避免按文件名排序) - 主题切换基于 .NET 10 官方 `Application.ThemeMode`,窗口不设置 Background 时自动启用 Mica 背景 - 封面嵌入使用 `-map 0:a -map 1:v -c:a copy -c:v copy` 参数,避免 `-map 0` 导致原有视频流干扰封面嵌入 ## 许可证 MIT License Copyright (c) 2026 weijx (lswjx@foxmail.com)