当前位置: 首页 > news >正文

一种MP3文件的压缩方法

事情是这样的

有一批音频需要压缩。这些音频主要是课文朗读。因为不是歌曲,质量要求不高,所以使用了比较低的质量,对于有些音频能压制到原来的八分之一的体积例如 (大小为78M的音频 压缩到9M)。

  MP3FileProcessor.CompressAndResampleMp3(fn_old, fn);

默认使用下面的压制参数 

采样率  int targetSampleRate= 8000

比特率 int bitRate=32

声道数 int channels=1

重采样质量  ResamplerQuality = 60


if (!File.Exists(inputFilePath))
throw new FileNotFoundException("输入文件不存在", inputFilePath);

            if (string.IsNullOrEmpty(outputFilePath))
throw new ArgumentException("输出文件路径不能为空");

            if (channels != 1 && channels != 2)
throw new ArgumentException("声道数必须为1(单声道)或2(立体声)", nameof(channels));

            // 支持的采样率验证(常见MP3采样率)
int[] supportedSampleRates = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 };
if (Array.IndexOf(supportedSampleRates, targetSampleRate) == -1)
throw new ArgumentException("不支持的采样率", nameof(targetSampleRate));

            // 支持的比特率验证(LAME支持的常见比特率)
if (bitRate < 32 || bitRate > 320 || bitRate % 8 != 0)
throw new ArgumentException("无效的比特率,必须是32-320之间的8的倍数", nameof(bitRate));

            // 确保输出目录存在
var outputDir = Path.GetDirectoryName(outputFilePath);
if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);

            WaveStream reader = null;
WaveStream resampledStream = null;
LameMP3FileWriter writer = null;

            try
{
// 读取输入音频文件(NAudio会自动识别格式)
reader = new AudioFileReader(inputFilePath);

                // 如果需要重采样或改变声道数
if (reader.WaveFormat.SampleRate != targetSampleRate ||
reader.WaveFormat.Channels != channels)
{
// 创建重采样器
var resampler = new MediaFoundationResampler(reader,
WaveFormat.CreateIeeeFloatWaveFormat(targetSampleRate, channels));

                    // 重采样质量设置(0-100,越高质量越好但速度越慢)
resampler.ResamplerQuality = 60;
resampledStream = new WaveProviderToStreamAdapter(resampler);
}
else
{
// 无需重采样,直接使用原始流
resampledStream = reader;
}

                // 初始化LAME编码器设置
LameConfig lameConfig = new LameConfig();
lameConfig.BitRate = bitRate;

                // 创建MP3写入器(内部会初始化LAME编码器)
writer = new LameMP3FileWriter(outputFilePath,
resampledStream.WaveFormat,
lameConfig);

                // 缓冲区大小(根据采样率调整,确保处理效率)
var bufferSize = resampledStream.WaveFormat.AverageBytesPerSecond / 4;
var buffer = new byte[bufferSize];
int bytesRead;

                // 处理音频数据
while ((bytesRead = resampledStream.Read(buffer, 0, buffer.Length)) > 0)
{
writer.Write(buffer, 0, bytesRead);
}
}
catch (Exception ex)
{
// 清理可能生成的不完整文件
if (File.Exists(outputFilePath))
File.Delete(outputFilePath);

                throw new IOException("MP3处理失败", ex);
}
finally
{
// 确保资源释放
writer?.Dispose();
resampledStream?.Dispose();
reader?.Dispose();
}

代码

    public class MP3FileProcessor{public class WaveProviderToStreamAdapter : WaveStream{private readonly IWaveProvider _provider;private long _position;public WaveProviderToStreamAdapter(IWaveProvider provider){_provider = provider ?? throw new ArgumentNullException(nameof(provider));}public override WaveFormat WaveFormat => _provider.WaveFormat;// 对于实时生成的流(如重采样器),长度无法预知,返回long.MaxValuepublic override long Length => long.MaxValue;public override long Position{get => _position;set => _position = value; // 重采样流不支持定位,此处仅作占位}public override int Read(byte[] buffer, int offset, int count){int bytesRead = _provider.Read(buffer, offset, count);_position += bytesRead;return bytesRead;}}public static void CompressAndResampleMp3(string inputFilePath, string outputFilePath,int targetSampleRate= 8000, int bitRate=32, int channels=1){// 验证输入参数if (!File.Exists(inputFilePath))throw new FileNotFoundException("输入文件不存在", inputFilePath);if (string.IsNullOrEmpty(outputFilePath))throw new ArgumentException("输出文件路径不能为空");if (channels != 1 && channels != 2)throw new ArgumentException("声道数必须为1(单声道)或2(立体声)", nameof(channels));// 支持的采样率验证(常见MP3采样率)int[] supportedSampleRates = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 };if (Array.IndexOf(supportedSampleRates, targetSampleRate) == -1)throw new ArgumentException("不支持的采样率", nameof(targetSampleRate));// 支持的比特率验证(LAME支持的常见比特率)if (bitRate < 32 || bitRate > 320 || bitRate % 8 != 0)throw new ArgumentException("无效的比特率,必须是32-320之间的8的倍数", nameof(bitRate));// 确保输出目录存在var outputDir = Path.GetDirectoryName(outputFilePath);if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))Directory.CreateDirectory(outputDir);WaveStream reader = null;WaveStream resampledStream = null;LameMP3FileWriter writer = null;try{// 读取输入音频文件(NAudio会自动识别格式)reader = new AudioFileReader(inputFilePath);// 如果需要重采样或改变声道数if (reader.WaveFormat.SampleRate != targetSampleRate ||reader.WaveFormat.Channels != channels){// 创建重采样器var resampler = new MediaFoundationResampler(reader,WaveFormat.CreateIeeeFloatWaveFormat(targetSampleRate, channels));// 重采样质量设置(0-100,越高质量越好但速度越慢)resampler.ResamplerQuality = 60;resampledStream = new WaveProviderToStreamAdapter(resampler);}else{// 无需重采样,直接使用原始流resampledStream = reader;}// 初始化LAME编码器设置LameConfig lameConfig = new LameConfig();lameConfig.BitRate = bitRate;// 创建MP3写入器(内部会初始化LAME编码器)writer = new LameMP3FileWriter(outputFilePath,resampledStream.WaveFormat,lameConfig);// 缓冲区大小(根据采样率调整,确保处理效率)var bufferSize = resampledStream.WaveFormat.AverageBytesPerSecond / 4;var buffer = new byte[bufferSize];int bytesRead;// 处理音频数据while ((bytesRead = resampledStream.Read(buffer, 0, buffer.Length)) > 0){writer.Write(buffer, 0, bytesRead);}}catch (Exception ex){// 清理可能生成的不完整文件if (File.Exists(outputFilePath))File.Delete(outputFilePath);throw new IOException("MP3处理失败", ex);}finally{// 确保资源释放writer?.Dispose();resampledStream?.Dispose();reader?.Dispose();}}}

http://www.dtcms.com/a/554106.html

相关文章:

  • 做网站时候图片和视频放在哪里c 2015 做网站
  • puppeteer函数笔记,设置token跳过登录、自动选择图片上传等
  • 雄安网站建设400多少钱郑州关键词网站优化排名
  • 在使用openfe出现NameError: name ‘exit‘ is not defined的解决方案
  • 【计算机通识】认识 RESTful API
  • 使用cJosn将数据读写文件
  • 做软件搜狗seo软件
  • 仿土巴兔网站建设学院网站建设流程
  • DeerFlow多智能体项目分析-向量数据库实现知识检索的源码解析
  • 001前端查询组件
  • AI在线客服搭建实战指南:三步构建7×24小时智能服务系统
  • TSMaster常用函数
  • 伯位数智模式为商家经营带来的变革与机遇
  • 网盘怎么做电影网站网站在公司做有什么要求吗
  • 介绍一下 multiprocessing 的 Manager模块
  • 网页建站总结报告网站建设初期怎么添加内容
  • C语言——猜数字游戏(rand、srand、time函数学习)
  • 多媒体网站开发实战装修设计软件免费
  • Rust流程控制(下):loop、while、for循环
  • 使用 UV 工具管理 Python 项目的常用命令
  • 解析视频汇聚平台EasyCVR强大的设备统一管理能力,助力构筑安防融合感知的基石
  • 南通做网站的手机怎么看网页源代码
  • 温州网上推广什么网站好深圳网络推广团队
  • 1951-2024年我国逐日\逐月\逐年近地面气温栅格数据
  • Linux----进程控制
  • 公司网站建设公司微网站建设价格
  • AI代码开发宝库系列:RAG--GraphRAG实战
  • 做一份网站动态图多少钱免费ip地址
  • 基于空间螺旋运动假设的水星近日点进动理论推导与验证
  • 手写Spring第20弹:JDK动态代理:深入剖析Java代理模式