游戏多媒体引擎 快速接入语音

为方便开发者调试和接入腾讯云游戏多媒体引擎产品 API,这里向你介绍 Native 工程快速接入文档。GME 快速入门文档只提供最主要的接入接口,协助用户进行接入。

相关产品
游戏多媒体引擎 产品页,含版本规格、价格与购买入口。

一、使用 GME 重要事项

GME 分为两个部分,提供实时语音服务、语音消息及转文本服务,使用这两个服务都依赖 Init 和 Poll 等核心接口。

注意:关于 Init 接口

注意:例如使用了实时语音服务,同时也需要使用语音消息服务,只需要调用一次 Init 初始化接口。

四、核心接口

·初始化 GME

·周期性调用 Poll 触发回调

五、实时语音

·加入实时语音房间

·打开或关闭麦克风

·打开或关闭扬声器

·退出语音房间

六、语音消息

·鉴权初始化

·启动流式语音识别

·停止录制

·反初始化 GME

八、1. 下载 SDK

进入下载指引页面,下载对应的 客户端 SDK。

九、2. 引入头文件

JavaObject-CC++import com.gme.TMG.ITMGContext;#import "GMESDK/TMGEngine.h"#import "GMESDK/QAVAuthBuffer.h"#include "auth_buffer.h"#include "tmg_sdk.h"

十、3. 获取单例

在使用语音功能时,需要首先获取 ITMGContext 对象。

十一、函数原型

JavaObject-CC++public static ITMGContext GetInstance(Context context)+ (ITMGContext*) GetInstance; static ITMGContext* ITMGContextGetInstance()

十二、示例代码

JavaObject-CC++//MainActivity.javaimport com.gme.TMG.ITMGContext;ITMGContext tmgContext = ITMGContext.GetInstance(this);//TMGSampleViewController.mITMGContext* _context = [ITMGContext GetInstance];ITMGContext* context = ITMGContextGetInstance();

十三、4. 设置回调

接口类采用 Delegate 方法用于向应用程序发送回调通知。将回调函数注册给 SDK,用于接收回调的信息,需要在进房之前设置。

十四、函数原型及示例代码

设置回调,用于接收回调的信息,需要在进房之前设置。

JavaObject-CC++//ITMGContextpublic abstract int SetTMGDelegate(ITMGDelegate delegate);//MainActivity.javatmgContext.SetTMGDelegate(TMGCallbackDispatcher.getInstance());ITMGDelegate < NSObject >//TMGSampleViewController.mITMGContext* _context = [ITMGContext GetInstance];_context.TMGDelegate = [DispatchCenter getInstance];//在初始化 SDK 时候m_pTmgContext = ITMGContextGetInstance();m_pTmgContext->SetTMGDelegate(this);//在析构函数中CTMGSDK_For_AudioDlg::~CTMGSDK_For_AudioDlg(){ ITMGContextGetInstance()->SetTMGDelegate(NULL);}

十五、回调示例

在构造函数中重写此回调函数,对回调参数进行处理。

JavaObject-CC++//MainActivity.javatmgContext.SetTMGDelegate(TMGCallbackDispatcher.getInstance());//RealTimeVoiceActivity.javapublic void OnEvent(ITMGContext.ITMG_MAIN_EVENT_TYPE type, Intent data) { if (type == ITMG_MAIN_EVENT_TYPE_ENTER_ROOM) { //回调处理 }}//需要参考 TMGCallbackDispatcher.java、TMGCallbackHelper.java以及 TMGDispatcherBase.java//TMGRealTimeViewController.mTMGRealTimeViewController ()< ITMGDelegate >- (void)OnEvent:(ITMG_MAIN_EVENT_TYPE)eventType data:(NSDictionary *)data { NSString *log = [NSString stringWithFormat:@"OnEvent:%d,data:%@", (int)eventType, data]; [self showLog:log]; NSLog(@"====%@====", log); switch (eventType) { // Step 6/11 : Perform the enter room event case ITMG_MAIN_EVENT_TYPE_ENTER_ROOM: { int result = ((NSNumber *)[data objectForKey:@"result"]).intValue; NSString *error_info = [data objectForKey:@"error_info"]; [self showLog:[NSString stringWithFormat:@"OnEnterRoomComplete:%d msg:(%@)", result, error_info]]; if (result == 0) { [self updateStatusEnterRoom:YES]; } } break; } }//需要参考 DispatchCenter.h、DispatchCenter.m//头文件中声明virtual void OnEvent(ITMG_MAIN_EVENT_TYPE eventType,const char* data);//示例代码void CTMGSDK_For_AudioDlg::OnEvent(ITMG_MAIN_EVENT_TYPE eventType, const char* data){ switch(eventType) { case ITMG_MAIN_EVENT_TYPE_XXXX_XXXX: { //对回调进行处理 } break; }}

参数 类型 含义
type ITMGContext.ITMG_MAIN_EVENT_TYPE 回调的事件类型
data Intent 消息类型 回调的相关信息,事件数据

十六、5. 初始化 SDK

未初始化前,SDK 处于未初始化阶段,需要通过接口 Init 初始化 SDK,才可以使用实时语音服务、语音消息服务及转文本服务。调用 Init 接口的线程必须于其他接口在同一线程,建议都在主线程调用接口。

十七、接口原型

JavaObject-CC++public abstract int Init(String sdkAppId, String openId);-(int)InitEngine:(NSString*)sdkAppID openID:(NSString*)openID;ITMGContext virtual int Init(const char* sdkAppId, const char* openId)

参数 类型 含义
sdkAppId string 来自 腾讯云控制台 的 GME 服务提供的 AppID,获取请参见 服务开通指引。
openID string openID 只支持 Int64 类型(转为 string 传入),规则由 App 开发者自行制定,App 内不重复即可。如需使用字符串作为 Openid 传入,可 提交工单 联系开发者。

十八、示例代码

JavaObject-CC++//MainActivity.javaint nRet = tmgContext.Init(appId, openId);if (nRet == AV_OK ){ // Step 4/11: Poll to trigger callback //https://cloud.tencent.com/document/product/607/15210#.E8.A7.A6.E5.8F.91.E4.BA.8B.E4.BB.B6.E5.9B.9E.E8.B0.83 EnginePollHelper.createEnginePollHelper(); showToast("Init success");}else if (nRet == AV_ERR_HAS_IN_THE_STATE) // 已经初始化过了,可以认为本次操作是成功的{ showToast("Init success");}else{ showToast("Init error errorCode:" + nRet);}//TMGSampleViewController.mQAVResult result = [_context InitEngine:self.appIDTF.text openID:self.openIDTF.text];if (result == QAV_OK) { self.isSDKInit = YES;}#define SDKAPPID3RD "14000xxxxx"cosnt char* openId="10001";ITMGContext* context = ITMGContextGetInstance();context->Init(SDKAPPID3RD, openId);

十九、6. 触发事件回调

通过在 update 里面周期的调用 Poll 可以触发事件回调。Poll 是 GME 的消息泵,GME 需要周期性的调用 Poll 接口触发事件回调。如果没有调用 Poll ,将会导致整个 SDK 服务运行异常。详情请参见 Sample Project 中的 EnginePollHelper 文件。

20、示例代码

JavaObject-CC++//MainActivity.javaEnginePollHelper.createEnginePollHelper();//EnginePollHelper.javaprivate Handler mhandler = new Handler(); private Runnable mRunnable = new Runnable() { @Override public void run() { if (s_pollEnabled) { if (ITMGContext.GetInstance(null) != null) ITMGContext.GetInstance(null).Poll(); } mhandler.postDelayed(mRunnable, 33); } };//周期性调用 Poll 请参考 EnginePollHelper.java 写法//TMGSampleViewController.m[EnginePollHelper createEnginePollHelper];//需要参考 EnginePollHelper.m 以及 EnginePollHelper.hvoid TMGTestScene::update(float delta){ ITMGContextGetInstance()->Poll();}

21、7. 本地鉴权计算

生成 AuthBuffer,用于相关功能的加密和鉴权,如正式发布请使用后台部署密钥,后台部署请参见 鉴权密钥。

22、接口原型

JavaObject-CC++AuthBuffer public native byte[] genAuthBuffer(int sdkAppId, String roomId, String openId, String key)//TMGSampleViewController.m[EnginePollHelper createEnginePollHelper];//需要参考 EnginePollHelper.m 以及 EnginePollHelper.hvoid TMGTestScene::update(float delta){ ITMGContextGetInstance()->Poll();}

参数 类型 含义
appId int 来自腾讯云控制台的 AppId 号码。
roomId string 房间号,最大支持127字符(离线语音房间号参数必须填 null)。
openId string 用户标识。与 Init 时候的 openId 相同。
key string 来自腾讯云 控制台 的权限密钥。

23、示例代码

JavaObject-CC++//GMEAuthBufferHelper.javaimport com.tencent.av.sig.AuthBuffer;//头文件public byte[] createAuthBuffer(String roomId) { byte[] authBuffer; // 生成鉴权秘钥,在开发调试阶段可以使用GME SDK提供的接口生成; // 应用正式发布时建议使用服务器生成,可参考https://cloud.tencent.com/document/product/607/12218 if (TextUtils.isEmpty(roomId)) { authBuffer = AuthBuffer.getInstance().genAuthBuffer(Integer.parseInt(mAppId), "0", mOpenId, mKey); }else { authBuffer = AuthBuffer.getInstance().genAuthBuffer(Integer.parseInt(mAppId), roomId, mOpenId, mKey); } return authBuffer; }// 生成鉴权秘钥,在开发调试阶段可以使用GME SDK提供的接口生成;// 应用正式发布时建议使用服务器生成,可参考https://cloud.tencent.com/document/product/607/12218//实时语音鉴权 NSData* authBuffer = [QAVAuthBuffer GenAuthBuffer:SDKAPPID3RD.intValue roomID:self.roomIdTF.text openID:_openId key:_key];//语音消息鉴权NSData* authBuffer = [QAVAuthBuffer GenAuthBuffer:(unsigned int)SDKAPPID3RD.integerValue roomID:nil openID:self.openId key:AUTHKEY];// 生成鉴权秘钥,在开发调试阶段可以使用GME SDK提供的接口生成;// 应用正式发布时建议使用服务器生成,可参考https://cloud.tencent.com/document/product/607/12218unsigned int bufferLen = 512;unsigned char retAuthBuff[512] = {0};QAVSDK_AuthBuffer_GenAuthBuffer(atoi(SDKAPPID3RD), roomId, "10001", AUTHKEY,retAuthBuff,bufferLen);

25、1. 加入房间

用生成的鉴权信息进房,加入房间默认不打开麦克风及扬声器。返回值为 AV_OK 的时候代表调用成功,不代表进房成功。

26、接口原型

JavaObject-CC++public abstract int EnterRoom(String roomID, int roomType, byte[] authBuffer);-(int)EnterRoom:(NSString*) roomId roomType:(int)roomType authBuffer:(NSData*)authBuffer;ITMGContext virtual int EnterRoom(const char* roomID, ITMG_ROOM_TYPE roomType, const char* authBuff, int buffLen);

参数 类型 含义
roomId String 房间号,最大支持127字符
roomType int 请使用 FLUENCY 类型音质进入房间
authBuffer byte[] 鉴权码

27、示例代码

JavaObject-CC++//RealTimeVoiceActivity.javabyte[] authBuffer = GMEAuthBufferHelper.getInstance().createAuthBuffer(roomId);ITMGContext.GetInstance(this).EnterRoom(roomId, roomType, authBuffer);//TMGRealTimeViewController.m[[ITMGContext GetInstance] EnterRoom:self.roomIdTF.text roomType:(int)self.roomTypeControl.selectedSegmentIndex + 1 authBuffer:authBuffer];ITMGContext* context = ITMGContextGetInstance();context->EnterRoom(roomID, ITMG_ROOM_TYPE_FLUENCY, (char*)retAuthBuff,bufferLen);

28、加入房间事件回调

加入房间完成后会发送信息 ITMG_MAIN_EVENT_TYPE_ENTER_ROOM,在 OnEvent 函数中进行判断回调后处理。如果回调为成功,即此时进房成功,开始进行计费。

注意:计费问题参考:

·示例代码:回调处理相关参考代码,包括加入房间事件以及断网事件。

JavaObject-CC++//RealTimeVoiceActivity.javapublic void OnEvent(ITMGContext.ITMG_MAIN_EVENT_TYPE type, Intent data) { if (type == ITMG_MAIN_EVENT_TYPE_ENTER_ROOM) { // Step 6/11 : Perform the enter room event int nErrCode = TMGCallbackHelper.ParseIntentParams2(data).nErrCode; String strMsg = TMGCallbackHelper.ParseIntentParams2(data).strErrMsg; if (nErrCode == AV_OK) { appendLog2MonitorView("EnterRomm success"); }else { appendLog2MonitorView(String.format(Locale.getDefault(), "EnterRomm errCode:%d errMsg:%s", nErrCode, strMsg)); } }} //TMGRealTimeViewController.m- (void)OnEvent:(ITMG_MAIN_EVENT_TYPE)eventType data:(NSDictionary *)data { NSString *log = [NSString stringWithFormat:@"OnEvent:%d,data:%@", (int)eventType, data]; [self showLog:log]; NSLog(@"====%@====", log); switch (eventType) { // Step 6/11 : Perform the enter room event case ITMG_MAIN_EVENT_TYPE_ENTER_ROOM: { int result = ((NSNumber *)[data objectForKey:@"result"]).intValue; NSString *error_info = [data objectForKey:@"error_info"]; [self showLog:[NSString stringWithFormat:@"OnEnterRoomComplete:%d msg:(%@)", result, error_info]]; if (result == 0) { [self updateStatusEnterRoom:YES]; } } break; } void TMGTestScene::OnEvent(ITMG_MAIN_EVENT_TYPE eventType,const char* data){ switch (eventType) { case ITMG_MAIN_EVENT_TYPE_ENTER_ROOM: { ListMicDevices(); ListSpeakerDevices(); std::string strText = "EnterRoom complete: ret="; strText += data; m_EditMonitor.SetWindowText(MByteToWChar(strText).c_str()); } } }

·错误码

错误码值 原因及建议方案
7006 鉴权失败,原因如下:AppID 不存在或者错误authbuff 鉴权错误鉴权过期 openId 不符合规范
7007 已经在其它房间
1001 已经在进房过程中,然后又重复了此操作。建议在进房回调返回之前不要再调用进房接口
1003 已经进房了在房间中,又调用一次进房接口
1101 确保已经初始化 SDK,确保 openId 是否符合规则,或者确保在同一线程调用接口,以及确保 Poll 接口正常调用

29、2. 开启或关闭麦克风

此接口用来开启关闭麦克风。加入房间默认不打开麦克风及扬声器。

30、示例代码

JavaObject-CC++//RealTimeVoiceActivity.javaITMGContext.GetInstance(this).GetAudioCtrl().EnableMic(true);//TMGRealTimeViewController.m[[[ITMGContext GetInstance] GetAudioCtrl] EnableMic:YES];ITMGContextGetInstance()->GetAudioCtrl()->EnableMic(true);

31、3. 开启或关闭扬声器

此接口用于开启关闭扬声器。

32、示例代码

JavaObject-CC++//RealTimeVoiceActivity.javaITMGContext.GetInstance(this).GetAudioCtrl().EnableSpeaker(true);//TMGRealTimeViewController.m[[[ITMGContext GetInstance] GetAudioCtrl] EnableSpeaker:YES];ITMGContextGetInstance()->GetAudioCtrl()->EnableSpeaker(true);

33、4. 退出房间

通过调用此接口可以退出所在房间。需等待退房回调并进行处理。

34、示例代码

JavaObject-CC++//RealTimeVoiceActivity.javaITMGContext.GetInstance(this).ExitRoom();//TMGRealTimeViewController.m[[ITMGContext GetInstance] ExitRoom];ITMGContext* context = ITMGContextGetInstance();context->ExitRoom();

35、退出房间回调

退出房间完成后会有回调,消息为 ITMG_MAIN_EVENT_TYPE_EXIT_ROOM。示例代码如下:

JavaObject-CC++//RealTimeVoiceActivity.javapublic void OnEvent(ITMGContext.ITMG_MAIN_EVENT_TYPE type, Intent data) { if (ITMGContext.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_EXIT_ROOM == type) { //收到退房成功事件 }}//TMGRealTimeViewController.m-(void)OnEvent:(ITMG_MAIN_EVENT_TYPE)eventType data:(NSDictionary *)data{NSLog(@"OnEvent:%lu,data:%@",(unsigned long)eventType,data);switch (eventType) { case ITMG_MAIN_EVENT_TYPE_EXIT_ROOM: { //收到退房成功事件 } break; }}void TMGTestScene::OnEvent(ITMG_MAIN_EVENT_TYPE eventType,const char* data){switch (eventType) { case ITMG_MAIN_EVENT_TYPE_EXIT_ROOM: { //进行处理 break; } }}

37、1. 鉴权初始化

在初始化 SDK 之后调用鉴权初始化,authBuffer 的获取参见上文实时语音鉴权信息接口 genAuthBuffer。

38、接口原型

JavaObject-CC++public abstract int ApplyPTTAuthbuffer(byte[] authBuffer);-(QAVResult)ApplyPTTAuthbuffer:(NSData *)authBuffer;ITMGPTT virtual int ApplyPTTAuthbuffer(const char* authBuffer, int authBufferLen)

参数 类型 含义
authBuffer String 鉴权

39、示例代码

JavaObject-CC++//VoiceMessageRecognitionActivity.javabyte[] authBuffer = GMEAuthBufferHelper.getInstance().createAuthBuffer("");ITMGContext.GetInstance(this).GetPTT().ApplyPTTAuthbuffer(authBuffer);//TMGPTTViewController.mNSData* authBuffer = [QAVAuthBuffer GenAuthBuffer:(unsigned int)SDKAPPID3RD.integerValue roomID:nil openID:self.openId key:AUTHKEY];[[[ITMGContext GetInstance] GetPTT] ApplyPTTAuthbuffer:authBuffer];ITMGContextGetInstance()->GetPTT()->ApplyPTTAuthbuffer(authBuffer,authBufferLen);

40、2. 启动流式语音识别

此接口用于启动流式语音识别,同时在回调中会有实时的语音转文字返回。停止录音调用 StopRecording,停止之后才有回调。

41、接口原型

JavaObject-CC++public abstract int StartRecordingWithStreamingRecognition (String filePath);public abstract int StopRecording();-(int)StartRecordingWithStreamingRecognition:(NSString *)filePath;-(QAVResult)StopRecording;ITMGPTT virtual int StartRecordingWithStreamingRecognition(const char* filePath) ITMGPTT virtual int StopRecording()

参数 类型 含义
filePath String 存放的语音路径

42、示例代码

JavaObject-CC++//VoiceMessageRecognitionActivity.javaITMGContext.GetInstance(this).GetPTT().StartRecordingWithStreamingRecognition(recordfilePath);//TMGPTTViewController.mQAVResult ret = [[[ITMGContext GetInstance] GetPTT] StartRecordingWithStreamingRecognition:[self pttTestPath]];if (ret == 0) { self.currentStatus = @"开始流式录音";} else { self.currentStatus = @"开始流式录音失败";}ITMGContextGetInstance()->GetPTT()->StartRecordingWithStreamingRecognition(filePath);

43、流式语音识别回调

启动流式语音识别后,需要在回调函数 OnEvent 中监听回调消息,事件消息分为 ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_COMPLETE ,在停止录制并完成识别后才返回文字,相当于一段话说完才会返回识别的文字。

根据需求在 OnEvent 函数中对相应事件消息进行判断。传递的参数包含以下4个信息。

消息名称 含义
result 用于判断流式语音识别是否成功的返回码
text 语音转文字识别的文本
file_path 录音存放的本地地址
file_id 录音在后台的 url 地址,录音在服务器存放90天

·示例代码

JavaObject-CC++//VoiceMessageRecognitionActivity.javaimport static com.tencent.TMG.ITMGContext.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_COMPLETE;public void OnEvent(ITMGContext.ITMG_MAIN_EVENT_TYPE type, Intent data) { if (type == ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_COMPLETE) { // Step 1.3/3 handle ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_COMPLETE event mIsRecording = false; if (nErrCode ==0) { String recordfilePath = data.getStringExtra("file_path"); mRecFilePathView.setText(recordfilePath); String recordFileUrl = data.getStringExtra("file_id"); mRecFileUrlView.setText(recordFileUrl); } else { appendLog2MonitorView("Record and recognition fail errCode:" + nErrCode); } }}//TMGPTTViewController.m- (void)OnEvent:(ITMG_MAIN_EVENT_TYPE)eventType data:(NSDictionary*)data { NSNumber *number = [data objectForKey:@"result"]; switch (eventType) { case ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_COMPLETE: { if (data != NULL &&[[data objectForKey:@"result"] intValue]== 0) { self.translateTF.text = [data objectForKey:@"text"] ; self.currentStatus = @"流式转换完成"; } } break; } void TMGTestScene::OnEvent(ITMG_MAIN_EVENT_TYPE eventType,const char* data){ switch (eventType) { case ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_COMPLETE: { HandleSTREAM2TEXTComplete(data,true); break; } … case ITMG_MAIN_EVNET_TYPE_PTT_STREAMINGRECOGNITION_IS_RUNNING: { HandleSTREAM2TEXTComplete(data, false); break; } } } void CTMGSDK_For_AudioDlg::HandleSTREAM2TEXTComplete(const char* data, bool isComplete) { std::string strText = "STREAM2TEXT: ret="; strText += data; m_EditMonitor.SetWindowText(MByteToWChar(strText).c_str()); Json::Reader reader; Json::Value root; bool parseRet = reader.parse(data, root); if (!parseRet) { ::SetWindowText(m_EditInfo.GetSafeHwnd(),MByteToWChar(std::string("parse result Json error")).c_str()); } else { if (isComplete) { ::SetWindowText(m_EditUpload.GetSafeHwnd(), MByteToWChar(root["file_id"].asString()).c_str()); } else { std::string isruning = "STREAMINGRECOGNITION_IS_RUNNING"; ::SetWindowText(m_EditUpload.GetSafeHwnd(), MByteToWChar(isruning).c_str()); } } }

·错误码

错误码 含义 处理方式
32775 流式语音转文本失败,但是录音成功 调用 UploadRecordedFile 接口上传录音,再调用 SpeechToText 接口进行语音转文字操作
32777 流式语音转文本失败,但是录音成功,上传成功 返回的信息中有上传成功的后台 url 地址,调用 SpeechToText 接口进行语音转文字操作
32786 流式语音转文本失败 在流式录制状态当中,请等待流式录制接口执行结果返回

44、3. 停止录音

此接口用于停止录音。此接口为异步接口,停止录音后会有录音完成回调,成功之后录音文件才可用。

45、接口原型

JavaObject-CC++public abstract int StopRecording();-(QAVResult)StopRecording;ITMGPTT virtual int StopRecording();

46、示例代码

JavaObject-CC++//VoiceMessageRecognitionActivity.javaITMGContext.GetInstance(this).GetPTT().StopRecording();//TMGPTTViewController.m- (void)stopRecClick { // Step 3/12 stop recording, need handle ITMG_MAIN_EVNET_TYPE_PTT_RECORD_COMPLETE event // https://cloud.tencent.com/document/product/607/15221#.E5.81.9C.E6.AD.A2.E5.BD.95.E9.9F.B3 QAVResult ret = [[[ITMGContext GetInstance] GetPTT] StopRecording]; if (ret == 0) { self.currentStatus = @"停止录音"; } else { self.currentStatus = @"停止录音失败"; } } ITMGContextGetInstance()->GetPTT()->StopRecording();

赞 (0)
上一篇 4天前
下一篇 4天前