在NAudio中将内存流中的格式从wav更改为mp3

15

你好,我正在尝试将文本转换为语音(wav),将其转换为mp3并在用户页面上播放。所以我需要帮助,接下来该怎么做?

这是我的asmx代码:

[WebMethod]
public byte[] StartSpeak(string Word)
{
    MemoryStream ms = new MemoryStream();
    using (System.Speech.Synthesis.SpeechSynthesizer synhesizer = new System.Speech.Synthesis.SpeechSynthesizer())
    {
        synhesizer.SelectVoiceByHints(System.Speech.Synthesis.VoiceGender.NotSet, System.Speech.Synthesis.VoiceAge.NotSet, 0, new System.Globalization.CultureInfo("en-US"));
        synhesizer.SetOutputToWaveStream(ms);
        synhesizer.Speak(Word);
    }
    return ms.ToArray();

    }

感谢您的选择。
谢谢。

你做到哪一步了?有出现错误吗?另外,我假设这只是语音转文本的部分,而不是转换的部分? - James Johnson
谢谢回复。我是一个初学者,所以如果有示例,那么下一步该做什么会有困难。 - user2431114
可能是 Audio Conversion C# 的重复问题。 - OmG
7个回答

62

我想分享一下使用NAudio.Lame的示例:

NuGet:

Install-Package NAudio.Lame

代码片段: 我的显然返回一个byte[] - 我有一个单独的保存到磁盘的方法,因为我认为这会使单元测试更容易。

public static byte[] ConvertWavToMp3(byte[] wavFile)
        {

            using(var retMs = new MemoryStream())
            using (var ms = new MemoryStream(wavFile))
            using(var rdr = new WaveFileReader(ms))
            using (var wtr = new LameMP3FileWriter(retMs, rdr.WaveFormat, 128))
            {
                rdr.CopyTo(wtr);
                return retMs.ToArray();
            }


        }

哇,我不知道为什么这个没有得到更多的赞。它完美地运行了。最简单的解决方案。感谢Wjdavis5! - JJ_Coder4Hire
无论我做了什么,返回的字节数组都是空的,对我没有起作用。 - Adrian C.
2
@AdrianC 在 rdr.CopyTo(wtr); 后面添加 wtr.Flush();。干杯。 - user1655141
我发现这个解决方案会将音频截断几秒钟。 - Skyfish
我认为你会想要像其他人建议的那样Flush()流。 - Wjdavis5

13
你需要一个MP3压缩库。我使用 Yeti Lame 封装的 Lame。你可以在这里找到代码和示例项目。 让它工作的步骤:
  1. 从 MP3Compressor中将以下文件复制到您的项目中:
    • AudioWriters.cs
    • Lame.cs
    • Lame_enc.dll
    • Mp3Writer.cs
    • Mp3WriterConfig.cs
    • WaveNative.cs
    • WriterConfig.cs

  2. Lame_enc.dll 的项目属性中,将 Copy to Output 属性设置为 Copy if newerCopy always
  3. 编辑 Lame.cs 并替换所有实例:
  4. [DllImport("Lame_enc.dll")]
    

    随着:

    [DllImport("Lame_enc.dll", CallingConvention = CallingConvention.Cdecl)]
    
  5. 将以下代码添加到您的项目中:

  6. public static Byte[] WavToMP3(byte[] wavFile)
    {
         using (MemoryStream source = new MemoryStream(wavFile))
         using (NAudio.Wave.WaveFileReader rdr = new NAudio.Wave.WaveFileReader(source))
         {
             WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(rdr.WaveFormat.SampleRate, rdr.WaveFormat.BitsPerSample, rdr.WaveFormat.Channels);
    
             // convert to MP3 at 96kbit/sec...
             Yeti.Lame.BE_CONFIG conf = new Yeti.Lame.BE_CONFIG(fmt, 96);
    
             // Allocate a 1-second buffer
             int blen = rdr.WaveFormat.AverageBytesPerSecond;
             byte[] buffer = new byte[blen];
    
             // Do conversion
             using (MemoryStream output = new MemoryStream())
             { 
                 Yeti.MMedia.Mp3.Mp3Writer mp3 = new Yeti.MMedia.Mp3.Mp3Writer(output, fmt, conf);
    
                 int readCount;
                 while ((readCount = rdr.Read(buffer, 0, blen)) > 0)
                     mp3.Write(buffer, 0, readCount);
                 mp3.Close();
    
                 return output.ToArray();
             }
         }
     }
    
  7. 要么向项目添加 System.Windows.Forms 的引用(如果还没有),要么编辑 AudioWriter.csWriterConfig.cs,删除引用。这两个文件都有一个可以删除的 using System.Windows.Forms;,而 WriterConfig.cs 中有一个需要被删除/注释掉的 ConfigControl 声明。

完成上述步骤后,您应该拥有一个功能完备的内存波形文件转MP3转换器,可以用来将从SpeechSynthesizer获取的WAV文件转换为MP3。


11

这篇文章有点老了,但由于您之前没有接受我提供的答案...

最近我构建了一个扩展程序用于封装LAME库以提供简化MP3编码。

使用NuGet软件包管理器查找 NAudio.Lame。可在此处找到使用它的基本示例。


我无法将引用添加到我的手机项目中。我应该怎么做?请提供一个教程来完成这个操作。 - Mani
抱歉 @max,但LAME编码器是一个本地Windows DLL,据我所知不适用于Windows Phone。鉴于这种情况,在Windows Phone上也无法使用LAME包装器。您必须找到另一种机制来进行MP3编码。 - Corey
我该如何构建一个Web服务来让这段代码运作?请理解我对于服务器端编码或相关机制了解不是特别深入。@Corey - Mani
@max 如果你正在运行一个ASP.NET或MVC4网站或类似的(即:在Win32 / Win64上的IIS),那么你可以在服务器端使用NAudio.Lame。不过需要添加一些东西 - 参考这个问题 - Corey
这是一个好建议。我会尝试为此构建一个Web服务。非常感谢 :) - Mani
哇,太棒了。 - Mike Gledhill

1

我在.NET 4.0中有一个类似的需求,需要转换8位8Khz单声道wav格式,使用以下代码:

public void WavToMp3(string wavPath, string fileId)
    {
        var tempMp3Path = TempPath + "tempFiles\\" + fileId + ".mp3";
        var mp3strm = new FileStream(tempMp3Path, FileMode.Create);
        try
        {
            using (var reader = new WaveFileReader(wavPath))
            {
                var blen = 65536;
                var buffer = new byte[blen];
                int rc;
                var bit16WaveFormat = new WaveFormat(16000, 16, 1);
                using (var conversionStream = new WaveFormatConversionStream(bit16WaveFormat, reader))
                {
                    var targetMp3Format = new WaveLib.WaveFormat(16000, 16, 1);
                    using (var mp3Wri = new Mp3Writer(mp3strm, new Mp3WriterConfig(targetMp3Format, new BE_CONFIG(targetMp3Format,64))))
                    {
                        while ((rc = conversionStream.Read(buffer, 0, blen)) > 0) mp3Wri.Write(buffer, 0, rc);
                        mp3strm.Flush();
                        conversionStream.Close();
                    }
                }
                reader.Close();
            }
            File.Move(tempMp3Path, TempPath + fileId + ".mp3");
        }
        finally
        {
            mp3strm.Close();
        }
    }

前提条件:

  1. 已编译的 .net 4 yeti 库(若要获得该库,请下载旧版库(http://www.codeproject.com/KB/audio-video/MP3Compressor/MP3Compressor.zip)并将其转换为 .net4.0,然后构建解决方案以获取新版本的 dll 文件)
  2. 下载 NAudio 库(由于 Lame 只支持 16 位 wav 样本,因此我需要先将其从 8 位转换为 16 位 wav 格式)

我使用了 64kpbs 的缓冲区大小(我的自定义要求)


1
假设您想将输出转换为MP3格式,您需要使用能够处理音频转码的工具。有许多可用的工具,但我个人偏好FFmpeg。它是一个命令行工具,因此您需要考虑到这一点,但除此之外,它非常容易使用。
有很多在线信息可供参考,您可以从这里here开始查看他们的文档。

0

试一试:

using (WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(new     
Mp3FileReader(inputStream))) 
using (WaveFileWriter waveFileWriter = new WaveFileWriter(outputStream, waveStream.WaveFormat)) 
{ 
    byte[] bytes = new byte[waveStream.Length]; 
    waveStream.Position = 0;
    waveStream.Read(bytes, 0, waveStream.Length); 
    waveFileWriter.WriteData(bytes, 0, bytes.Length); 
    waveFileWriter.Flush(); 
} 

0
假设您已经从NuGet安装了NAudio和NAudio.Lame:
using (var reader = new AudioFileReader(@"C:\Temp\Test0001.wav"))
using (var writer = new LameMP3FileWriter(@"C:\Temp\Test0001.mp3", reader.WaveFormat, LAMEPreset.STANDARD))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接