# 一、接入流程
# 1.直播入口检测 (在登录后执行)
FString UserInfo = FString::Printf(TEXT("{\"openid\":\"%s\",\"appid\":\"%s\",\"renderer\":\"%s\"}"),*UserId, *WxAppId,*FPlatformMisc::GetPrimaryGPUBrand());
UWXGameLiveEngine::CheckSupport(UserInfo, TestEnv, [=](int result, const FString& message)
{
//处理回调结果
if (result == 0) {
// 显示直播入口
LiveButton->SetVisibility(ESlateVisibility::Visible);
// 初始化SDK
UWXGameLiveEngine::Init(mGameName,mGameAppId,mIlinkAppId);
// 启用跳转视频号能力
UWXGameLiveEngine::EnableStartChannelLive(true);
// 启用内部麦克风权限申请逻辑
UWXGameLiveEngine::AuthorizeInnerAudio(true);
// 启用SDK内部麦克风采集
UWXGameLiveEngine::EnableInnerAudioCapture(true);
// 设置直播事件监听
UWXGameLiveEngine::SetLiveEventObserver(this);
}
else
{
GEngine->AddOnScreenDebugMessage(-1,200.f,FColor::Blue, FString::Printf(TEXT("CheckSupport result: %d , message: %s"), result, *message));
}
});
# 2.拉起挂件直播
void LaunchLiveWidget()
{
// LoadLiveWebView必须在Init之后调用
UWXGameLiveEngine::LoadLiveWidget();
}
# 3.处理视频号授权事件
void OnRequireAuthorize()
{
// 使用MSDK进行视频号授权
#if PLATFORM_IOS || PLATFORM_ANDROID
MSDKLogin::ChannelPermissionAuth("WeChat", "snsapi_channels_livestream");
#endif
}
# 4.处理打开链接事件
void OnOpenUrl(const FString& url, int screenType, bool isFullScreen, bool isBrowser)
{
// eg:使用MSDKWebView打开链接
MSDKWebView::OpenUrl(TCHAR_TO_UTF8(*url),screenType, isFullScreen, true, "", isBrowser);
}
# 5.处理跳转微信事件
void OnStartChannelLive(const FString& liveJsonInfo)
{
MSDKFriendReqInfo ReqInfo;
ReqInfo.type = kMSDKFriendReqTypeWXChannelStartLive;
ReqInfo.extraJson = TCHAR_TO_UTF8(*liveJsonInfo);
MSDKFriend::SendMessage(ReqInfo,"WeChat");
}
# 6.处理开播事件
void OnStartLive(bool isAudioPermissionGranted)
{
// 启动视频采集
m_WXVideoCapture.Reset(new WXVideoCapture());
m_WXVideoCapture->StartCapturingFrames();
if (isAudioPermissionGranted) {
// 如果没有使用SDK内部麦克风采集,需要在这里启动第三方语音引擎(如GVoice)的PCM数据回调
} else {
// 用户拒绝了麦克风权限,可以给下提示:没有麦克风权限,无法采集主播语音
}
}
# 7.处理关播事件
void OnStopLive()
{
// 停止视频采集
if (m_WXVideoCapture.IsValid())
{
m_WXVideoCapture->StopCapturingFrames();
m_WXVideoCapture.Release();
}
// 如果使用了第三方语音引擎的PCM采集,这里需要停止采集
}
# 8.GVoice 语音采集
# 9.微信拉起游戏开播
- 监听游戏被第三方应用拉起时,传递过来的参数,确认是被微信视频号拉起时,调用OnMessageFromWeChat接口将相关参数传给直播SDK。 以MSDK为例,示例如下:
void UWXLiveUserWidget::OnBaseRetNotify(const MSDKBaseRet& baseRet)
{
GEngine->AddOnScreenDebugMessage(-1,200.f,FColor::Blue, FString::Printf(TEXT("OnBaseRetNotify methodNameID: %d"), baseRet.methodNameID));
UE_LOG(WXLiveLog, Log, TEXT("OnBaseRetNotify methodNameID: %d"), baseRet.methodNameID);
if (baseRet.methodNameID == kMethodNameChannelPermissionAuth)
{
// 视频号授权票据返回
std::string ExtraInfo = baseRet.extraJson;
#if PLATFORM_ANDROID
// android平台上,msdk返回的tdiAuthBuffer字段中多出了3个换行符,需要msdk修复,这里先临时处理下
std::string::size_type pos = 0;
std::string target = "\\n";
while ((pos = ExtraInfo.find(target,pos)) != std::string::npos)
{
ExtraInfo.erase(pos, target.length());
}
//ExtraInfo.erase(std::remove(ExtraInfo.begin(),ExtraInfo.end(),'\n'),ExtraInfo.end());
#endif
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(FString(ExtraInfo.c_str()));
TSharedPtr<FJsonObject> rRoot;
if (FJsonSerializer::Deserialize(Reader, rRoot) && rRoot.IsValid())
{
if (rRoot->HasField(TEXT("tdiAuthBuffer")))
{
TArray<uint8> TdiAuthBuffer;
const FString STdiAuthBuffer = rRoot->GetStringField(TEXT("tdiAuthBuffer"));
FBase64::Decode(STdiAuthBuffer,TdiAuthBuffer);
GEngine->AddOnScreenDebugMessage(-1,200.f,FColor::Blue, FString::Printf(TEXT("OnBaseRetNotify STdiAuthBuffer: %s"), *STdiAuthBuffer));
UWXGameLiveEngine::AuthorizeFinish(baseRet.retCode, TdiAuthBuffer);
}
}
}
else if (baseRet.methodNameID == kMethodNameWakeUp)
{
// 视频号拉起游戏开播
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(FString(baseRet.extraJson.c_str()));
TSharedPtr<FJsonObject> rRoot;
// bool bSuccessful = FJsonSerializer::Deserialize(Reader, rRoot);
if (FJsonSerializer::Deserialize(Reader, rRoot) && rRoot.IsValid())
{
const TSharedPtr<FJsonObject>* ParamsObj = nullptr;
GEngine->AddOnScreenDebugMessage(-1,200.f,FColor::Blue, FString::Printf(TEXT("OnBaseRetNotify retCode: %d extraJson: %s"), baseRet.retCode,*FString(baseRet.extraJson.c_str())));
const FString Params = rRoot->GetStringField(TEXT("params"));
const TSharedRef<TJsonReader<>> ParamsReader = TJsonReaderFactory<>::Create(Params);
TSharedPtr<FJsonObject> ParamsObject;
if (FJsonSerializer::Deserialize(ParamsReader, ParamsObject) && ParamsObject.IsValid())
{
// 接受来自视频号的参数
FString msgFromChannel;
#if PLATFORM_ANDROID
ParamsObject->TryGetStringField(TEXT("_wxappextendobject_extInfo"),msgFromChannel);
#elif PLATFORM_IOS
ParamsObject->TryGetStringField(TEXT("messageExt"),msgFromChannel);
#endif
UE_LOG(WXLiveLog, Log, TEXT("OnBaseRetNotify msgFromChannel: %s"), *msgFromChannel);
GEngine->AddOnScreenDebugMessage(-1,200.f,FColor::Blue, FString::Printf(TEXT("OnBaseRetNotify msgFromChannel: %s"), *msgFromChannel));
if (msgFromChannel.Contains(TEXT("WeChatLive_ShiPinHao")))
{
UWXGameLiveEngine::OnMessageFromWeChat(msgFromChannel);
}
}
}
}
# 注意事项
- 使用Fmod for Unreal音频引擎时,启用WXGameLive.Build.cs文件中以下几行注释:
/*********************FMOD Setting Begin******************/
#if UE_4_19_OR_LATER
PublicDefinitions.Add("USE_FMOD");
#else
Definitions.Add("USE_FMOD");
#endif
PrivateDependencyModuleNames.AddRange(
new string[]
{
"FMODStudio",
}
);
/*********************FMOD Setting End******************/
- 使用Wwise情况下,sdk提供了wwise的录音插件:WGLive,游戏侧需将该插件挂在到wwise的工程的master总线上后,重新build sound bank资源。并且启用WXGameLive.Build.cs文件中以下一行注释
PublicAdditionalLibraries.Add(Path.Combine(LibDir, "wwise/libWGLiveFX.a"));
GVoice的时序需要特别注意:
a. mVoiceEngine.invoke(4, 1, 0, null) 必须在麦克风权限同意后再调用
b. mVoiceEngine.invoke(5, 1, 1, null) 必须在mVoiceEngine.Init()之前调用游戏注销当前登录的帐号时需要关闭当前的直播,调用如下接口:
UWXGameLiveEngine::PostGameMessage(TEXT("{\"type\":\"finishLive\"}"),0);