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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...