ASP.NET MVC 中的超快速文本到语音 (WAV -> MP3)

2024-01-31

这个问题本质上是关于微软的语音API(SAPI)对于服务器工作负载的适用性以及它是否可以在内部可靠地使用。w3wp用于语音合成。我们有一个异步控制器,它使用本机System.Speech.NET 4 中的程序集(不是Microsoft.Speech作为 Microsoft 语音平台 - 运行时版本 11 的一部分提供的一个)和蹩脚.exe 到生成mp3如下:

       [CacheFilter]
        public void ListenAsync(string url)
        {
                string fileName = string.Format(@"C:\test\{0}.wav", Guid.NewGuid());                       

                try
                {
                    var t = new System.Threading.Thread(() =>
                    {
                        using (SpeechSynthesizer ss = new SpeechSynthesizer())
                        {
                            ss.SetOutputToWaveFile(fileName, new SpeechAudioFormatInfo(22050, AudioBitsPerSample.Eight, AudioChannel.Mono));
                            ss.Speak("Here is a test sentence...");
                            ss.SetOutputToNull();
                            ss.Dispose();
                        }

                        var process = new Process() { EnableRaisingEvents = true };
                        process.StartInfo.FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\lame.exe");
                        process.StartInfo.Arguments = string.Format("-V2 {0} {1}", fileName, fileName.Replace(".wav", ".mp3"));
                        process.StartInfo.UseShellExecute = false;
                        process.StartInfo.RedirectStandardOutput = false;
                        process.StartInfo.RedirectStandardError = false;
                        process.Exited += (sender, e) =>
                        {
                            System.IO.File.Delete(fileName);

                            AsyncManager.OutstandingOperations.Decrement();
                        };

                        AsyncManager.OutstandingOperations.Increment();
                        process.Start();
                    });

                    t.Start();
                    t.Join();
                }
                catch { }

            AsyncManager.Parameters["fileName"] = fileName;
        }

        public FileResult ListenCompleted(string fileName)
        {
            return base.File(fileName.Replace(".wav", ".mp3"), "audio/mp3");
        }

问题是为什么SpeechSynthesizer需要在这样的单独线程上运行才能返回(这在 SO 的其他地方报告过)here https://stackoverflow.com/questions/4671158/c-sharp-speechsynthesizer-makes-service-unresponsive and here https://stackoverflow.com/questions/1719780/speechsynthesizer-how-do-i-play-save-the-wav-file)以及是否实施STAThreadRouteHandler http://www.productiverage.com/Read/13对于这个请求比上面的方法更有效/可扩展吗?

二、运行时有哪些选项SpeakAsync在 ASP.NET(MVC 或 WebForms)上下文中?我尝试过的选项似乎都不起作用(请参阅下面的更新)。

欢迎任何有关如何改进此模式的其他建议(即必须彼此串行执行但每个都具有异步支持的两个依赖项)。我认为这个方案在负载下不可持续,特别是考虑到已知内存泄漏 http://connect.microsoft.com/VisualStudio/feedback/details/664196/system-speech-has-a-memory-leak in SpeechSynthesizer。考虑在不同的堆栈上一起运行此服务。

Update:两者都没有Speak or SpeakAsnc选项似乎在以下情况下工作STAThreadRouteHandler。前者产生:

System.InvalidOperationException:异步操作不是 在这种情况下允许。启动异步操作的页面有 将 Async 属性设置为 true 并执行异步操作 只能在 PreRenderComplete 事件之前的页面上启动。在 System.Web.LegacyAspNetSynchronizationContext.OperationStarted() 位于 System.ComponentModel.AsyncOperationManager.CreateOperation(对象 用户提供的状态)在 System.Speech.Internal.Synthesis.VoiceSynthesis..ctor(弱引用 语音合成器)在 System.Speech.Synthesis.SpeechSynthesizer.get_VoiceSynthesizer() 在 System.Speech.Synthesis.SpeechSynthesizer.SetOutputToWaveFile(字符串 路径、SpeechAudioFormatInfo 格式信息)

后者的结果是:

System.InvalidOperationException:异步操作方法 “Listen”无法同步执行。在 System.Web.Mvc.Async.AsyncActionDescriptor.Execute(ControllerContext controllerContext、IDictionary`2个参数)

它看起来像是一个自定义的 STA 线程池(带有ThreadStaticCOM 对象的实例)是更好的方法:http://marcinbudny.blogspot.ca/2012/04/dealing-with-sta-coms-in-web.html http://marcinbudny.blogspot.ca/2012/04/dealing-with-sta-coms-in-web.html

更新#2: 好像不是System.Speech.SpeechSynthesizer需要 STA 处理,只要您遵循这一点,似乎在 MTA 线程上运行良好Start/Join图案。这是一个新版本,可以正确使用SpeakAsync(问题是过早地处理它!)并将 WAV 生成和 MP3 生成分成两个单独的请求:

[CacheFilter]
[ActionName("listen-to-text")]
public void ListenToTextAsync(string text)
{
    AsyncManager.OutstandingOperations.Increment();   

    var t = new Thread(() =>
    {
        SpeechSynthesizer ss = new SpeechSynthesizer();
        string fileName = string.Format(@"C:\test\{0}.wav", Guid.NewGuid());

        ss.SetOutputToWaveFile(fileName, new SpeechAudioFormatInfo(22050,
                                                                   AudioBitsPerSample.Eight,
                                                                   AudioChannel.Mono));
        ss.SpeakCompleted += (sender, e) =>
        {
            ss.SetOutputToNull();
            ss.Dispose();

            AsyncManager.Parameters["fileName"] = fileName;
            AsyncManager.OutstandingOperations.Decrement();
        };

        CustomPromptBuilder pb = new CustomPromptBuilder(settings.DefaultVoiceName);
        pb.AppendParagraphText(text);
        ss.SpeakAsync(pb);               
    });

    t.Start();
    t.Join();                    
}

[CacheFilter]
public ActionResult ListenToTextCompleted(string fileName)
{
    return RedirectToAction("mp3", new { fileName = fileName });
}

[CacheFilter]
[ActionName("mp3")]
public void Mp3Async(string fileName) 
{
    var process = new Process()
    {
        EnableRaisingEvents = true,
        StartInfo = new ProcessStartInfo()
        {
            FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\lame.exe"),
            Arguments = string.Format("-V2 {0} {1}", fileName, fileName.Replace(".wav", ".mp3")),
            UseShellExecute = false,
            RedirectStandardOutput = false,
            RedirectStandardError = false
        }
    };

    process.Exited += (sender, e) =>
    {
        System.IO.File.Delete(fileName);
        AsyncManager.Parameters["fileName"] = fileName;
        AsyncManager.OutstandingOperations.Decrement();
    };

    AsyncManager.OutstandingOperations.Increment();
    process.Start();
}

[CacheFilter]
public ActionResult Mp3Completed(string fileName) 
{
    return base.File(fileName.Replace(".wav", ".mp3"), "audio/mp3");
}

I/O 在服务器上非常昂贵。您认为服务器硬盘上可以写入多少个 wav 写入流?为什么不在内存中完成所有操作并仅在完全处理后才写入 mp3? mp3 较小,I/O 占用的时间也很短。如果需要,您甚至可以更改代码以将流直接返回给用户,而不是保存到 mp3。

如何使用 LAME 将 wav 编码为 mp3 C# https://stackoverflow.com/questions/19166140/how-do-can-i-use-lame-to-encode-an-wav-to-an-mp3-c-sharp/23947113#23947113

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.NET MVC 中的超快速文本到语音 (WAV -> MP3) 的相关文章

  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • 从 ASP .Net Web 服务访问 MSMQ 时出现权限错误

    我写了一个从消息队列读取的 Web 服务 这在卡西尼号下工作得很好 现在我已经在 IIS 下部署了该服务 当该服务尝试访问队列时 我收到一条错误消息 队列不存在或者您没有足够的权限来执行该操作 我已将 IIS 虚拟目录上的匿名访问用户设置为
  • OpenGL:仅获取模板缓冲区而没有深度缓冲区?

    我想获取一个模板缓冲区 但如果可能的话 不要承受附加深度缓冲区的开销 因为我不会使用它 我发现的大多数资源表明 虽然模板缓冲区是可选的 例如 排除它以利于获得更高的深度缓冲区精度 但我还没有看到任何请求并成功获取仅 8 位模板缓冲区的代码
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

    我正在编写一个需要遍历实体框架的测试库MetadataWorkspace对于给定的DbContext类型 但是 由于这是一个测试库 我宁愿不连接到数据库 它引入了测试环境中可能无法使用的依赖项 当我尝试获取参考时MetadataWorksp

随机推荐

  • ios 7 UiView 框架问题

    我在 iOS6 和 iOS7 中运行相同的应用程序 其中有导航栏 它在 iOS6 上运行良好 但在 iOS7 中 所有视图都有点向上 就像根本没有考虑导航栏一样 我尝试更改模拟指标选项中的顶栏属性 但它不起作用 在 iOS6 中 它从导航栏
  • 在 POST/batches 请求中使用现有的 SparkSession

    我正在尝试使用Livy远程提交多个Spark jobs 假设我想执行以下操作spark submit远程任务 包含所有选项 spark submit class com company drivers JumboBatchPipelineD
  • Serilog - 无法根据属性记录到多个文件

    您好 我正在尝试使用以下命令在一个文件中记录一些消息 在另一个文件中记录其他消息Serilog 我尝试过以下配置 Log Logger new LoggerConfiguration WriteTo Map type audit name
  • ndb async 是否保证在应用程序请求完成后执行?

    我正在使用 ndb 编写一个分析模型 该模型根据应用程序请求记录一些数据 每个请求通过ndb put async调用一个ndb请求来记录数据 而客户端不关心结果 本质上 我不希望应用程序请求等待保存统计数据以进行分析 然而 我对官方文档的解
  • Android设置壁纸出错了

    所以我很久以前就在开发壁纸更换器并发布了它 一段时间后 我开始收到壁纸尺寸调整不正确的评论 我还尝试了不同尺寸的鸸鹋 它们是正确的 我正确地缩放位图等 但不知何故 android倾向于将壁纸重新缩放得更大 有办法避免吗 我的代码 Displ
  • 与 VB.NET 中的 Array() 等效吗?

    在 VB6 中你可以这样做 Dim a As Variant a Array 1 2 3 你能在 VB NET 中使用特定类型做类似的事情吗 Dim a As Integer a Array 1 2 3 Dim a As Integer N
  • 命名空间“std”中没有名为“unary_function”的模板;您的意思是“__unary_function”吗?

    刚刚将我的 Xcode 升级到 15 0 突然它开始在 RCT Folly 中出现以下错误 No template named unary function in namespace std did you mean unary funct
  • 在运行时转储 gcov 数据

    我正在使用 gcov 收集我正在从事的 C 项目的代码覆盖率数据 据我所知 一旦程序完成后退出 gcov 就会转储代码覆盖率数据 如何收集长时间运行的进程的 gcov 数据 比如说 我的程序是一个操作系统的内核 该操作系统在永不关闭的服务器
  • iOS:Xcode 中的 ImageMagick 编译器警告

    我在 iOS 项目中使用 ImageMagick 但是该库已经过时 因为以前的开发人员使用了源代码 我使用的是 Xcode 6 3 2 我想使用 Cocoapods 将 ImageMagick 集成到项目中 而不是复制源文件 然而 当我将
  • SDL_ttf找不到“SDL.h”,但main.cpp可以

    我正在编写一个 make 文件来编译一个非常简单的 SDL2 程序 到目前为止 它编译 SDL2 得很好 现在我正在编译扩展框架 SDL2 image 和 SDL ttf 看起来MAKE正确地找到了SDL ttf h 但是SDL ttf h
  • 使用 GSON 将 JSON 转换为 Java 对象时如何覆盖 Java 映射?

    我有一个 JSON 字符串 如下所示 status status date 01 10 2019 alerts labels field1 value1 field2 value2 field3 value3 field100 value1
  • Sphinx Note Block 在代码块下的列表中?

    我有一个问题 如果我想将注释块放在代码块下的列表中 它就会包含在代码块中 如果我取消缩进 列表编号会在注释后重新开始 所以基本上 我需要的是 Fixed list example First do spam Then do eggs som
  • 如何使用 BERT 找到与向量最接近的单词

    我正在尝试使用 BERT 获取给定单词嵌入的文本表示 或最接近的单词 基本上我试图获得与 gensim 类似的功能 gt gt gt your word vector array 0 00449447 0 00310097 0 024217
  • 谷歌的无图像按钮

    最近有几篇关于谷歌新的无图像按钮的文章 http stopdesign com archive 2009 02 04 recreating the button html http stopdesign com archive 2009 0
  • 将文本添加到绘图中

    x lt seq 3 3 0 01 y1 lt dnorm x 0 1 y2 lt 0 5 dnorm x 0 1 plot x y1 type l bty L xlab X ylab dnorm X points x y2 type l
  • 数组中所有元素的总和

    我是编程初学者 我想计算数组中所有元素的总和 我做了这个 但我看不出我的错误在哪里 function ArrayAdder array this sum 0 this array array ArrayAdder prototype com
  • python 按不同标准对元组进行排序

    我有一个清单a 1 a 1 b 2 c 我想得到这个列表 2 c 1 a 1 b 如果我这样做 sorted a reverse True 我只能得到 2 c 1 b 1 a 我怎样才能得到我想要的列表 如果您想保留原始列表中的排序顺序 但
  • 如何通过 SoundCloud API 添加评论

    我想通过 SoundCloud API 发表评论 但查看文档 http developers soundcloud com docs api reference tracks这似乎是不可能的 唯一可用的方法 tracks id commen
  • 为什么 React 需要 Babel 和 Webpack 才能工作?

    我正在查看 vue js 的 wiki 页面 看到了这个 与 React 开发相比 Vue 可以集成到 现有的 Web 应用程序更加容易 通常 Web 应用程序 只需包含 Vue js 即可立即开始使用 Vue JavaScript 库 与
  • ASP.NET MVC 中的超快速文本到语音 (WAV -> MP3)

    这个问题本质上是关于微软的语音API SAPI 对于服务器工作负载的适用性以及它是否可以在内部可靠地使用 w3wp用于语音合成 我们有一个异步控制器 它使用本机System Speech NET 4 中的程序集 不是Microsoft Sp