Unity5.3 API 之 Microphone(游戏语音SDK )

发表于2017-08-10
评论0 2.2k浏览
好久不见,最近手机游戏内置语音越来越普遍,这样的需求也难免多了起来。对就是像微信/阴阳师那样。

下面介绍两种实现方法:
1.unity内置API - Microphone
2.第三方包SDK
3.- API - sealed class Microphine

优点:unity爸爸自己内置的,以后功能应该会更强大,避免接SDK,和第三方包的不稳定因素。
缺点:提供的方法太少,编码和解码需要自己搞定,优化不够到位,没有语音识别功能。

我推荐第二种方法,具体还是看需求!

第一种:unityAPI

API - sealed class Microphone
namespace UnityEngine
{
    //
    // 摘要:
    //     ///
    //     Use this class to record to an AudioClip using a connected microphone.
    //     ///
    public sealed class Microphone
    {
        public Microphone();
        //
        // 摘要:
        //     ///
        //     A list of available microphone devices, identified by name.
        //     ///
        public static string[] devices { get; }
        //
        // 摘要:
        //     ///
        //     Stops recording.
        //     ///
        //
        // 参数:
        //   deviceName:
        //     The name of the device.
        [WrapperlessIcall]
        public static void End(string deviceName);
        [WrapperlessIcall]
        public static void GetDeviceCaps(string deviceName, out int minFreq, out int maxFreq);
        //
        // 摘要:
        //     ///
        //     Get the position in samples of the recording.
        //     ///
        //
        // 参数:
        //   deviceName:
        //     The name of the device.
        [WrapperlessIcall]
        public static int GetPosition(string deviceName);
        //
        // 摘要:
        //     ///
        //     Query if a device is currently recording.
        //     ///
        //
        // 参数:
        //   deviceName:
        //     The name of the device.
        [WrapperlessIcall]
        public static bool IsRecording(string deviceName);
        //
        // 摘要:
        //     ///
        //     Start Recording with device.
        //     ///
        //
        // 参数:
        //   deviceName:
        //     The name of the device.
        //
        //   loop:
        //     Indicates whether the recording should continue recording if lengthSec is reached,
        //     and wrap around and record from the beginning of the AudioClip.
        //
        //   lengthSec:
        //     Is the length of the AudioClip produced by the recording.
        //
        //   frequency:
        //     The sample rate of the AudioClip produced by the recording.
        //
        // 返回结果:
        //     ///
        //     The function returns null if the recording fails to start.
        //     ///
        [WrapperlessIcall]
        public static AudioClip Start(string deviceName, bool loop, int lengthSec, int frequency);
    }
}

开关录音
/// <summary>
    /// 开关录音
    /// </summary>
    /// <param name="isFlag"></param>
    public void StartMicro(bool isFlag)
    {
        if (Microphone.devices.Length < 0)
            return;
        if (isFlag)
        {
            Microphone.End(null);
            m_CurrentClip = Microphone.Start(null, false, m_SamplingMaxTime, m_SamplingRate);
            if (m_CurrentClip)
                return;
        }
        else
        {
            int length;
            int lastPos = Microphone.GetPosition(null);
            Debug.Log(lastPos   "..........."   Microphone.IsRecording(null));
            if (Microphone.IsRecording(null))
            {
                length = lastPos / m_SamplingRate;
                Debug.Log(length);
            }
            else
            {
                length = m_SamplingMaxTime;
            }
            Microphone.End(null);
            //if (length < m_SamplingMinTime)
            //{
            //    Debug.Log("长度小于两秒");
            //    return;
            //}
            byte[] wav = m_CurrentClip.EncodeToWAV(m_SamplingRate * length);
            int lengthSamples;
            int frequency;      
            float[] pcm = AudioClipCompress.WavToPCM(wav, out lengthSamples, out frequency);
            labelText = "pcm"   pcm.Length;
            AudioClip mClip = AudioClip.Create("", lengthSamples, 1, frequency, false);
            mClip.SetData(pcm, 0);
            AudioSource source = gameObject.GetComponent<AudioSource>();
            if (source == null)
                source = gameObject.AddComponent<AudioSource>();
            source.clip = mClip;
            source.Play();
        }
    }

其实Microphone.Start的返回值就是AuidoClip,拿过来就可以播了。
但是语音聊天涉及到网络通信,所以需要进行一下数据转换。
EncodeToWAV - audioclip 转 byte
WavToPCM - byte 转 float
最后mClip.SetData(pcm, 0);
OK!

第二种:sdk(呀呀云SDK 和 亲加SDK)

1.呀呀云Dome 和 说明书文档 在附件里!
特别注意的是 播放语音的时候有两种方式 本地 和 下载。
根据项目需求选择吧。
using UnityEngine;
using System.Collections;
using System;
using YunvaIM;
public class Demo : MonoBehaviour
{
    private string sUserId="123";
    private string labelText = "ssss";
    string filePath = "";
        private string recordPath=string.Empty;//返回录音地址
        private string recordUrlPath=string.Empty;//返回录音url地址
        public GUISkin guiSkin;
        void Start ()
    {
        EventListenerManager.AddListener(ProtocolEnum.IM_RECORD_VOLUME_NOTIFY, ImRecordVolume);//录音音量大小回调监听
        #region 初始化注册
        int init = YunVaImSDK.instance.YunVa_Init(0, 300000, Application.persistentDataPath, true);
        #endregion
        if (init == 0) 
                {
                        Debug.Log("初始化成功...");
                        labelText="初始化成功...";
                } 
                else 
                {
                        Debug.Log("初始化失败...");
                        labelText="初始化失败...";
                }
        }
    void OnGUI()
    {
                if (guiSkin != null) 
                {
                        GUI.skin=guiSkin;
                }
        GUI.Box(new Rect(10f, 10f, 340, 900f), "菜单");
        sUserId = GUI.TextField(new Rect(20f, 50f, 150f, 100f), sUserId);
        if(GUI.Button(new Rect(20f,150f,150f,100f),"登录"))
        {
            #region 登录
            string ttFormat = "{{\"nickname\":\"{0}\",\"uid\":\"{1}\"}}";
            string tt = string.Format(ttFormat, sUserId, sUserId);
                        string[] wildcard = new string[2];
                        wildcard[0] = "0x001";
                        wildcard[1] = "0x002";
                        YunVaImSDK.instance.YunVaOnLogin(tt, "1111", wildcard, 0, (data) => 
            {
                if (data.result == 0)
                {
                    labelText = string.Format("登录成功,昵称:{0},用户ID:{1}", data.nickName, data.userId);
                    YunVaImSDK.instance.RecordSetInfoReq(true);//开启录音的音量大小回调
                }
                else
                {
                    labelText = string.Format("登录失败,错误消息:{0}", data.msg);
                }
            });
            #endregion
        }
        if (GUI.Button(new Rect(20f, 250f, 150f, 100f), "开始录音"))
        {
            labelText = "正在录音中。。。。。。";
            #region 开始录音
            filePath = string.Format("{0}/{1}.amr", Application.persistentDataPath, DateTime.Now.ToFileTime());
            Debug.Log("FilePath:"   filePath);
            YunVaImSDK.instance.RecordStartRequest(filePath);
            #endregion
        }
        if (GUI.Button(new Rect(20f,350f, 150f, 100f),"停止录音"))
        {
            labelText = "停止录音.........";
            #region 停止录音
            YunVaImSDK.instance.RecordStopRequest(StopRecordResponse);
            #endregion
        }
        if (GUI.Button(new Rect(20f, 450f, 150f, 100f), "播放语音"))
        {
            labelText = "播放语音.........";
            #region 播放语音
            string ext = DateTime.Now.ToFileTime().ToString();
            YunVaImSDK.instance.RecordStartPlayRequest(filePath, "", ext, (data2) =>
           //YunVaImSDK.instance.RecordStartPlayRequest("", recordUrlPath, ext, (data2) =>
            {
                if (data2.result == 0)
                {
                    Debug.Log("播放成功");
                    labelText = "播放成功";
                }
                else
                {
                    Debug.Log("播放失败");
                    labelText = "播放失败";
                }
            });
            #endregion
        }
        if (GUI.Button(new Rect(190f,50f, 150f, 100f),"停止播放"))
                {
                        labelText = "停止播放.........";
                        Debug.Log("停止播放");
            #region 停止播放
            YunVaImSDK.instance.RecordStopPlayRequest();
            #endregion
        }
        if (GUI.Button(new Rect(190f,150f, 150f, 100f),"语音识别"))
                {
                        labelText = "语音识别.........";
                        Debug.Log("语音识别");
            string ext = DateTime.Now.ToFileTime().ToString();
            YunVaImSDK.instance.SpeechStartRequest(recordPath, ext, (data3) =>
                                                                { 
                                if(data3.result==0)
                                {
                    labelText = "识别成功,识别内容:"   data3.text;
                                }
                                else
                                {
                                        labelText = "识别失败,原因:"   data3.msg;
                                }
                        });
                }
                if(GUI.Button(new Rect(190f,250f, 150f, 100f),"上传语音"))
                {
                        Debug.Log("准备上传:"   recordPath);
                        labelText = "准备上传:"  recordPath;
              string fileId = DateTime.Now.ToFileTime().ToString();
              YunVaImSDK.instance.UploadFileRequest(recordPath, fileId, (data1) =>
                          {
                                if(data1.result==0)
                                {
                                        recordUrlPath=data1.fileurl;
                                        Debug.Log("上传成功:" recordUrlPath);
                                        labelText = "上传成功:" recordUrlPath;
                                }
                                else
                                {
                                        labelText ="上传失败:" data1.msg;
                                        Debug.Log("上传失败:" data1.msg);
                                }
                        });
                }
                if(GUI.Button(new Rect(190f,350f, 150f, 100f),"下载语音"))
                {
                        labelText = "下载语音......";
                        string DownLoadfilePath = string.Format("{0}/{1}.amr", Application.persistentDataPath, DateTime.Now.ToFileTime());
                        Debug.Log("下载语音:" DownLoadfilePath);
            string fileid = DateTime.Now.ToFileTime().ToString();
            YunVaImSDK.instance.DownLoadFileRequest(recordUrlPath, DownLoadfilePath, fileid, (data4) =>
                                                               {
                                if(data4.result==0)
                                {
                                        Debug.Log("下载成功:" data4.filename);
                                        labelText = "下载成功:" data4.filename;
                                }
                                else
                                {
                                        Debug.Log("下载失败:" data4.msg);
                                        labelText = "下载失败:" data4.msg;
                                }
                        });
                }
        if (GUI.Button(new Rect(190f, 450f, 150f, 100f), "登出"))
        {
            #region 登出
            YunVaImSDK.instance.YunVaLogOut();
            #endregion
        }
        GUI.Label(new Rect(400f, 10f, 500f, 30f), "返回提示");
        GUI.Label(new Rect(400f, 30f, 500f, 50f), labelText); 
    }
/// <summary>
/// 停止录音
/// </summary>
/// <param name="data"></param>
    private void  StopRecordResponse(ImRecordStopResp  data)
    {
        if(!string.IsNullOrEmpty(data.strfilepath))
        {
                        recordPath=data.strfilepath;
                        labelText = "停止录音返回:" recordPath;
                        Debug.Log("停止录音返回:" recordPath);
        }
    }
    public void ImRecordVolume(object data)
    {
        ImRecordVolumeNotify RecordVolumeNotify = data as ImRecordVolumeNotify;
        Debug.Log("ImRecordVolumeNotify:v_volume="   RecordVolumeNotify.v_volume);
    }
}

2.亲加 主要是各种事件回调和接口
使用操作起来有点复杂,但是功能全面。
(慎重选择)

亲加说明文档连接
http://www.gotye.com.cn/docs/ime/unity3d.html

Dome
using UnityEngine;  
using System.Collections;  
using gotye;  
public class MainManager : MonoBehaviour {  
    public GotyeAPI api;  
    string appKey = "xxxxxxxxxxxxxxxx";  
    string packageName = "com.gotye.api";  
    ListenerLogin listenerLogin;  
    ListenerChat listenerChat;  
    ListenerRoom listenerRoom;  
    string resurt = "";  
    string text = "";  
    static MainManager _instance;  
    public static MainManager Instance {  
        get { return _instance; }  
    }  
    void Awake()  
    {  
        InvokeRepeating("mainLoop", 0.0f, 0.050f);//初始化  
        _instance = this;  
    }  
    // Use this for initialization  
    void Start()  
    {  
        //初始化  
        api = GotyeAPI.GetInstance();  
        api.Init(appKey, packageName);  
        //添加事件回调  
        listenerLogin = new ListenerLogin();  
        listenerChat = new ListenerChat();  
        listenerRoom = new ListenerRoom();  
        api.AddListener(listenerLogin);  
        api.AddListener(listenerChat);  
        api.AddListener(listenerRoom);  
    }  
    void OnGUI()  
    {  
        GUI.Label(new Rect(200, 0, 200, 200), text);  
        GUI.Label(new Rect(200, 200, 200, 200), resurt);  
        if (GUI.Button(new Rect(0, 0, 200, 100), "sq123登录"))  
        {  
            text = "sq123登录";  
            api.Login("sq123", null);  
        }  
        if (GUI.Button(new Rect(0, 100, 200, 100), "sq222登录"))  
        {  
            text = "sq222登录";  
            api.Login("sq222", null);  
        }  
        if (GUI.Button(new Rect(0, 200, 200, 100), "进入聊天室"))  
        {  
            //298926  
            text = "进入聊天室";  
            GotyeRoom room = new GotyeRoom(298926);  
            api.EnterRoom(room);  
        }  
        if (GUI.Button(new Rect(0, 300, 200, 100), "开始说话"))  
        {  
            text = "开始说话";  
            GotyeRoom room = new GotyeRoom(298926);  
            //api.SendMessage(GotyeMessage.CreateTextMessage(room, "111"));  
            api.StartTalk(room,0,false,20000);  
        }  
        if (GUI.Button(new Rect(0, 400, 200, 100), "停止说话"))  
        {  
            text = "停止说话";  
            api.StopTalk();  
        }  
        if (GUI.Button(new Rect(0, 500, 200, 100), "退出聊天室"))  
        {  
            text = "退出聊天室";  
             GotyeRoom room = new GotyeRoom(298926);  
             api.LeaveRoom(room);  
        }  
        if (GUI.Button(new Rect(0, 600, 200, 100), "退出登录"))  
        {  
            text = "退出登录";  
            api.Logout();  
        }  
    }  
    void mainLoop()//初始化  
    {  
        GotyeAPI.GetInstance().MainLoop();  
    }  
    //显示Gui信息  
    public void ShowAnimate(string log) {  
        text = log;  
    }  
    public void ShowResurt(string log)  
    {  
        resurt = log;  
    }  
}  

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: