unity 接声网SDK还是比较容易的,按照官方的步骤做就可以,但有两点比较坑
首先说明我的API版本为3.6.1.1
一是退出程序时必须销毁直播引擎,否则在编辑器里重新启动时会报错 Create engine failed, error code: -7
二是默认的采集分辨率为640X360,如果想要更高的分辨率,需要调用引擎的 SetVideoEncoderConfiguration()方法,坑就坑在你必须要给所有的参数都赋一遍值,否则调用会不成功,及时某些参数有默认值也要手动赋值
//app的id
public string appId = "你的appID";
/// <summary>
/// 用户Id
/// </summary>
private uint uid = 0;
/// <summary>
/// 频道名
/// </summary>
private string channel = "你的频道";
private IRtcEngine mRtcEngine;
public VideoSurface vs;
/// <summary>
/// 需要的权限列表
/// </summary>
private List<string> permissionList = new List<string>();
public Text logText;
private void Start()
{
//设置永不息屏
Screen.sleepTimeout = SleepTimeout.NeverSleep;
//获取手机的权限
#if (UNITY_2018_3_OR_NEWER)
permissionList.Add(Permission.Microphone);
permissionList.Add(Permission.Camera);
#endif
//生成uid
uid = GenerateUid();
//先请求token
StartCoroutine(WaitTime());
}
private void Update()
{
#if (UNITY_2018_3_OR_NEWER)
// 获取设备权限。
CheckPermission();
#endif
}
/// <summary>
/// 请求权限,然后生成token
/// </summary>
/// <returns></returns>
private IEnumerator WaitTime()
{
//等待获取权限
yield return new WaitForSeconds(2f);
if (permissionList.Count >= 2)
{
//通过网络获取token
NetCenter.Instance.GetToken(uid,channel,Init);
}
else
{
StartCoroutine(WaitTime());
}
}
private void Init()
{
//初始化引擎
mRtcEngine = IRtcEngine.GetEngine(appId);
//本地用户成功加入频道时,会触发该回调。
mRtcEngine.OnJoinChannelSuccess = OnJoinChannelSuccess;
// SDK 接收到第一帧远端视频并成功解码时,会触发该回调。
// 可以在该回调中调用 SetForUser 方法设置远端视图。
mRtcEngine.OnUserJoined = OnUserJoinedHandler;
// 远端用户离开频道或掉线时,会触发该回调。
mRtcEngine.OnUserOffline = OnUserOfflineHandler;
//token过期前30秒,申请新token,并更新
mRtcEngine.OnTokenPrivilegeWillExpire = OnTokenPrivilegeWillExpireHandler;
//错误信息
mRtcEngine.OnError = OnErrorHandler;
//设置频道场景为直播
mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_LIVE_BROADCASTING);
// 设置用户角色为主播
mRtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
// 启用视频模块。
mRtcEngine.EnableVideo();
//设置分辨率
VideoEncoderConfiguration ve = new VideoEncoderConfiguration();
VideoDimensions vd = new VideoDimensions();
vd.width = 1280;
vd.height = 720;
ve.dimensions = vd;
ve.frameRate = FRAME_RATE.FRAME_RATE_FPS_15;
ve.minFrameRate = 0;
ve.bitrate = 3240;
ve.minFrameRate = 200;
ve.orientationMode = ORIENTATION_MODE.ORIENTATION_MODE_ADAPTIVE;
ve.degradationPreference = DEGRADATION_PREFERENCE.MAINTAIN_BALANCED;
ve.mirrorMode = VIDEO_MIRROR_MODE_TYPE.VIDEO_MIRROR_MODE_DISABLED;
print(mRtcEngine.SetVideoEncoderConfiguration(ve));
//设置降噪
VideoDenoiserOptions denoiser = new VideoDenoiserOptions();
denoiser.mode = 0; //降噪模式 0自动 1手动
denoiser.level = VIDEO_DENOISER_LEVEL.VIDEO_DENOISER_LEVEL_STRENGTH; //0性能质量平衡
mRtcEngine.SetVideoDenoiserOptions(true, denoiser);
// 获取本地视频显示,并传递到 Unity 层。
mRtcEngine.EnableVideoObserver();
// 如果频道中有 Web SDK,调用该方法开启 Native SDK 和 Web SDK 互通。
mRtcEngine.EnableWebSdkInteroperability(true);
// 加入频道。
mRtcEngine.JoinChannelByKey(NetCenter.Instance .token, channel, "",uid);
print("已加入");
}
private void OnJoinChannelSuccess(string channelName, uint uid, int elapsed)
{
}
private void OnUserJoinedHandler(uint uid, int elapsed)
{
// print("uid " + uid);
//vs.SetForUser(uid);
//vs.SetGameFps(30);
//vs.SetEnable(true);
}
private void OnUserOfflineHandler(uint uid, USER_OFFLINE_REASON reason)
{
}
private void OnTokenPrivilegeWillExpireHandler(string token)
{
NetCenter.Instance.GetToken(uid, channel);
mRtcEngine.RenewToken(NetCenter.Instance.token);
}
private void OnErrorHandler(int error, string msg)
{
print("error:"+error+" msg:"+msg);
}
/// <summary>
/// 获取权限
/// </summary>
private void CheckPermission()
{
#if (UNITY_2018_3_OR_NEWER)
foreach (string permission in permissionList)
{
if (Permission.HasUserAuthorizedPermission(permission))
{
}
else
{
Permission.RequestUserPermission(permission);
}
}
#endif
}
public void OnQuitCkick()
{
Application.Quit();
}
/// <summary>
/// 切换摄像头
/// </summary>
public void ChangeCamera()
{
mRtcEngine.SwitchCamera();
}
/// <summary>
/// 生成Uid
/// </summary>
private uint GenerateUid()
{
//获取当前时间的毫秒数
TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1);
uint milliseconds = (uint)ts.TotalMilliseconds;
//获取一个随机数
uint random = (uint)new System.Random().Next(0, 9999);
string temp = 1.ToString() + milliseconds.ToString() + random.ToString();
//uint最大为4294967295 10位数,保险起见我们规定uid最大为9位数
while (temp.Length > 9)
{
//如果长度大于9,去掉第二位,第一位为标记位不能移除,第一位用于区分是主播还是观众,在我们的系统里,所有角色都是主播,用ID来区分真实的主播和观众
temp = temp.Remove(1, 1);
}
return uint.Parse(temp);
}
private void OnDestroy()
{
IRtcEngine.Destroy();
mRtcEngine = null;
}
private void OnApplicationQuit()
{
IRtcEngine.Destroy();
mRtcEngine = null;
}
除此之外,在请求token时,发生了一些意外,请求的token是对的,但是返回的错误码永远都是过期,原因是我们的服务器时间比真实时间慢了一天,导致生成的token都是过期,声网的token保质期最长为24小时