CS程式和BS程式文字轉語音

来源:https://www.cnblogs.com/lxshwyan/archive/2019/07/15/11188190.html
-Advertisement-
Play Games

一、項目中一直用到了文字轉語音的功能,需求也比較簡單,就是將一段報警信息通過語音的方式播放出來,之前一直採用CS客戶端,利用微軟自帶的Speech語音播放庫就可以完成, 1.1 封裝winSpedk類代碼如下: namespace Speak { using System; using System ...


    一、項目中一直用到了文字轉語音的功能,需求也比較簡單,就是將一段報警信息通過語音的方式播放出來,之前一直採用CS客戶端,利用微軟自帶的Speech語音播放庫就可以完成,

       1.1 封裝winSpedk類代碼如下:

namespace Speak
{
    using System;
    using System.Runtime.CompilerServices;
    using System.Speech.Synthesis;
    using System.Threading;
    using SpeechLib;

    public class WinSpeak
    {
        #region 屬性
        private SpeechSynthesizer Speak;
        public event ErrorInfo ErrorInfoEvent;
        private Thread thVoice;
        private string strVoiceMsg;
        SpVoice Voice = null;
        private static WinSpeak _intence;
        #endregion

        private WinSpeak()
        {
            Voice = new SpVoice();
        }

        #region 方法
        public static WinSpeak _Init()
        {
            if (_intence == null)
                _intence = new WinSpeak();

            return _intence;
        }
        /// <summary>
        /// 讀語音
        /// </summary>
        private void SpeakM()
        {
            try
            {
                if (Speak != null)
                {
                    this.Speak.SpeakAsync(strVoiceMsg);
                }
            }
            catch (Exception exception)
            {
                this.ErrInfo(exception);
            }
        }
        /// <summary>
        /// 非同步播放文本語音
        /// </summary>
        /// <param name="msg"></param>
        public void BeginSpeakText(string msg)
        {
            try
            {
                if (Speak != null)
                {
                    Speak.SpeakAsyncCancelAll();
                    Speak.Dispose();
                }

                if (thVoice != null && thVoice.ThreadState == ThreadState.Running)
                {
                    thVoice.Abort();
                }

                Speak = new SpeechSynthesizer();
                Speak.SetOutputToDefaultAudioDevice();

                strVoiceMsg = msg;

                //thVoice = new Thread(new ThreadStart(SpeakM));
                //thVoice.Start();
                Speak.SpeakAsync(msg);

                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            catch (Exception exception)
            {
                this.ErrInfo(exception);
            }
        }
        /// <summary>
        /// 播放文本語音
        /// </summary>
        /// <param name="msg"></param>
        public void SpeakText(string msg)
        {
            try
            {
                this.Speak = new SpeechSynthesizer();
                this.Speak.Speak(msg);
                this.Speak.SetOutputToNull();
                this.Speak.Dispose();
            }
            catch (Exception exception)
            {
                this.ErrInfo(exception);
            }
        }
        /// <summary>
        /// Speech播放文本合成語音
        /// </summary>
        /// <param name="msg"></param>
        public void Speech_SpeakText(string msg)
        {
            try
            {
                if (Voice != null)
                {
                    Voice.Speak(null, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
                    Voice.Speak(msg, SpeechVoiceSpeakFlags.SVSFlagsAsync);
                }
            }
            catch (Exception ex)
            {
                this.ErrInfo(ex);
            }
        }
        /// <summary>
        /// 關閉語音釋放資源
        /// </summary>
        public void SpeakClose()
        {
            try
            {
                if (Speak != null)
                {
                    this.Speak.SpeakAsyncCancelAll();
                    this.Speak.Dispose();
                }

                if (Voice != null)
                {
                    Voice.Speak(null, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
                }
            }
            catch (Exception ex)
            {
                cGlobe_Log.Error(cGlobe_Log.GetMethodInfo() + ex.Message);
            }
        }
        /// <summary>
        /// 獲取錯誤信息
        /// </summary>
        /// <param name="str"></param>
        private void ErrInfo(Exception str)
        {
            if (this.ErrorInfoEvent != null)
            {
                this.ErrorInfoEvent(str);
            }
        }
        #endregion

        ~WinSpeak()
        {
            try
            {
                if (Speak != null)
                {
                    this.Speak.SpeakAsyncCancelAll();
                    this.Speak.Dispose();
                }
            }
            catch (Exception exception)
            {
                //this.ErrInfo(exception);
            }
        }
    }
}
View Code

      1.2  調用如下(一個同步播放、一個非同步播放):  

   private void btnTest_Click(object sender, EventArgs e)
        {
            try
            {
                string strSep = txtWord.Text;
                SFBR.WinSpeak._Init().Speech_SpeakText(strSep);
            }
            catch (Exception ex)
            { }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                string strSep = txtWord.Text;
                SFBR.WinSpeak._Init().BeginSpeakText(strSep);
            }
            catch (Exception ex)
            { }
        }
View Code

   二、 最近客戶提出需求需要在BS系統實現文字語音播放的功能,因不能接入外網不能調用第三方服務等,最後想到了一個解決方案:先把文字轉化為音頻文件,再把音頻文件以流的形式推送到BS端進行播放;

       2.1  同樣可以利用微軟自帶的Speech語音播放庫將一段文本轉化為音頻文件:

       2.2 封裝 SpeechService文字轉換音頻文件類

    public class SpeechService
    {
        private static SpeechSynthesizer synth = null;
        /// <summary>
        /// 返回一個SpeechSynthesizer對象
        /// </summary>
        /// <returns></returns>
        private static SpeechSynthesizer GetSpeechSynthesizerInstance()
        {
            if (synth == null)
            {
                synth = new SpeechSynthesizer();
            }
            return synth;
        }
        /// <summary>
        /// 保存語音文件
        /// </summary>
        /// <param name="text"></param>
        public static void SaveMp3(string strFileName,string spText)
        {    
            synth = GetSpeechSynthesizerInstance();
            synth.Rate = 1;
            synth.Volume = 100;      
            synth.SetOutputToWaveFile(strFileName);
            synth.Speak(spText);
            synth.SetOutputToNull();
        }  
    }
View Code

       2.3  接下來就是將音頻文件以文件流的形式推送到前端播放:

  public async Task<ActionResult> PlayWav(string id,string spText)
        {    
            string strPath = Server.MapPath("~\\MP4\\" + id + ".wav");
            SpeechService.SaveMp3(strPath, spText);
            try
            {     
                using (FileStream fileStream = new FileStream(strPath, FileMode.Open))
                {
                    byte[] fileByte = new byte[fileStream.Length];
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.Read(fileByte, 0, (int)fileStream.Length);
                    long fSize = fileStream.Length;
                    long startbyte = 0;
                    long endbyte = fSize - 1;
                    int statusCode = 200;
                    if ((Request.Headers["Range"] != null))
                    {
                        //Get the actual byte range from the range header string, and set the starting byte.
                        string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
                        startbyte = Convert.ToInt64(range[1]);
                        if (range.Length > 2 && range[2] != "") endbyte = Convert.ToInt64(range[2]);
                        //If the start byte is not equal to zero, that means the user is requesting partial content.
                        if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
                        { statusCode = 206; }//Set the status code of the response to 206 (Partial Content) and add a content range header.                                    
                    }
                    long desSize = endbyte - startbyte + 1;
                    //Headers
                    Response.StatusCode = statusCode;
                    Response.ContentType = "audio/mpeg";
                    Response.AddHeader("Content-Accept", Response.ContentType);
                    Response.AddHeader("Content-Length", desSize.ToString());
                    Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}", startbyte, endbyte, fSize));
                    return File(fileByte, Response.ContentType);
               
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
View Code

    註意:返回的必須為非同步( async Task)不然會報錯,因為文字音頻轉換涉及到非同步調用

       2.4 前端展示

   

       2.5  運行截圖如下:

 BS實現文字音頻調用demo地址如下:

  https://github.com/lxshwyan/SpeechBSDemo.git

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.python介紹 Python(英國發音:/ˈpaɪθən/ 美國發音:/ˈpaɪθɑːn/)是一種廣泛使用的解釋型、高級編程、通用型編程語言,由吉多、範羅蘇姆創造,第一版發佈於1991年。可以視之為一種改良(加入一些其他編程語言的優點,如面向對象)的lisp。Python的設計哲學強調代碼的可 ...
  • 題目 "String painter " 給出兩個字元串s1,s2。對於每次操作可以將 s1 串中的任意一個子段變成另一個字元。問最少需要多少步操作能將s1串變為s2串。 解析 太妙了這個題,mark一下。 這個題先考慮怎麼由空串轉化s2, $f[i][j]$表示從空串到s2最少的次數, 則有$f[ ...
  • 3.9各類型數據方法補充,轉換,分類,編碼,坑中菜 3.9.1數據類型方法補充 1.str:不可變 補充方法 1. s1.capitalize():首字母大寫 2. s1.title(): 每個單詞首字母大寫 3. s1.swapcase():大小寫反轉 4. s1.center():居中 填充 5 ...
  • 1.各種斷言方法 常用斷言方法: 方法 用途 assertEqual(a, b) 核實a == b assertNotEqual(a, b) 核實a != b assertTrue(x) 核實x為True assertFalse(x) 核實x為False asseertIn(item, list) ...
  • Github有一個經過重寫的微信小程式SignalR的js類庫 https://github.com/liangshiw/SignalRMiniProgram-Client 於是我把他改成支付寶小程式的版本,上面這個項目的核心代碼基本沒有變,只是小程式開放介面改了一下,在支付寶小程式就能跑起來了 把 ...
  • App_Code 下創建的.cs文件僅僅是“內容”不是代碼。設置文件為“編譯”就可正常引用。 ...
  • 這篇文章主要講解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建項目框架的時候。 一、什麼是泛型 泛型是C#2.0推出的新語法,不是語法糖,而是2.0由框架升級提供的功能。 我們在編程程式時,經常會遇到功能非常相似的模塊,只是它們處理的數據不一樣。但我們沒有辦法,只能分別寫多個方法來處理不同的 ...
  • 主要記錄下如何在EF 中連接Oracle s資料庫,很傻瓜式,非常簡單,但是不知道的童鞋,也會搞得很難受,我自己就是 1.創一個控制台程式,並且添加 Oracle.ManagedDataAccess.EntityFramework 2.添加完之後,會自動在App.config 中添加一堆配置信息,主 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...