unity接在线科大讯飞语音合成(Windows)
1、首先下载讯飞在线语音合成SDK,解压,可以先看下SDK中的C语言写的例子
2、将SDK中的bin 、include、libs拷贝到unity工程中,如图所示:
3、接着开始写代码(一共三个脚本)
UIManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;public class UIManager : MonoBehaviour {public InputField field;public void InputTextForAudio() {string str = field.text;//得到需要转换语音的文本field.text = null;//将需要转换语音的文本清空//调用写好的语音合成函数if (str != null||!("".Equals(str))) {Test.ButtonCreateAudio(str);}}
}
Test:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using TTS;//TTS是自己封装的dll,里面封装了错误编号,以及需要的结构体,在debug路径下
using System.IO;
using System.Runtime.InteropServices;using System.Threading;public class Test {public static void ButtonCreateAudio(string str) {int ret = 0;IntPtr session_ID;//APPID请勿随意改动string login_configs = "appid = 5ac9f8d1";//登录参数,自己注册后获取的appidstring text = str;//text是待合成文本string filename = "Call.wav"; //合成的语音文件名uint audio_len = 0;SynthStatus synth_status = SynthStatus.MSP_TTS_FLAG_STILL_HAVE_DATA;ret = mscdll.MSPLogin(null,null, login_configs);//第一个参数为用户名,第二个参数为密码,第三个参数是登录参数,用户名和密码需要在http://open.voicecloud.cn//MSPLogin方法返回失败if (ret != (int)ErrorCode.MSP_SUCCESS){Debug.Log("登录失败" + ret);return;}string _params = "engine_type =cloud ,voice_name=xiaoyan, text_encoding = UTF8,sample_rate = 16000"; session_ID = mscdll.QTTSSessionBegin(_params, ref ret);//QTTSSessionBegin方法返回失败if (ret != (int)ErrorCode.MSP_SUCCESS){Debug.Log("会话开始失败!" + ret);ret = mscdll.MSPLogout();//退出登录return;}ret = mscdll.QTTSTextPut(Marshal.PtrToStringAnsi(session_ID), text, (uint)Encoding.Default.GetByteCount(text), string.Empty);//QTTSTextPut方法返回失败if (ret != (int)ErrorCode.MSP_SUCCESS){Debug.Log("放入文本失败" + ret);ret = mscdll.QTTSSessionEnd(Marshal.PtrToStringAnsi(session_ID), "");//结束会话ret = mscdll.MSPLogout();//退出登录return;}//内存流可直接在内存进行读写,不需要临时缓冲区或者临时文件MemoryStream memoryStream = new MemoryStream();memoryStream.Write(new byte[44], 0, 44);//为结构体开辟空间,后面用来存储音频文件结构体while (true){IntPtr source = mscdll.QTTSAudioGet(Marshal.PtrToStringAnsi(session_ID), ref audio_len, ref synth_status, ref ret);byte[] array = new byte[(int)audio_len];if (audio_len > 0){Marshal.Copy(source, array, 0, (int)audio_len);}memoryStream.Write(array, 0, (int)audio_len);//将合成的音频字节数据存放到内存流中Thread.Sleep(150);//防止CPU频繁占用if (synth_status == SynthStatus.MSP_TTS_FLAG_DATA_END || ret != 0)break;}WAVE_Header wave_Header = getWave_Header((int)memoryStream.Length);byte[] array2 = StructToBytes(wave_Header);memoryStream.Position = 0L;//将指针定位到开头memoryStream.Write(array2, 0, array2.Length);//存储结构体的字节数组memoryStream.Position = 0L;//将指针定位到开头 if (filename != null){//通过文件名创建音频文件流FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write);memoryStream.WriteTo(fileStream);//将内存流中的数据写入到文件流,文件流写入到音频文件中ImemoryStream.Close();//关闭流fileStream.Close();}ret = mscdll.QTTSSessionEnd(Marshal.PtrToStringAnsi(session_ID), "");//结束会话ret = mscdll.MSPLogout();//退出登录Debug.Log("会话结束");Debug.Log("退出登录");}/// <summary>/// 结构体转字符串/// </summary>/// <param name="structure"></param>/// <returns></returns>private static byte[] StructToBytes(object structure){int num = Marshal.SizeOf(structure);IntPtr intPtr = Marshal.AllocHGlobal(num);byte[] result;try{Marshal.StructureToPtr(structure, intPtr, false);byte[] array = new byte[num];Marshal.Copy(intPtr, array, 0, num);result = array;}finally{Marshal.FreeHGlobal(intPtr);}return result;}/// <summary>/// 结构体初始化赋值/// </summary>/// <param name="data_len"></param>/// <returns></returns>private static WAVE_Header getWave_Header(int data_len){return new WAVE_Header{RIFF_ID = 1179011410,//相当于SDK例子中的"RIFF",只是转换成了对应的ASCL值File_Size = data_len -8,RIFF_Type = 1163280727,FMT_ID = 544501094,FMT_Size = 16,FMT_Tag = 1,FMT_Channel = 1,FMT_SamplesPerSec = 16000,AvgBytesPerSec = 32000,BlockAlign = 2,BitsPerSample = 16,DATA_ID = 1635017060,DATA_Size = data_len-44};}/// <summary>/// 语音音频头/// </summary>private struct WAVE_Header{public int RIFF_ID;public int File_Size;public int RIFF_Type;public int FMT_ID;public int FMT_Size;public short FMT_Tag;public ushort FMT_Channel;public int FMT_SamplesPerSec;public int AvgBytesPerSec;public ushort BlockAlign;public ushort BitsPerSample;public int DATA_ID;public int DATA_Size;}
}
MSC:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;namespace TTS
{public enum ErrorCode{MSP_SUCCESS = 0,MSP_ERROR_FAIL = -1,MSP_ERROR_EXCEPTION = -2,/* General errors 10100(0x2774) */MSP_ERROR_GENERAL = 10100, /* 0x2774 */MSP_ERROR_OUT_OF_MEMORY = 10101, /* 0x2775 */MSP_ERROR_FILE_NOT_FOUND = 10102, /* 0x2776 */MSP_ERROR_NOT_SUPPORT = 10103, /* 0x2777 */MSP_ERROR_NOT_IMPLEMENT = 10104, /* 0x2778 */MSP_ERROR_ACCESS = 10105, /* 0x2779 */MSP_ERROR_INVALID_PARA = 10106, /* 0x277A */MSP_ERROR_INVALID_PARA_VALUE = 10107, /* 0x277B */MSP_ERROR_INVALID_HANDLE = 10108, /* 0x277C */MSP_ERROR_INVALID_DATA = 10109, /* 0x277D */MSP_ERROR_NO_LICENSE = 10110, /* 0x277E */MSP_ERROR_NOT_INIT = 10111, /* 0x277F */MSP_ERROR_NULL_HANDLE = 10112, /* 0x2780 */MSP_ERROR_OVERFLOW = 10113, /* 0x2781 */MSP_ERROR_TIME_OUT = 10114, /* 0x2782 */MSP_ERROR_OPEN_FILE = 10115, /* 0x2783 */MSP_ERROR_NOT_FOUND = 10116, /* 0x2784 */MSP_ERROR_NO_ENOUGH_BUFFER = 10117, /* 0x2785 */MSP_ERROR_NO_DATA = 10118, /* 0x2786 */MSP_ERROR_NO_MORE_DATA = 10119, /* 0x2787 */MSP_ERROR_SKIPPED = 10120, /* 0x2788 */MSP_ERROR_ALREADY_EXIST = 10121, /* 0x2789 */MSP_ERROR_LOAD_MODULE = 10122, /* 0x278A */MSP_ERROR_BUSY = 10123, /* 0x278B */MSP_ERROR_INVALID_CONFIG = 10124, /* 0x278C */MSP_ERROR_VERSION_CHECK = 10125, /* 0x278D */MSP_ERROR_CANCELED = 10126, /* 0x278E */MSP_ERROR_INVALID_MEDIA_TYPE = 10127, /* 0x278F */MSP_ERROR_CONFIG_INITIALIZE = 10128, /* 0x2790 */MSP_ERROR_CREATE_HANDLE = 10129, /* 0x2791 */MSP_ERROR_CODING_LIB_NOT_LOAD = 10130, /* 0x2792 *//* Error codes of network 10200(0x27D8)*/MSP_ERROR_NET_GENERAL = 10200, /* 0x27D8 */MSP_ERROR_NET_OPENSOCK = 10201, /* 0x27D9 */ /* Open socket */MSP_ERROR_NET_CONNECTSOCK = 10202, /* 0x27DA */ /* Connect socket */MSP_ERROR_NET_ACCEPTSOCK = 10203, /* 0x27DB */ /* Accept socket */MSP_ERROR_NET_SENDSOCK = 10204, /* 0x27DC */ /* Send socket data */MSP_ERROR_NET_RECVSOCK = 10205, /* 0x27DD */ /* Recv socket data */MSP_ERROR_NET_INVALIDSOCK = 10206, /* 0x27DE */ /* Invalid socket handle */MSP_ERROR_NET_BADADDRESS = 10207, /* 0x27EF */ /* Bad network address */MSP_ERROR_NET_BINDSEQUENCE = 10208, /* 0x27E0 */ /* Bind after listen/connect */MSP_ERROR_NET_NOTOPENSOCK = 10209, /* 0x27E1 */ /* Socket is not opened */MSP_ERROR_NET_NOTBIND = 10210, /* 0x27E2 */ /* Socket is not bind to an address */MSP_ERROR_NET_NOTLISTEN = 10211, /* 0x27E3 */ /* Socket is not listenning */MSP_ERROR_NET_CONNECTCLOSE = 10212, /* 0x27E4 */ /* The other side of connection is closed */MSP_ERROR_NET_NOTDGRAMSOCK = 10213, /* 0x27E5 */ /* The socket is not datagram type *//* Error codes of mssp message 10300(0x283C) */MSP_ERROR_MSG_GENERAL = 10300, /* 0x283C */MSP_ERROR_MSG_PARSE_ERROR = 10301, /* 0x283D */MSP_ERROR_MSG_BUILD_ERROR = 10302, /* 0x283E */MSP_ERROR_MSG_PARAM_ERROR = 10303, /* 0x283F */MSP_ERROR_MSG_CONTENT_EMPTY = 10304, /* 0x2840 */MSP_ERROR_MSG_INVALID_CONTENT_TYPE = 10305, /* 0x2841 */MSP_ERROR_MSG_INVALID_CONTENT_LENGTH = 10306, /* 0x2842 */MSP_ERROR_MSG_INVALID_CONTENT_ENCODE = 10307, /* 0x2843 */MSP_ERROR_MSG_INVALID_KEY = 10308, /* 0x2844 */MSP_ERROR_MSG_KEY_EMPTY = 10309, /* 0x2845 */MSP_ERROR_MSG_SESSION_ID_EMPTY = 10310, /* 0x2846 */MSP_ERROR_MSG_LOGIN_ID_EMPTY = 10311, /* 0x2847 */MSP_ERROR_MSG_SYNC_ID_EMPTY = 10312, /* 0x2848 */MSP_ERROR_MSG_APP_ID_EMPTY = 10313, /* 0x2849 */MSP_ERROR_MSG_EXTERN_ID_EMPTY = 10314, /* 0x284A */MSP_ERROR_MSG_INVALID_CMD = 10315, /* 0x284B */MSP_ERROR_MSG_INVALID_SUBJECT = 10316, /* 0x284C */MSP_ERROR_MSG_INVALID_VERSION = 10317, /* 0x284D */MSP_ERROR_MSG_NO_CMD = 10318, /* 0x284E */MSP_ERROR_MSG_NO_SUBJECT = 10319, /* 0x284F */MSP_ERROR_MSG_NO_VERSION = 10320, /* 0x2850 */MSP_ERROR_MSG_MSSP_EMPTY = 10321, /* 0x2851 */MSP_ERROR_MSG_NEW_RESPONSE = 10322, /* 0x2852 */MSP_ERROR_MSG_NEW_CONTENT = 10323, /* 0x2853 */MSP_ERROR_MSG_INVALID_SESSION_ID = 10324, /* 0x2854 *//* Error codes of DataBase 10400(0x28A0)*/MSP_ERROR_DB_GENERAL = 10400, /* 0x28A0 */MSP_ERROR_DB_EXCEPTION = 10401, /* 0x28A1 */MSP_ERROR_DB_NO_RESULT = 10402, /* 0x28A2 */MSP_ERROR_DB_INVALID_USER = 10403, /* 0x28A3 */MSP_ERROR_DB_INVALID_PWD = 10404, /* 0x28A4 */MSP_ERROR_DB_CONNECT = 10405, /* 0x28A5 */MSP_ERROR_DB_INVALID_SQL = 10406, /* 0x28A6 */MSP_ERROR_DB_INVALID_APPID = 10407, /* 0x28A7 *//* Error codes of Resource 10500(0x2904)*/MSP_ERROR_RES_GENERAL = 10500, /* 0x2904 */MSP_ERROR_RES_LOAD = 10501, /* 0x2905 */ /* Load resource */MSP_ERROR_RES_FREE = 10502, /* 0x2906 */ /* Free resource */MSP_ERROR_RES_MISSING = 10503, /* 0x2907 */ /* Resource File Missing */MSP_ERROR_RES_INVALID_NAME = 10504, /* 0x2908 */ /* Invalid resource file name */MSP_ERROR_RES_INVALID_ID = 10505, /* 0x2909 */ /* Invalid resource ID */MSP_ERROR_RES_INVALID_IMG = 10506, /* 0x290A */ /* Invalid resource image pointer */MSP_ERROR_RES_WRITE = 10507, /* 0x290B */ /* Write read-only resource */MSP_ERROR_RES_LEAK = 10508, /* 0x290C */ /* Resource leak out */MSP_ERROR_RES_HEAD = 10509, /* 0x290D */ /* Resource head currupt */MSP_ERROR_RES_DATA = 10510, /* 0x290E */ /* Resource data currupt */MSP_ERROR_RES_SKIP = 10511, /* 0x290F */ /* Resource file skipped *//* Error codes of TTS 10600(0x2968)*/MSP_ERROR_TTS_GENERAL = 10600, /* 0x2968 */MSP_ERROR_TTS_TEXTEND = 10601, /* 0x2969 */ /* Meet text end */MSP_ERROR_TTS_TEXT_EMPTY = 10602, /* 0x296A */ /* no synth text *//* Error codes of Recognizer 10700(0x29CC) */MSP_ERROR_REC_GENERAL = 10700, /* 0x29CC */MSP_ERROR_REC_INACTIVE = 10701, /* 0x29CD */MSP_ERROR_REC_GRAMMAR_ERROR = 10702, /* 0x29CE */MSP_ERROR_REC_NO_ACTIVE_GRAMMARS = 10703, /* 0x29CF */MSP_ERROR_REC_DUPLICATE_GRAMMAR = 10704, /* 0x29D0 */MSP_ERROR_REC_INVALID_MEDIA_TYPE = 10705, /* 0x29D1 */MSP_ERROR_REC_INVALID_LANGUAGE = 10706, /* 0x29D2 */MSP_ERROR_REC_URI_NOT_FOUND = 10707, /* 0x29D3 */MSP_ERROR_REC_URI_TIMEOUT = 10708, /* 0x29D4 */MSP_ERROR_REC_URI_FETCH_ERROR = 10709, /* 0x29D5 *//* Error codes of Speech Detector 10800(0x2A30) */MSP_ERROR_EP_GENERAL = 10800, /* 0x2A30 */MSP_ERROR_EP_NO_SESSION_NAME = 10801, /* 0x2A31 */MSP_ERROR_EP_INACTIVE = 10802, /* 0x2A32 */MSP_ERROR_EP_INITIALIZED = 10803, /* 0x2A33 *//* Error codes of TUV */MSP_ERROR_TUV_GENERAL = 10900, /* 0x2A94 */MSP_ERROR_TUV_GETHIDPARAM = 10901, /* 0x2A95 */ /* Get Busin Param huanid*/MSP_ERROR_TUV_TOKEN = 10902, /* 0x2A96 */ /* Get Token */MSP_ERROR_TUV_CFGFILE = 10903, /* 0x2A97 */ /* Open cfg file */MSP_ERROR_TUV_RECV_CONTENT = 10904, /* 0x2A98 */ /* received content is error */MSP_ERROR_TUV_VERFAIL = 10905, /* 0x2A99 */ /* Verify failure *//* Error codes of IMTV */MSP_ERROR_IMTV_SUCCESS = 11000, /* 0x2AF8 */ /* 成功 */MSP_ERROR_IMTV_NO_LICENSE = 11001, /* 0x2AF9 */ /* 试用次数结束,用户需要付费 */MSP_ERROR_IMTV_SESSIONID_INVALID = 11002, /* 0x2AFA */ /* SessionId失效,需要重新登录通行证 */MSP_ERROR_IMTV_SESSIONID_ERROR = 11003, /* 0x2AFB */ /* SessionId为空,或者非法 */MSP_ERROR_IMTV_UNLOGIN = 11004, /* 0x2AFC */ /* 未登录通行证 */MSP_ERROR_IMTV_SYSTEM_ERROR = 11005, /* 0x2AFD */ /* 系统错误 *//* Error codes of HCR */MSP_ERROR_HCR_GENERAL = 11100,MSP_ERROR_HCR_RESOURCE_NOT_EXIST = 11101,/* Error codes of http 12000(0x2EE0) */MSP_ERROR_HTTP_BASE = 12000, /* 0x2EE0 *//*Error codes of ISV */MSP_ERROR_ISV_NO_USER = 13000, /* 32C8 */ /* the user doesn't exist */}#region TTS枚举常量/// <summary>/// vol参数的枚举常量/// </summary>public enum enuVol{x_soft,soft,medium,loud,x_loud}/// <summary>/// speed语速参数的枚举常量/// </summary>public enum enuSpeed{x_slow,slow,medium,fast,x_fast}/// <summary>/// speeker朗读者枚举常量/// </summary>public enum enuSpeeker{小燕_青年女声_中英文_普通话 = 0,小宇_青年男声_中英文_普通话,凯瑟琳_青年女声_英语,亨利_青年男声_英语,玛丽_青年女声_英语,小研_青年女声_中英文_普通话,小琪_青年女声_中英文_普通话,小峰_青年男声_中英文_普通话,小梅_青年女声_中英文_粤语,小莉_青年女声_中英文_台普,小蓉_青年女声_汉语_四川话,小芸_青年女声_汉语_东北话,小坤_青年男声_汉语_河南话,小强_青年男声_汉语_湖南话,小莹_青年女声_汉语_陕西话,小新_童年男声_汉语_普通话,楠楠_童年女声_汉语_普通话,老孙_老年男声_汉语_普通话}public enum SynthStatus{MSP_TTS_FLAG_STILL_HAVE_DATA = 1,MSP_TTS_FLAG_DATA_END = 2,MSP_TTS_FLAG_CMD_CANCELED = 0}#endregionpublic class mscdll{#region TTS dll import[DllImport("msc_x64", CallingConvention = CallingConvention.StdCall)]public static extern int MSPLogin(string usr, string pwd, string parameters);[DllImport("msc_x64", CallingConvention = CallingConvention.Winapi)]public static extern int MSPLogout();[DllImport("msc_x64", CallingConvention = CallingConvention.Winapi)]public static extern IntPtr QTTSSessionBegin(string _params, ref int errorCode);[DllImport("msc_x64", CallingConvention = CallingConvention.Winapi)]public static extern int QTTSTextPut(string sessionID, string textString, uint textLen, string _params);[DllImport("msc_x64", CallingConvention = CallingConvention.Winapi)]public static extern IntPtr QTTSAudioGet(string sessionID, ref uint audioLen, ref SynthStatus synthStatus, ref int errorCode);[DllImport("msc_x64", CallingConvention = CallingConvention.Winapi)]public static extern IntPtr QTTSAudioInfo(string sessionID);[DllImport("msc_x64", CallingConvention = CallingConvention.Winapi)]public static extern int QTTSSessionEnd(string sessionID, string hints);#endregion}
}
4、unity端输入截屏:
5、合成的音频文件在项目的根目录下:
最后总结一下自己遇到的错误:
1、登录失败:
原因1:MCS与APPID不匹配
原因2:语音识别过程中出错,没有正常退出登录,此时需要重启unity(大多数是这个原因)
2、中文乱码问题:刚开始没选择编码方式,结果中文识别乱码,然后选择utf8编码方式,正确合成语音
3、最大的问题,至今没解决,unity端合成中文缺少最后面一部分,英文和数字正常,在单独的C#端也正常
解决办法:如果要合成中文,有多少中文汉字就在句子后面加多少个空格(这种解决办法很不理想,但至今没找到合理的办法)
欢迎提问,顺便考虑下解决问题3
demo地址:https://download.csdn.net/download/hyy_sui_yuan/10654175
unity接在线科大讯飞语音合成(Windows)相关推荐
- UNITY实战进阶-科大讯飞TTS(离线语音合成) unity播放PCM格式的wav(不依赖第三方库)-7
准备工作 1.注册科大讯飞开发者账户 2.创建一个应用,获取APPID 3.下载离线sdk(你是什么平台的就下什么平台的) 4.开打压缩包 5.我们需要的文件 bin\msc.dll ...
- 调用科大讯飞语音合成离线SDK的基础上调用pyqt5模块编写gui界面
程序说明 该程序是继我上一次调用科大讯飞语音合成离线SDK,用Python写了一个文本转语音的程序的进一步开发,这次开发是用pyqt5模块和其自带的designer做了一个gui界面. 程序展示 该程 ...
- Unity创建在线多人游戏视频教程
Unity创建在线多人游戏视频教程 Learn To Create An Online Multiplayer Game In Unity 学会在Unity中创建在线多人游戏 MP4 |视频:h264 ...
- 计算机应用基础中什么是桌面,福师《计算机应用基础》在线作业二 Windows中进行系统设置的工具集是 用户可以根据自己的爱好更改显示器 键盘 鼠标器 桌面等硬件的设置...
福师<计算机应用基础>在线作业二 Windows中进行系统设置的工具集是 用户可以根据自己的爱好更改显示器 键盘 鼠标器 桌面等硬件的设置 (12页) 本资源提供全文预览,点击全文预览即可 ...
- 19秋计算机应用基础在线作业2,计算机应用基础19秋在线作业2 Windows 下能浏览并管理文件 驱动器及网络连接的强大工具是...
1.Evaluation Warning: The document was created with Spire.Doc for .NET.计算机应用基础19秋在线作业21 单选题1 Windows ...
- Vue+SpringBoot+Audio+科大讯飞 语音合成技术
最终思路 思路就是vue前端向后台发送需要播放的语音信息(文字),然后后台返回语音流数据,通过URL.createObjectURL(data) 这个API生成一个URL,然后给audio标签附上ur ...
- 接口调用-【4】讯飞离线语音合成Windows/Linux
1.离线语音合成调用主函数(离线语音合成调用属于简单的,无回调函数) package com.iflytek; import com.iflytek.util.Step2_tts_thread; im ...
- Unity实现在线宝箱功能
Unity实现在线宝箱功能 首先让明确一点OnlineBox其实是一个Button组件. 先实现一个功能是点击宝箱,更换打开成宝箱的图片,并播放对应的音效: /// <summary>// ...
- 利用科大讯飞语音合成模块SDK实现ROS语音交互
利用科大讯飞语音合成模块SDK实现ROS语音交互 本文内容与CSDN博主「AI Chen」的原创文章相同,可以直接参考原文:https://blog.csdn.net/qq_39400324/arti ...
最新文章
- 跳跃游戏(判断是否可以跳到最后一个下标)
- java web三:反射
- Windows下配置NodeJS环境详解
- 双拼输入法键位图_教你在Windows自带的微软拼音输入法中用上小鹤双拼方案
- 京东:Flink SQL 优化实战
- java篇 之 变量存放位置
- 立志10天学会C++基础应用—day01
- Docker(四) Dockerfile 详解
- java 看虚拟机内存_java 虚拟机内存介绍
- Day 41 Rsync备份
- Git环境配置(案例:clone bert源码到本地仓库)
- 洛谷P3265 装备购买
- 啊哈算法—解救小哈(深度优先搜索)
- 开心消消乐、纯前端实现开心消消乐、开心消消乐代码、HTML+JS实现开心消消乐
- CRC校验算法——C语言实现
- C# winform实现系统托盘NotifyIcon控件右键菜单
- 汇编(五):第一个汇编程序
- C语言运算优先级口诀
- 手机号码格式和邮箱格式校正
- 以太坊区块链浏览器搭建