翼度科技»论坛 编程开发 .net 查看内容

C#调用科大讯飞离线语音合成实现文本转语音

10

主题

10

帖子

30

积分

新手上路

Rank: 1

积分
30
C#文本转语音(科大讯飞离线版)

引言

文本转语音(Text To Speech),简称TTS,在很多业务场景会用到,比如广播大厅,人机互动等。C#要实现TTS有不少选择,比如调用System.Speech,此处就不细说了,下面主要介绍一下C#调用科大讯飞的离线语音合成SDK来实现文本转语音。
产品介绍

地址:[https://www.xfyun.cn/service/offline_tts]
步骤

一、创建科大讯飞应用

进入科大讯飞控制台创建一个应用:[https://console.xfyun.cn/app/myapp],没有账号的可以先注册一个。

创建应用后会有一个APPID,先记下来,后面写代码会用到。
二、下载对应平台的SDK

点击刚创建的应用,进去应用服务界面,在左侧点击语音合成下面的离线语音合成(普通版/高品质版),如下

如果是windows平台,那么只能选择普通版。Linux的话可以选择高品质版,两者的效果在我看来相差还是比较大的。

下载完解压出来,目录如下

里面我们需要用到的是bin目录内的文件,当然你也可以参考samples里面的c语言代码,跟后面我提供的C#代码差不多
三、编写C#代码

Windows版
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.IO;
  7. namespace Speech
  8. {
  9.     /// <summary>
  10.     /// 讯飞语音合成
  11.     /// Author:String Lee
  12.     /// Date:2021年12月15日 14:06:00
  13.     /// </summary>
  14.     public class WindowsXFTTSUtils
  15.     {
  16.         #region TTS枚举常量
  17.         public enum ErrorCode
  18.         {
  19.             MSP_SUCCESS = 0,
  20.             MSP_ERROR_FAIL = -1,
  21.             MSP_ERROR_EXCEPTION = -2,
  22.             /* General errors 10100(0x2774) */
  23.             MSP_ERROR_GENERAL = 10100,     /* 0x2774 */
  24.             MSP_ERROR_OUT_OF_MEMORY = 10101,     /* 0x2775 */
  25.             MSP_ERROR_FILE_NOT_FOUND = 10102,     /* 0x2776 */
  26.             MSP_ERROR_NOT_SUPPORT = 10103,     /* 0x2777 */
  27.             MSP_ERROR_NOT_IMPLEMENT = 10104,     /* 0x2778 */
  28.             MSP_ERROR_ACCESS = 10105,     /* 0x2779 */
  29.             MSP_ERROR_INVALID_PARA = 10106,     /* 0x277A */
  30.             MSP_ERROR_INVALID_PARA_VALUE = 10107,     /* 0x277B */
  31.             MSP_ERROR_INVALID_HANDLE = 10108,     /* 0x277C */
  32.             MSP_ERROR_INVALID_DATA = 10109,     /* 0x277D */
  33.             MSP_ERROR_NO_LICENSE = 10110,     /* 0x277E */
  34.             MSP_ERROR_NOT_INIT = 10111,     /* 0x277F */
  35.             MSP_ERROR_NULL_HANDLE = 10112,     /* 0x2780 */
  36.             MSP_ERROR_OVERFLOW = 10113,     /* 0x2781 */
  37.             MSP_ERROR_TIME_OUT = 10114,     /* 0x2782 */
  38.             MSP_ERROR_OPEN_FILE = 10115,     /* 0x2783 */
  39.             MSP_ERROR_NOT_FOUND = 10116,     /* 0x2784 */
  40.             MSP_ERROR_NO_ENOUGH_BUFFER = 10117,     /* 0x2785 */
  41.             MSP_ERROR_NO_DATA = 10118,     /* 0x2786 */
  42.             MSP_ERROR_NO_MORE_DATA = 10119,     /* 0x2787 */
  43.             MSP_ERROR_SKIPPED = 10120,     /* 0x2788 */
  44.             MSP_ERROR_ALREADY_EXIST = 10121,     /* 0x2789 */
  45.             MSP_ERROR_LOAD_MODULE = 10122,     /* 0x278A */
  46.             MSP_ERROR_BUSY = 10123,     /* 0x278B */
  47.             MSP_ERROR_INVALID_CONFIG = 10124,     /* 0x278C */
  48.             MSP_ERROR_VERSION_CHECK = 10125,     /* 0x278D */
  49.             MSP_ERROR_CANCELED = 10126,     /* 0x278E */
  50.             MSP_ERROR_INVALID_MEDIA_TYPE = 10127,     /* 0x278F */
  51.             MSP_ERROR_CONFIG_INITIALIZE = 10128,     /* 0x2790 */
  52.             MSP_ERROR_CREATE_HANDLE = 10129,     /* 0x2791 */
  53.             MSP_ERROR_CODING_LIB_NOT_LOAD = 10130,     /* 0x2792 */
  54.             /* Error codes of network 10200(0x27D8)*/
  55.             MSP_ERROR_NET_GENERAL = 10200,     /* 0x27D8 */
  56.             MSP_ERROR_NET_OPENSOCK = 10201,     /* 0x27D9 */   /* Open socket */
  57.             MSP_ERROR_NET_CONNECTSOCK = 10202,     /* 0x27DA */   /* Connect socket */
  58.             MSP_ERROR_NET_ACCEPTSOCK = 10203,     /* 0x27DB */   /* Accept socket */
  59.             MSP_ERROR_NET_SENDSOCK = 10204,     /* 0x27DC */   /* Send socket data */
  60.             MSP_ERROR_NET_RECVSOCK = 10205,     /* 0x27DD */   /* Recv socket data */
  61.             MSP_ERROR_NET_INVALIDSOCK = 10206,     /* 0x27DE */   /* Invalid socket handle */
  62.             MSP_ERROR_NET_BADADDRESS = 10207,     /* 0x27EF */   /* Bad network address */
  63.             MSP_ERROR_NET_BINDSEQUENCE = 10208,     /* 0x27E0 */   /* Bind after listen/connect */
  64.             MSP_ERROR_NET_NOTOPENSOCK = 10209,     /* 0x27E1 */   /* Socket is not opened */
  65.             MSP_ERROR_NET_NOTBIND = 10210,     /* 0x27E2 */   /* Socket is not bind to an address */
  66.             MSP_ERROR_NET_NOTLISTEN = 10211,     /* 0x27E3 */   /* Socket is not listenning */
  67.             MSP_ERROR_NET_CONNECTCLOSE = 10212,     /* 0x27E4 */   /* The other side of connection is closed */
  68.             MSP_ERROR_NET_NOTDGRAMSOCK = 10213,     /* 0x27E5 */   /* The socket is not datagram type */
  69.             /* Error codes of mssp message 10300(0x283C) */
  70.             MSP_ERROR_MSG_GENERAL = 10300,     /* 0x283C */
  71.             MSP_ERROR_MSG_PARSE_ERROR = 10301,     /* 0x283D */
  72.             MSP_ERROR_MSG_BUILD_ERROR = 10302,     /* 0x283E */
  73.             MSP_ERROR_MSG_PARAM_ERROR = 10303,     /* 0x283F */
  74.             MSP_ERROR_MSG_CONTENT_EMPTY = 10304,     /* 0x2840 */
  75.             MSP_ERROR_MSG_INVALID_CONTENT_TYPE = 10305,     /* 0x2841 */
  76.             MSP_ERROR_MSG_INVALID_CONTENT_LENGTH = 10306,     /* 0x2842 */
  77.             MSP_ERROR_MSG_INVALID_CONTENT_ENCODE = 10307,     /* 0x2843 */
  78.             MSP_ERROR_MSG_INVALID_KEY = 10308,     /* 0x2844 */
  79.             MSP_ERROR_MSG_KEY_EMPTY = 10309,     /* 0x2845 */
  80.             MSP_ERROR_MSG_SESSION_ID_EMPTY = 10310,     /* 0x2846 */
  81.             MSP_ERROR_MSG_LOGIN_ID_EMPTY = 10311,     /* 0x2847 */
  82.             MSP_ERROR_MSG_SYNC_ID_EMPTY = 10312,     /* 0x2848 */
  83.             MSP_ERROR_MSG_APP_ID_EMPTY = 10313,     /* 0x2849 */
  84.             MSP_ERROR_MSG_EXTERN_ID_EMPTY = 10314,     /* 0x284A */
  85.             MSP_ERROR_MSG_INVALID_CMD = 10315,     /* 0x284B */
  86.             MSP_ERROR_MSG_INVALID_SUBJECT = 10316,     /* 0x284C */
  87.             MSP_ERROR_MSG_INVALID_VERSION = 10317,     /* 0x284D */
  88.             MSP_ERROR_MSG_NO_CMD = 10318,     /* 0x284E */
  89.             MSP_ERROR_MSG_NO_SUBJECT = 10319,     /* 0x284F */
  90.             MSP_ERROR_MSG_NO_VERSION = 10320,     /* 0x2850 */
  91.             MSP_ERROR_MSG_MSSP_EMPTY = 10321,     /* 0x2851 */
  92.             MSP_ERROR_MSG_NEW_RESPONSE = 10322,     /* 0x2852 */
  93.             MSP_ERROR_MSG_NEW_CONTENT = 10323,     /* 0x2853 */
  94.             MSP_ERROR_MSG_INVALID_SESSION_ID = 10324,     /* 0x2854 */
  95.             /* Error codes of DataBase 10400(0x28A0)*/
  96.             MSP_ERROR_DB_GENERAL = 10400,     /* 0x28A0 */
  97.             MSP_ERROR_DB_EXCEPTION = 10401,     /* 0x28A1 */
  98.             MSP_ERROR_DB_NO_RESULT = 10402,     /* 0x28A2 */
  99.             MSP_ERROR_DB_INVALID_USER = 10403,     /* 0x28A3 */
  100.             MSP_ERROR_DB_INVALID_PWD = 10404,     /* 0x28A4 */
  101.             MSP_ERROR_DB_CONNECT = 10405,     /* 0x28A5 */
  102.             MSP_ERROR_DB_INVALID_SQL = 10406,     /* 0x28A6 */
  103.             MSP_ERROR_DB_INVALID_APPID = 10407,    /* 0x28A7 */
  104.             /* Error codes of Resource 10500(0x2904)*/
  105.             MSP_ERROR_RES_GENERAL = 10500,     /* 0x2904 */
  106.             MSP_ERROR_RES_LOAD = 10501,     /* 0x2905 */   /* Load resource */
  107.             MSP_ERROR_RES_FREE = 10502,     /* 0x2906 */   /* Free resource */
  108.             MSP_ERROR_RES_MISSING = 10503,     /* 0x2907 */   /* Resource File Missing */
  109.             MSP_ERROR_RES_INVALID_NAME = 10504,     /* 0x2908 */   /* Invalid resource file name */
  110.             MSP_ERROR_RES_INVALID_ID = 10505,     /* 0x2909 */   /* Invalid resource ID */
  111.             MSP_ERROR_RES_INVALID_IMG = 10506,     /* 0x290A */   /* Invalid resource image pointer */
  112.             MSP_ERROR_RES_WRITE = 10507,     /* 0x290B */   /* Write read-only resource */
  113.             MSP_ERROR_RES_LEAK = 10508,     /* 0x290C */   /* Resource leak out */
  114.             MSP_ERROR_RES_HEAD = 10509,     /* 0x290D */   /* Resource head currupt */
  115.             MSP_ERROR_RES_DATA = 10510,     /* 0x290E */   /* Resource data currupt */
  116.             MSP_ERROR_RES_SKIP = 10511,     /* 0x290F */   /* Resource file skipped */
  117.             /* Error codes of TTS 10600(0x2968)*/
  118.             MSP_ERROR_TTS_GENERAL = 10600,     /* 0x2968 */
  119.             MSP_ERROR_TTS_TEXTEND = 10601,     /* 0x2969 */  /* Meet text end */
  120.             MSP_ERROR_TTS_TEXT_EMPTY = 10602,     /* 0x296A */  /* no synth text */
  121.             /* Error codes of Recognizer 10700(0x29CC) */
  122.             MSP_ERROR_REC_GENERAL = 10700,     /* 0x29CC */
  123.             MSP_ERROR_REC_INACTIVE = 10701,     /* 0x29CD */
  124.             MSP_ERROR_REC_GRAMMAR_ERROR = 10702,     /* 0x29CE */
  125.             MSP_ERROR_REC_NO_ACTIVE_GRAMMARS = 10703,     /* 0x29CF */
  126.             MSP_ERROR_REC_DUPLICATE_GRAMMAR = 10704,     /* 0x29D0 */
  127.             MSP_ERROR_REC_INVALID_MEDIA_TYPE = 10705,     /* 0x29D1 */
  128.             MSP_ERROR_REC_INVALID_LANGUAGE = 10706,     /* 0x29D2 */
  129.             MSP_ERROR_REC_URI_NOT_FOUND = 10707,     /* 0x29D3 */
  130.             MSP_ERROR_REC_URI_TIMEOUT = 10708,     /* 0x29D4 */
  131.             MSP_ERROR_REC_URI_FETCH_ERROR = 10709,     /* 0x29D5 */
  132.             /* Error codes of Speech Detector 10800(0x2A30) */
  133.             MSP_ERROR_EP_GENERAL = 10800,     /* 0x2A30 */
  134.             MSP_ERROR_EP_NO_SESSION_NAME = 10801,     /* 0x2A31 */
  135.             MSP_ERROR_EP_INACTIVE = 10802,     /* 0x2A32 */
  136.             MSP_ERROR_EP_INITIALIZED = 10803,     /* 0x2A33 */
  137.             /* Error codes of TUV */
  138.             MSP_ERROR_TUV_GENERAL = 10900,     /* 0x2A94 */
  139.             MSP_ERROR_TUV_GETHIDPARAM = 10901,     /* 0x2A95 */   /* Get Busin Param huanid*/
  140.             MSP_ERROR_TUV_TOKEN = 10902,     /* 0x2A96 */   /* Get Token */
  141.             MSP_ERROR_TUV_CFGFILE = 10903,     /* 0x2A97 */   /* Open cfg file */
  142.             MSP_ERROR_TUV_RECV_CONTENT = 10904,     /* 0x2A98 */   /* received content is error */
  143.             MSP_ERROR_TUV_VERFAIL = 10905,     /* 0x2A99 */   /* Verify failure */
  144.             /* Error codes of IMTV */
  145.             MSP_ERROR_IMTV_SUCCESS = 11000,     /* 0x2AF8 */   /* 成功 */
  146.             MSP_ERROR_IMTV_NO_LICENSE = 11001,     /* 0x2AF9 */   /* 试用次数结束,用户需要付费 */
  147.             MSP_ERROR_IMTV_SESSIONID_INVALID = 11002,     /* 0x2AFA */   /* SessionId失效,需要重新登录通行证 */
  148.             MSP_ERROR_IMTV_SESSIONID_ERROR = 11003,     /* 0x2AFB */   /* SessionId为空,或者非法 */
  149.             MSP_ERROR_IMTV_UNLOGIN = 11004,     /* 0x2AFC */   /* 未登录通行证 */
  150.             MSP_ERROR_IMTV_SYSTEM_ERROR = 11005,     /* 0x2AFD */   /* 系统错误 */
  151.             /* Error codes of HCR */
  152.             MSP_ERROR_HCR_GENERAL = 11100,
  153.             MSP_ERROR_HCR_RESOURCE_NOT_EXIST = 11101,
  154.             /* Error codes of http 12000(0x2EE0) */
  155.             MSP_ERROR_HTTP_BASE = 12000,    /* 0x2EE0 */
  156.             /*Error codes of ISV */
  157.             MSP_ERROR_ISV_NO_USER = 13000,    /* 32C8 */    /* the user doesn't exist */
  158.         }
  159.         public enum SynthStatus
  160.         {
  161.             MSP_TTS_FLAG_STILL_HAVE_DATA = 1,
  162.             MSP_TTS_FLAG_DATA_END = 2,
  163.             MSP_TTS_FLAG_CMD_CANCELED = 0
  164.         }
  165.         #endregion
  166.         #region TTS dll import
  167.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  168.         public static extern int MSPLogin(string user, string password, string configs);
  169.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  170.         public static extern int MSPLogout();
  171.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  172.         public static extern IntPtr QTTSSessionBegin(string _params, ref int errorCode);
  173.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  174.         public static extern int QTTSTextPut(string sessionID, string textString, uint textLen, string _params);
  175.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  176.         public static extern IntPtr QTTSAudioGet(string sessionID, ref uint audioLen, ref SynthStatus synthStatus, ref int errorCode);
  177.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  178.         public static extern IntPtr QTTSAudioInfo(string sessionID);
  179.         [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]
  180.         public static extern int QTTSSessionEnd(string sessionID, string hints);
  181.         #endregion
  182.         /// <summary>
  183.         /// 生成语音文件
  184.         /// </summary>
  185.         /// <param name="text"></param>
  186.         /// <param name="filename"></param>
  187.         /// <param name="speaker"></param>
  188.         /// <param name="speed"></param>
  189.         /// <returns></returns>
  190.         public static bool GetAudio(string text, string filename, string speaker, int speed)
  191.         {
  192.             IntPtr session_ID = IntPtr.Zero;
  193.             try
  194.             {
  195.                 string login_configs = $"appid =xxx ";//登录参数,自己注册后获取的appid
  196.                 string type = speaker;
  197.                 uint audio_len = 0;
  198.                 SynthStatus synth_status = SynthStatus.MSP_TTS_FLAG_STILL_HAVE_DATA;
  199.                 var ret = WindowsXFTTSUtils.MSPLogin(string.Empty, string.Empty, login_configs);
  200.                 //MSPLogin方法返回失败
  201.                 if (ret != (int)ErrorCode.MSP_SUCCESS)
  202.                 {
  203.                     return false;
  204.                 }
  205.                 string _params = $"engine_type = local,rdn = 2, speed = {speed}, volume = 100, rcn = 0, voice_name={type}, tts_res_path =fo|res\\tts\\{type}.jet;fo|res\\tts\\common.jet, sample_rate = 16000";
  206.                 //string _params = "ssm=1,ent=sms16k,vcn=xiaoyan,spd=medium,aue=speex-wb;7,vol=x-loud,auf=audio/L16;rate=16000";
  207.                 //string @params = "engine_type = local,voice_name=xiaoyan,speed=50,volume=50,pitch=50,rcn=1, text_encoding = UTF8, background_sound=1,sample_rate = 16000";
  208.                 session_ID = WindowsXFTTSUtils.QTTSSessionBegin(_params, ref ret);
  209.                 //QTTSSessionBegin方法返回失败
  210.                 if (ret != (int)ErrorCode.MSP_SUCCESS)
  211.                 {
  212.                     return false;
  213.                 }
  214.                 ret = WindowsXFTTSUtils.QTTSTextPut(Ptr2Str(session_ID), text, (uint)Encoding.Default.GetByteCount(text), string.Empty);
  215.                 //QTTSTextPut方法返回失败
  216.                 if (ret != (int)ErrorCode.MSP_SUCCESS)
  217.                 {
  218.                     return false;
  219.                 }
  220.                 MemoryStream memoryStream = new MemoryStream();
  221.                 memoryStream.Write(new byte[44], 0, 44);
  222.                 while (true)
  223.                 {
  224.                     IntPtr source = WindowsXFTTSUtils.QTTSAudioGet(Ptr2Str(session_ID), ref audio_len, ref synth_status, ref ret);
  225.                     if (source != IntPtr.Zero)
  226.                     {
  227.                         byte[] array = new byte[(int)audio_len];
  228.                         if (audio_len > 0)
  229.                         {
  230.                             Marshal.Copy(source, array, 0, (int)audio_len);
  231.                         }
  232.                         memoryStream.Write(array, 0, array.Length);
  233.                     }
  234.                     if (synth_status == SynthStatus.MSP_TTS_FLAG_DATA_END || ret != 0)
  235.                         break;
  236.                 }
  237.                 WAVE_Header wave_Header = GetWave_Header((int)memoryStream.Length - 44);
  238.                 byte[] array2 = StructToBytes(wave_Header);
  239.                 memoryStream.Position = 0L;
  240.                 memoryStream.Write(array2, 0, array2.Length);
  241.                 memoryStream.Position = 0L;
  242.                 if (filename != null)
  243.                 {
  244.                     var dir = Path.GetDirectoryName(filename);
  245.                     if (!Directory.Exists(dir))
  246.                         Directory.CreateDirectory(dir);
  247.                     FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write);
  248.                     memoryStream.WriteTo(fileStream);
  249.                     memoryStream.Close();
  250.                     fileStream.Close();
  251.                 }
  252.                 return true;
  253.             }
  254.             catch (Exception ex)
  255.             {
  256.                 return false;
  257.             }
  258.             finally
  259.             {
  260.                 WindowsXFTTSUtils.QTTSSessionEnd(Ptr2Str(session_ID), "");
  261.                 WindowsXFTTSUtils.MSPLogout();//退出登录
  262.             }
  263.         }
  264.         /// <summary>
  265.         /// 结构体转字符串
  266.         /// </summary>
  267.         /// <param name="structure"></param>
  268.         /// <returns></returns>
  269.         private static byte[] StructToBytes(object structure)
  270.         {
  271.             int num = Marshal.SizeOf(structure);
  272.             IntPtr intPtr = Marshal.AllocHGlobal(num);
  273.             byte[] result;
  274.             try
  275.             {
  276.                 Marshal.StructureToPtr(structure, intPtr, false);
  277.                 byte[] array = new byte[num];
  278.                 Marshal.Copy(intPtr, array, 0, num);
  279.                 result = array;
  280.             }
  281.             finally
  282.             {
  283.                 Marshal.FreeHGlobal(intPtr);
  284.             }
  285.             return result;
  286.         }
  287.         /// <summary>
  288.         /// 结构体初始化赋值
  289.         /// </summary>
  290.         /// <param name="data_len"></param>
  291.         /// <returns></returns>
  292.         private static WAVE_Header GetWave_Header(int data_len)
  293.         {
  294.             return new WAVE_Header
  295.             {
  296.                 RIFF_ID = 1179011410,
  297.                 File_Size = data_len + 36,
  298.                 RIFF_Type = 1163280727,
  299.                 FMT_ID = 544501094,
  300.                 FMT_Size = 16,
  301.                 FMT_Tag = 1,
  302.                 FMT_Channel = 1,
  303.                 FMT_SamplesPerSec = 16000,
  304.                 AvgBytesPerSec = 32000,
  305.                 BlockAlign = 2,
  306.                 BitsPerSample = 16,
  307.                 DATA_ID = 1635017060,
  308.                 DATA_Size = data_len
  309.             };
  310.         }
  311.         /// <summary>
  312.         /// 语音音频头
  313.         /// </summary>
  314.         private struct WAVE_Header
  315.         {
  316.             public int RIFF_ID;
  317.             public int File_Size;
  318.             public int RIFF_Type;
  319.             public int FMT_ID;
  320.             public int FMT_Size;
  321.             public short FMT_Tag;
  322.             public ushort FMT_Channel;
  323.             public int FMT_SamplesPerSec;
  324.             public int AvgBytesPerSec;
  325.             public ushort BlockAlign;
  326.             public ushort BitsPerSample;
  327.             public int DATA_ID;
  328.             public int DATA_Size;
  329.         }
  330.         /// 指针转字符串
  331.         /// </summary>
  332.         /// <param name="p">指向非托管代码字符串的指针</param>
  333.         /// <returns>返回指针指向的字符串</returns>
  334.         public static string Ptr2Str(IntPtr p)
  335.         {
  336.             List<byte> lb = new List<byte>();
  337.             while (Marshal.ReadByte(p) != 0)
  338.             {
  339.                 lb.Add(Marshal.ReadByte(p));
  340.                 p = p + 1;
  341.             }
  342.             return Encoding.Default.GetString(lb.ToArray());
  343.         }
  344.     }
  345. }
复制代码
Linux版
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.IO;
  7. namespace Speech
  8. {
  9.     /// <summary>
  10.     /// 讯飞语音合成
  11.     /// Author:String Lee
  12.     /// Date:2021年12月15日 14:06:00
  13.     /// </summary>
  14.     public class LinuxXFTTSUtils
  15.     {
  16.         #region TTS枚举常量
  17.         public enum ErrorCode
  18.         {
  19.             MSP_SUCCESS = 0,
  20.             MSP_ERROR_FAIL = -1,
  21.             MSP_ERROR_EXCEPTION = -2,
  22.             /* General errors 10100(0x2774) */
  23.             MSP_ERROR_GENERAL = 10100,     /* 0x2774 */
  24.             MSP_ERROR_OUT_OF_MEMORY = 10101,     /* 0x2775 */
  25.             MSP_ERROR_FILE_NOT_FOUND = 10102,     /* 0x2776 */
  26.             MSP_ERROR_NOT_SUPPORT = 10103,     /* 0x2777 */
  27.             MSP_ERROR_NOT_IMPLEMENT = 10104,     /* 0x2778 */
  28.             MSP_ERROR_ACCESS = 10105,     /* 0x2779 */
  29.             MSP_ERROR_INVALID_PARA = 10106,     /* 0x277A */
  30.             MSP_ERROR_INVALID_PARA_VALUE = 10107,     /* 0x277B */
  31.             MSP_ERROR_INVALID_HANDLE = 10108,     /* 0x277C */
  32.             MSP_ERROR_INVALID_DATA = 10109,     /* 0x277D */
  33.             MSP_ERROR_NO_LICENSE = 10110,     /* 0x277E */
  34.             MSP_ERROR_NOT_INIT = 10111,     /* 0x277F */
  35.             MSP_ERROR_NULL_HANDLE = 10112,     /* 0x2780 */
  36.             MSP_ERROR_OVERFLOW = 10113,     /* 0x2781 */
  37.             MSP_ERROR_TIME_OUT = 10114,     /* 0x2782 */
  38.             MSP_ERROR_OPEN_FILE = 10115,     /* 0x2783 */
  39.             MSP_ERROR_NOT_FOUND = 10116,     /* 0x2784 */
  40.             MSP_ERROR_NO_ENOUGH_BUFFER = 10117,     /* 0x2785 */
  41.             MSP_ERROR_NO_DATA = 10118,     /* 0x2786 */
  42.             MSP_ERROR_NO_MORE_DATA = 10119,     /* 0x2787 */
  43.             MSP_ERROR_SKIPPED = 10120,     /* 0x2788 */
  44.             MSP_ERROR_ALREADY_EXIST = 10121,     /* 0x2789 */
  45.             MSP_ERROR_LOAD_MODULE = 10122,     /* 0x278A */
  46.             MSP_ERROR_BUSY = 10123,     /* 0x278B */
  47.             MSP_ERROR_INVALID_CONFIG = 10124,     /* 0x278C */
  48.             MSP_ERROR_VERSION_CHECK = 10125,     /* 0x278D */
  49.             MSP_ERROR_CANCELED = 10126,     /* 0x278E */
  50.             MSP_ERROR_INVALID_MEDIA_TYPE = 10127,     /* 0x278F */
  51.             MSP_ERROR_CONFIG_INITIALIZE = 10128,     /* 0x2790 */
  52.             MSP_ERROR_CREATE_HANDLE = 10129,     /* 0x2791 */
  53.             MSP_ERROR_CODING_LIB_NOT_LOAD = 10130,     /* 0x2792 */
  54.             /* Error codes of network 10200(0x27D8)*/
  55.             MSP_ERROR_NET_GENERAL = 10200,     /* 0x27D8 */
  56.             MSP_ERROR_NET_OPENSOCK = 10201,     /* 0x27D9 */   /* Open socket */
  57.             MSP_ERROR_NET_CONNECTSOCK = 10202,     /* 0x27DA */   /* Connect socket */
  58.             MSP_ERROR_NET_ACCEPTSOCK = 10203,     /* 0x27DB */   /* Accept socket */
  59.             MSP_ERROR_NET_SENDSOCK = 10204,     /* 0x27DC */   /* Send socket data */
  60.             MSP_ERROR_NET_RECVSOCK = 10205,     /* 0x27DD */   /* Recv socket data */
  61.             MSP_ERROR_NET_INVALIDSOCK = 10206,     /* 0x27DE */   /* Invalid socket handle */
  62.             MSP_ERROR_NET_BADADDRESS = 10207,     /* 0x27EF */   /* Bad network address */
  63.             MSP_ERROR_NET_BINDSEQUENCE = 10208,     /* 0x27E0 */   /* Bind after listen/connect */
  64.             MSP_ERROR_NET_NOTOPENSOCK = 10209,     /* 0x27E1 */   /* Socket is not opened */
  65.             MSP_ERROR_NET_NOTBIND = 10210,     /* 0x27E2 */   /* Socket is not bind to an address */
  66.             MSP_ERROR_NET_NOTLISTEN = 10211,     /* 0x27E3 */   /* Socket is not listenning */
  67.             MSP_ERROR_NET_CONNECTCLOSE = 10212,     /* 0x27E4 */   /* The other side of connection is closed */
  68.             MSP_ERROR_NET_NOTDGRAMSOCK = 10213,     /* 0x27E5 */   /* The socket is not datagram type */
  69.             /* Error codes of mssp message 10300(0x283C) */
  70.             MSP_ERROR_MSG_GENERAL = 10300,     /* 0x283C */
  71.             MSP_ERROR_MSG_PARSE_ERROR = 10301,     /* 0x283D */
  72.             MSP_ERROR_MSG_BUILD_ERROR = 10302,     /* 0x283E */
  73.             MSP_ERROR_MSG_PARAM_ERROR = 10303,     /* 0x283F */
  74.             MSP_ERROR_MSG_CONTENT_EMPTY = 10304,     /* 0x2840 */
  75.             MSP_ERROR_MSG_INVALID_CONTENT_TYPE = 10305,     /* 0x2841 */
  76.             MSP_ERROR_MSG_INVALID_CONTENT_LENGTH = 10306,     /* 0x2842 */
  77.             MSP_ERROR_MSG_INVALID_CONTENT_ENCODE = 10307,     /* 0x2843 */
  78.             MSP_ERROR_MSG_INVALID_KEY = 10308,     /* 0x2844 */
  79.             MSP_ERROR_MSG_KEY_EMPTY = 10309,     /* 0x2845 */
  80.             MSP_ERROR_MSG_SESSION_ID_EMPTY = 10310,     /* 0x2846 */
  81.             MSP_ERROR_MSG_LOGIN_ID_EMPTY = 10311,     /* 0x2847 */
  82.             MSP_ERROR_MSG_SYNC_ID_EMPTY = 10312,     /* 0x2848 */
  83.             MSP_ERROR_MSG_APP_ID_EMPTY = 10313,     /* 0x2849 */
  84.             MSP_ERROR_MSG_EXTERN_ID_EMPTY = 10314,     /* 0x284A */
  85.             MSP_ERROR_MSG_INVALID_CMD = 10315,     /* 0x284B */
  86.             MSP_ERROR_MSG_INVALID_SUBJECT = 10316,     /* 0x284C */
  87.             MSP_ERROR_MSG_INVALID_VERSION = 10317,     /* 0x284D */
  88.             MSP_ERROR_MSG_NO_CMD = 10318,     /* 0x284E */
  89.             MSP_ERROR_MSG_NO_SUBJECT = 10319,     /* 0x284F */
  90.             MSP_ERROR_MSG_NO_VERSION = 10320,     /* 0x2850 */
  91.             MSP_ERROR_MSG_MSSP_EMPTY = 10321,     /* 0x2851 */
  92.             MSP_ERROR_MSG_NEW_RESPONSE = 10322,     /* 0x2852 */
  93.             MSP_ERROR_MSG_NEW_CONTENT = 10323,     /* 0x2853 */
  94.             MSP_ERROR_MSG_INVALID_SESSION_ID = 10324,     /* 0x2854 */
  95.             /* Error codes of DataBase 10400(0x28A0)*/
  96.             MSP_ERROR_DB_GENERAL = 10400,     /* 0x28A0 */
  97.             MSP_ERROR_DB_EXCEPTION = 10401,     /* 0x28A1 */
  98.             MSP_ERROR_DB_NO_RESULT = 10402,     /* 0x28A2 */
  99.             MSP_ERROR_DB_INVALID_USER = 10403,     /* 0x28A3 */
  100.             MSP_ERROR_DB_INVALID_PWD = 10404,     /* 0x28A4 */
  101.             MSP_ERROR_DB_CONNECT = 10405,     /* 0x28A5 */
  102.             MSP_ERROR_DB_INVALID_SQL = 10406,     /* 0x28A6 */
  103.             MSP_ERROR_DB_INVALID_APPID = 10407,    /* 0x28A7 */
  104.             /* Error codes of Resource 10500(0x2904)*/
  105.             MSP_ERROR_RES_GENERAL = 10500,     /* 0x2904 */
  106.             MSP_ERROR_RES_LOAD = 10501,     /* 0x2905 */   /* Load resource */
  107.             MSP_ERROR_RES_FREE = 10502,     /* 0x2906 */   /* Free resource */
  108.             MSP_ERROR_RES_MISSING = 10503,     /* 0x2907 */   /* Resource File Missing */
  109.             MSP_ERROR_RES_INVALID_NAME = 10504,     /* 0x2908 */   /* Invalid resource file name */
  110.             MSP_ERROR_RES_INVALID_ID = 10505,     /* 0x2909 */   /* Invalid resource ID */
  111.             MSP_ERROR_RES_INVALID_IMG = 10506,     /* 0x290A */   /* Invalid resource image pointer */
  112.             MSP_ERROR_RES_WRITE = 10507,     /* 0x290B */   /* Write read-only resource */
  113.             MSP_ERROR_RES_LEAK = 10508,     /* 0x290C */   /* Resource leak out */
  114.             MSP_ERROR_RES_HEAD = 10509,     /* 0x290D */   /* Resource head currupt */
  115.             MSP_ERROR_RES_DATA = 10510,     /* 0x290E */   /* Resource data currupt */
  116.             MSP_ERROR_RES_SKIP = 10511,     /* 0x290F */   /* Resource file skipped */
  117.             /* Error codes of TTS 10600(0x2968)*/
  118.             MSP_ERROR_TTS_GENERAL = 10600,     /* 0x2968 */
  119.             MSP_ERROR_TTS_TEXTEND = 10601,     /* 0x2969 */  /* Meet text end */
  120.             MSP_ERROR_TTS_TEXT_EMPTY = 10602,     /* 0x296A */  /* no synth text */
  121.             /* Error codes of Recognizer 10700(0x29CC) */
  122.             MSP_ERROR_REC_GENERAL = 10700,     /* 0x29CC */
  123.             MSP_ERROR_REC_INACTIVE = 10701,     /* 0x29CD */
  124.             MSP_ERROR_REC_GRAMMAR_ERROR = 10702,     /* 0x29CE */
  125.             MSP_ERROR_REC_NO_ACTIVE_GRAMMARS = 10703,     /* 0x29CF */
  126.             MSP_ERROR_REC_DUPLICATE_GRAMMAR = 10704,     /* 0x29D0 */
  127.             MSP_ERROR_REC_INVALID_MEDIA_TYPE = 10705,     /* 0x29D1 */
  128.             MSP_ERROR_REC_INVALID_LANGUAGE = 10706,     /* 0x29D2 */
  129.             MSP_ERROR_REC_URI_NOT_FOUND = 10707,     /* 0x29D3 */
  130.             MSP_ERROR_REC_URI_TIMEOUT = 10708,     /* 0x29D4 */
  131.             MSP_ERROR_REC_URI_FETCH_ERROR = 10709,     /* 0x29D5 */
  132.             /* Error codes of Speech Detector 10800(0x2A30) */
  133.             MSP_ERROR_EP_GENERAL = 10800,     /* 0x2A30 */
  134.             MSP_ERROR_EP_NO_SESSION_NAME = 10801,     /* 0x2A31 */
  135.             MSP_ERROR_EP_INACTIVE = 10802,     /* 0x2A32 */
  136.             MSP_ERROR_EP_INITIALIZED = 10803,     /* 0x2A33 */
  137.             /* Error codes of TUV */
  138.             MSP_ERROR_TUV_GENERAL = 10900,     /* 0x2A94 */
  139.             MSP_ERROR_TUV_GETHIDPARAM = 10901,     /* 0x2A95 */   /* Get Busin Param huanid*/
  140.             MSP_ERROR_TUV_TOKEN = 10902,     /* 0x2A96 */   /* Get Token */
  141.             MSP_ERROR_TUV_CFGFILE = 10903,     /* 0x2A97 */   /* Open cfg file */
  142.             MSP_ERROR_TUV_RECV_CONTENT = 10904,     /* 0x2A98 */   /* received content is error */
  143.             MSP_ERROR_TUV_VERFAIL = 10905,     /* 0x2A99 */   /* Verify failure */
  144.             /* Error codes of IMTV */
  145.             MSP_ERROR_IMTV_SUCCESS = 11000,     /* 0x2AF8 */   /* 成功 */
  146.             MSP_ERROR_IMTV_NO_LICENSE = 11001,     /* 0x2AF9 */   /* 试用次数结束,用户需要付费 */
  147.             MSP_ERROR_IMTV_SESSIONID_INVALID = 11002,     /* 0x2AFA */   /* SessionId失效,需要重新登录通行证 */
  148.             MSP_ERROR_IMTV_SESSIONID_ERROR = 11003,     /* 0x2AFB */   /* SessionId为空,或者非法 */
  149.             MSP_ERROR_IMTV_UNLOGIN = 11004,     /* 0x2AFC */   /* 未登录通行证 */
  150.             MSP_ERROR_IMTV_SYSTEM_ERROR = 11005,     /* 0x2AFD */   /* 系统错误 */
  151.             /* Error codes of HCR */
  152.             MSP_ERROR_HCR_GENERAL = 11100,
  153.             MSP_ERROR_HCR_RESOURCE_NOT_EXIST = 11101,
  154.             /* Error codes of http 12000(0x2EE0) */
  155.             MSP_ERROR_HTTP_BASE = 12000,    /* 0x2EE0 */
  156.             /*Error codes of ISV */
  157.             MSP_ERROR_ISV_NO_USER = 13000,    /* 32C8 */    /* the user doesn't exist */
  158.         }
  159.         public enum SynthStatus
  160.         {
  161.             MSP_TTS_FLAG_STILL_HAVE_DATA = 1,
  162.             MSP_TTS_FLAG_DATA_END = 2,
  163.             MSP_TTS_FLAG_CMD_CANCELED = 0
  164.         }
  165.         #endregion
  166.         #region TTS dll import
  167.         [DllImport("libmsc.so", EntryPoint = "MSPLogin", CallingConvention = CallingConvention.Cdecl)]
  168.         public static extern int MSPLogin(string user, string password, string configs);
  169.         [DllImport("libmsc.so", EntryPoint = "MSPLogout", CallingConvention = CallingConvention.Cdecl)]
  170.         public static extern int MSPLogout();
  171.         [DllImport("libmsc.so", EntryPoint = "QTTSSessionBegin", CallingConvention = CallingConvention.Cdecl)]
  172.         public static extern IntPtr QTTSSessionBegin(string _params, ref int errorCode);
  173.         [DllImport("libmsc.so", EntryPoint = "QTTSTextPut", CallingConvention = CallingConvention.Cdecl)]
  174.         public static extern int QTTSTextPut(string sessionID, string textString, uint textLen, string _params);
  175.         [DllImport("libmsc.so", EntryPoint = "QTTSAudioGet", CallingConvention = CallingConvention.Cdecl)]
  176.         public static extern IntPtr QTTSAudioGet(string sessionID, ref uint audioLen, ref SynthStatus synthStatus, ref int errorCode);
  177.         [DllImport("libmsc.so", EntryPoint = "QTTSAudioInfo", CallingConvention = CallingConvention.Cdecl)]
  178.         public static extern IntPtr QTTSAudioInfo(string sessionID);
  179.         [DllImport("libmsc.so", EntryPoint = "QTTSSessionEnd", CallingConvention = CallingConvention.Cdecl)]
  180.         public static extern int QTTSSessionEnd(string sessionID, string hints);
  181.         #endregion
  182.         /// <summary>
  183.         /// 生成语音文件
  184.         /// </summary>
  185.         /// <param name="text"></param>
  186.         /// <param name="filename"></param>
  187.         /// <param name="speaker"></param>
  188.         /// <param name="speed"></param>
  189.         /// <returns></returns>
  190.         public static bool GetAudio(string text, string filename, string speaker, int speed)
  191.         {
  192.             IntPtr session_ID = IntPtr.Zero;
  193.             try
  194.             {
  195.                 string login_configs = $"appid =xxx ";//登录参数,自己注册后获取的appid
  196.                 string type = speaker;
  197.                 uint audio_len = 0;
  198.                 SynthStatus synth_status = SynthStatus.MSP_TTS_FLAG_STILL_HAVE_DATA;
  199.                 var ret = LinuxXFTTSUtils.MSPLogin(string.Empty, string.Empty, login_configs);
  200.                 //MSPLogin方法返回失败
  201.                 if (ret != (int)ErrorCode.MSP_SUCCESS)
  202.                 {
  203.                     Console.WriteLine("1");
  204.                     return false;
  205.                 }
  206.                 //string _params = $"engine_type = purextts,rdn = 2, speed = {speed}, volume = 100, rcn = 0, voice_name={type}, tts_res_path =fo|res\\xtts\\{type}.jet;fo|res\\xtts\\common.jet, sample_rate = 16000";
  207.                 string _params = $"engine_type = purextts,voice_name={speaker}, text_encoding = UTF8, tts_res_path = fo|res/xtts/{speaker}.jet;fo|res/xtts/common.jet, sample_rate = 16000, speed = {speed}, volume = 100, pitch = 50, rdn = 2";
  208.                 //string _params = "ssm=1,ent=sms16k,vcn=xiaoyan,spd=medium,aue=speex-wb;7,vol=x-loud,auf=audio/L16;rate=16000";
  209.                 //string @params = "engine_type = local,voice_name=xiaoyan,speed=50,volume=50,pitch=50,rcn=1, text_encoding = UTF8, background_sound=1,sample_rate = 16000";
  210.                 session_ID = LinuxXFTTSUtils.QTTSSessionBegin(_params, ref ret);
  211.                 //QTTSSessionBegin方法返回失败
  212.                 if (ret != (int)ErrorCode.MSP_SUCCESS)
  213.                 {
  214.                     return false;
  215.                 }
  216.                 ret = LinuxXFTTSUtils.QTTSTextPut(Ptr2Str(session_ID), text, (uint)Encoding.Default.GetByteCount(text), string.Empty);
  217.                 //QTTSTextPut方法返回失败
  218.                 if (ret != (int)ErrorCode.MSP_SUCCESS)
  219.                 {
  220.                     return false;
  221.                 }
  222.                 MemoryStream memoryStream = new MemoryStream();
  223.                 memoryStream.Write(new byte[44], 0, 44);
  224.                 while (true)
  225.                 {
  226.                     IntPtr source = LinuxXFTTSUtils.QTTSAudioGet(Ptr2Str(session_ID), ref audio_len, ref synth_status, ref ret);
  227.                     if (source != IntPtr.Zero)
  228.                     {
  229.                         byte[] array = new byte[(int)audio_len];
  230.                         if (audio_len > 0)
  231.                         {
  232.                             Marshal.Copy(source, array, 0, (int)audio_len);
  233.                         }
  234.                         memoryStream.Write(array, 0, array.Length);
  235.                     }
  236.                     if (synth_status == SynthStatus.MSP_TTS_FLAG_DATA_END || ret != 0)
  237.                         break;
  238.                 }
  239.                 WAVE_Header wave_Header = GetWave_Header((int)memoryStream.Length - 44);
  240.                 byte[] array2 = StructToBytes(wave_Header);
  241.                 memoryStream.Position = 0L;
  242.                 memoryStream.Write(array2, 0, array2.Length);
  243.                 memoryStream.Position = 0L;
  244.                 if (filename != null)
  245.                 {
  246.                     var dir = Path.GetDirectoryName(filename);
  247.                     if (!Directory.Exists(dir))
  248.                         Directory.CreateDirectory(dir);
  249.                     FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write);
  250.                     memoryStream.WriteTo(fileStream);
  251.                     memoryStream.Close();
  252.                     fileStream.Close();
  253.                 }
  254.                 return true;
  255.             }
  256.             catch (Exception ex)
  257.             {
  258.                 return false;
  259.             }
  260.             finally
  261.             {
  262.                 LinuxXFTTSUtils.QTTSSessionEnd(Ptr2Str(session_ID), "");
  263.                 LinuxXFTTSUtils.MSPLogout();//退出登录
  264.             }
  265.         }
  266.         /// <summary>
  267.         /// 结构体转字符串
  268.         /// </summary>
  269.         /// <param name="structure"></param>
  270.         /// <returns></returns>
  271.         private static byte[] StructToBytes(object structure)
  272.         {
  273.             int num = Marshal.SizeOf(structure);
  274.             IntPtr intPtr = Marshal.AllocHGlobal(num);
  275.             byte[] result;
  276.             try
  277.             {
  278.                 Marshal.StructureToPtr(structure, intPtr, false);
  279.                 byte[] array = new byte[num];
  280.                 Marshal.Copy(intPtr, array, 0, num);
  281.                 result = array;
  282.             }
  283.             finally
  284.             {
  285.                 Marshal.FreeHGlobal(intPtr);
  286.             }
  287.             return result;
  288.         }
  289.         /// <summary>
  290.         /// 结构体初始化赋值
  291.         /// </summary>
  292.         /// <param name="data_len"></param>
  293.         /// <returns></returns>
  294.         private static WAVE_Header GetWave_Header(int data_len)
  295.         {
  296.             return new WAVE_Header
  297.             {
  298.                 RIFF_ID = 1179011410,
  299.                 File_Size = data_len + 36,
  300.                 RIFF_Type = 1163280727,
  301.                 FMT_ID = 544501094,
  302.                 FMT_Size = 16,
  303.                 FMT_Tag = 1,
  304.                 FMT_Channel = 1,
  305.                 FMT_SamplesPerSec = 16000,
  306.                 AvgBytesPerSec = 32000,
  307.                 BlockAlign = 2,
  308.                 BitsPerSample = 16,
  309.                 DATA_ID = 1635017060,
  310.                 DATA_Size = data_len
  311.             };
  312.         }
  313.         /// <summary>
  314.         /// 语音音频头
  315.         /// </summary>
  316.         private struct WAVE_Header
  317.         {
  318.             public int RIFF_ID;
  319.             public int File_Size;
  320.             public int RIFF_Type;
  321.             public int FMT_ID;
  322.             public int FMT_Size;
  323.             public short FMT_Tag;
  324.             public ushort FMT_Channel;
  325.             public int FMT_SamplesPerSec;
  326.             public int AvgBytesPerSec;
  327.             public ushort BlockAlign;
  328.             public ushort BitsPerSample;
  329.             public int DATA_ID;
  330.             public int DATA_Size;
  331.         }
  332.         /// 指针转字符串
  333.         /// </summary>
  334.         /// <param name="p">指向非托管代码字符串的指针</param>
  335.         /// <returns>返回指针指向的字符串</returns>
  336.         public static string Ptr2Str(IntPtr p)
  337.         {
  338.             List<byte> lb = new List<byte>();
  339.             while (Marshal.ReadByte(p) != 0)
  340.             {
  341.                 lb.Add(Marshal.ReadByte(p));
  342.                 p = p + 1;
  343.             }
  344.             return Encoding.Default.GetString(lb.ToArray());
  345.         }
  346.     }
  347. }
复制代码
上面分别是Windows的普通版与Linux高品质版的调用代码,比较凌乱,用的时候可以再封装一下,还要记得把之前记下来的APPID填到代码里。
四、调用
  1. [ApiController]
  2. [Route("[controller]")]
  3. public class TextToSpeechController : ControllerBase
  4. {
  5.     [HttpGet]
  6.     public FileStreamResult GetWav(string text,string speaker)
  7.     {
  8.         var fileName = Guid.NewGuid().ToString() + ".wav";
  9.         var mimeType = "application/....";
  10.         if(string.IsNullOrEmpty(speaker))
  11.             speaker = "xiaofeng";
  12.         if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
  13.             LinuxXFTTSUtils.GetAudio(text, fileName, speaker, 50);
  14.         else if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  15.             WindowsXFTTSUtils.GetAudio(text, fileName, speaker, 50);
  16.         Stream stream = System.IO.File.OpenRead(fileName);
  17.         System.IO.File.Delete(fileName);
  18.         return new FileStreamResult(stream, mimeType)
  19.         {
  20.             FileDownloadName = fileName
  21.         };
  22.     }
  23. }
复制代码
注意需要把下载的SDK包里面的bin目录内的文件拷贝到运行目录,如果是linux版,需要从libs里面拷贝libmsc.so库,speaker可以填xiaofeng或者xiaoyan,分别是男女声,需要更多的发音人可以去购买。
代码基本完整提供了,各位直接复制粘贴使用即可,离线SDK可以免费体验30天,过期了需要购买或者重新注册创建新应用来延续使用。不过既然都是离线版了,直接把电脑时间固定住应该也能继续白嫖。哈哈,个人学习使用的话可以,商用版还是要购买噢。

来源:https://www.cnblogs.com/DriftingLeaf/archive/2023/08/22/17648569.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具