微信小程序+.NET(五) 音频格式转换-从.mp3到.wav

  从.mp3到.wav的音频格式转换

  当实际开发时,经常会遇到格式转化的问题,或是文本编码格式(看我另一篇文本编码转换文章链接:https://blog.csdn.net/jinglell/article/details/99679463),或是这次说到的音频编码格式。
  我遇到的需求是,将微信小程序录音得来的.mp3转换为科大讯飞语音识别的.wav/.pcm。
  我在解决问题时,尝试过很多方法,比如构造.wav文件头,使用NAudio.dll等,这两种方式我先贴出来,当时并没有解决我的问题:
  1.构造.wav文件头

		/// 
        /// wave文件头
        /// 
        private struct WAVE_Header
        {
            public int RIFF_ID;           //4 byte , 'RIFF'
            public int File_Size;         //4 byte , 文件长度
            public int RIFF_Type;         //4 byte , 'WAVE'

            public int FMT_ID;            //4 byte , 'fmt'
            public int FMT_Size;          //4 byte , 数值为16或18,18则最后又附加信息
            public short FMT_Tag;          //2 byte , 编码方式,一般为0x0001
            public ushort FMT_Channel;     //2 byte , 声道数目,1--单声道;2--双声道
            public int FMT_SamplesPerSec;//4 byte , 采样频率
            public int AvgBytesPerSec;   //4 byte , 每秒所需字节数,记录每秒的数据量
            public ushort BlockAlign;      //2 byte , 数据块对齐单位(每个采样需要的字节数)
            public ushort BitsPerSample;   //2 byte , 每个采样需要的bit数

            public int DATA_ID;           //4 byte , 'data'
            public int DATA_Size;         //4 byte , 
        }

        /// 
        /// 根据数据段的长度,生产文件头
        /// 
        /// 音频数据长度
        /// 返回wav文件头结构体
        WAVE_Header getWave_Header(int data_len)
        {
            WAVE_Header wav_Header = new WAVE_Header();
            wav_Header.RIFF_ID = 0x46464952;        //字符RIFF
            wav_Header.File_Size = data_len + 36;
            wav_Header.RIFF_Type = 0x45564157;      //字符WAVE

            wav_Header.FMT_ID = 0x20746D66;         //字符fmt
            wav_Header.FMT_Size = 16;
            wav_Header.FMT_Tag = 0x0001;
            wav_Header.FMT_Channel = 1;             //单声道
            wav_Header.FMT_SamplesPerSec = 16000;   //采样频率
            wav_Header.AvgBytesPerSec = 32000;      //每秒所需字节数
            wav_Header.BlockAlign = 2;              //每个采样1个字节
            wav_Header.BitsPerSample = 16;           //每个采样8bit

            wav_Header.DATA_ID = 0x61746164;        //字符data
            wav_Header.DATA_Size = data_len;

            return wav_Header;
        }

这个方式应该是可以的,是最原始最基础的,不过当时我并没有找到科大讯飞的音频格式要求,我对音频的了解也很少,所以转换出来的音频全是噪音,等找到时发现人家科大讯飞给了更好的工具,所以并没有再去修改这里的参数等尝试。
  2.NAudio转码

var inputFileName = "XXX.mp3";
var outputFileName = inputFileName.Substring(0, inputFileName.Length - 3) + "wav";
 var builder = new Mp3FileReader.FrameDecompressorBuilder(wf => new Mp3FrameDecompressor(wf));
using (var reader = new Mp3FileReader(inputFileName, builder))
{
	WaveFileWriter.CreateWaveFile(outputFileName, reader);
}

大致就是这样,这是我刚从网上找的,很简单的几句,不过就是读取不了我从微信小程序录下来的音频!0_0!
所以最后我找到了第三个方法,而且我发现官网给的也是这个工具:ffmpeg!我先试了试转码后能不能直接识别,发现可以之后,所以我想能不能直接在.NET里直接调用ffmpeg.exe这类exe文件?一查,真的可以!好了,问题解决了!
大致参考了一下,先下载好ffmpeg.exe然后放到项目里
微信小程序+.NET(五) 音频格式转换-从.mp3到.wav_第1张图片
然后查看科大讯飞官方说明:

https://www.xfyun.cn/doc/asr/voicedictation/Audio.html#%E9%9F%B3%E9%A2%91%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2%E5%B7%A5%E5%85%B7ffmpeg

微信小程序+.NET(五) 音频格式转换-从.mp3到.wav_第2张图片
但是官网并没有给出ffmpeg.exe下载链接,我发出来,链接: https://download.csdn.net/download/jinglell/11569562

解压后打开bin文件夹,我们这次需要的只是ffmpeg.exe,
下面是具体用法:

		#region 音频格式转换
        /// 
        /// 音频格式转换
        /// 
        /// 
        /// 
        public string mp32wav( string input )
        {
            //string output = input.Substring(0, input.Length - 3) + "wav";
            string absoluteUrl = GetConfigValue("AudioAbsoluteFolderTemp");//绝对路径
            string relativeUrl = GetConfigValue("AudioRelativeFolderTemp");//相对路径
            string catalog = DateTime.Now.ToString("yyyyMMdd");
            string filePath = System.IO.Path.Combine( absoluteUrl, catalog );
            if (!System.IO.Directory.Exists(filePath))
            {
                System.IO.Directory.CreateDirectory(filePath);
            }
            string fileName = CreateFileName(".wav");
            string output = System.IO.Path.Combine(filePath, fileName);
            //返回URL路径
            string returnURL = System.IO.Path.Combine(relativeUrl, catalog, fileName).Replace("\\", "/");
			string strCmd = "-y -i "+ input +" -acodec pcm_s16le -f s16le -ac 1 -ar 16000 "+output;
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "D:\\ffmpeg\\bin\\ffmpeg.exe";//要执行的程序名称 
            p.StartInfo.Arguments = " " + strCmd;
            p.StartInfo.UseShellExecute = true;
            p.StartInfo.RedirectStandardInput = false;//可能接受来自调用程序的输入信息 
            p.StartInfo.RedirectStandardOutput = false;//由调用程序获取输出信息 
            p.StartInfo.RedirectStandardError = false;//重定向标准错误输出
            p.StartInfo.CreateNoWindow = false;//不显示程序窗口
            p.Start();//启动程序
            p.WaitForExit();//等待程序执行完退出进程
            if (System.IO.File.Exists(output))
            {
                //return returnURL;
                return output;
            }
            return "";
        }
        #endregion

这里我是直接转码后存到了我的本地服务器,本地IIS资源服务器具体配置网上有很多教程不再赘述。

你可能感兴趣的:(.NET,C#,程序人生,微信小程序+.NET)