本文为声网 RTE 开发者社区作者投稿,作者为 @arige
指标
1. 制订指标
无妨大家想一下这个场景:
你走进一个咖啡厅,看到了一个美女或者帅哥,想要一个微信号,不便后续倒退。
那咱们要怎么做呢?
走到对方跟前,小声对他说:“你好,你长的很像我的前女友(前男友),能够加下你的微信吗?”。
对方有可能悄声的说,“我扫你”。
你这个时候你就须要把你的二维码展现给他。
当你们恋爱胜利,求婚的时候,可能要找一个更加浪漫的环境,并且你们的对话心愿给更多人看到、听到。
通过这个下面场景的设想,咱们能够简略的确定一些根本的因素
- 能够更改的场景(咖啡厅和求婚现场)
- 自主塑造形象性能(毕竟外貌是一见倾心的原点)
- 单聊(要微信号不能一次要一群人得呀。不然可能被当成流氓给打得哟)
- 文件共享(把本人得二维码展现给对方,让对方加好友)
- 群聊、群视频(把求婚现场给其余用户看)
2. 拆解指标
为了满足下面提到得要求,咱们须要以下性能:
- 反对 unity 的不便接入。毕竟 unity 是一个十分好的 3D 引擎,如果能够不便接入得话,在后续得场景创立和人物发明上都能够有更大的扩大空间
- 1 vs 1 的视频,或者 1 vs 多的直播模式。能够满足单聊和群聊的需要
- 同步本地播放的本地视频或者远端视频给其余用户。能够满足共享二维码的需要。
3. 成果预览
如果要残缺的实现一个残缺的我的项目会破费比拟多的工夫,而我发现目前声网的 Demo 会提供简略的人物模型和素材,然而他们开放度较高,开发者能够依据须要应用本人定制化的模型素材,为了实现上述提到的需要,我只做了一些渺小的批改,就满足了咱们的需要。本次次要看下成果,为后续在生产环境中落地做一些技术上的储备。
以下是在 demo 上调整后显示进去的成果。
这是用 unity 来实现的一个咖啡厅的样子
这是一个服装店,咱们能够给人物进行换装,这个也是由 unity 来实现的。
以上两个的接入都十分的不便,咱们能够很好的对接 unity,如果需要的话,后续有本人的 unity 场景也能够疾速接入。
这个是我本人测试的 1 vs 1 的视频测试成果
这个是我本人测试的将本地视频分享给对方的一个成果
设想一下,是不是能够和你的对象一起看剧了呢?
简略实现
以上成果都是基于声网的 sdk 来实现的,如果你也想进行尝试或者应用,能够持续查看我的接入过程和两头遇到的问题以及解决方案。
1. 账号筹备
咱们既然应用了声网的 sdk,那注册一个声网的账号做一些声网的账号配置也很正当吧。
- 注册账号
- 实现实名
- 创立我的项目
- 配置我的项目
而后进入具体配置
生成 token,并将 appid、证书、token 复制保留。
留神!!!这里很重要,肯定要看认真,我的项目中会应用到!
至此,账号的筹备曾经实现了。
2. 配置我的项目
- demo 源码
- 通过声网官网客服,申请元宇宙 SDK、Unity 工程文件、开发指南,同时申请开明应用权限,详情可拜访 shengwang.cn
- 将 sdk 解压并配置到我的项目中 肯定要留神目录,如果本人的我的项目中不存在以后的目录要本人创立
- 配置 id 个别状况下,这个文件是不会上传到近程仓库的,写到这里也次要是平安思考。将在后盾中申请的 appid、证书,复制后粘贴到 /Android/local.properties 外面,如下:
- 配置 channel 将在后盾生成 token 的时候,填写的 channel 给写到类中,如下
- 配置我的项目权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 对于 Android 12.0 及以上设施,还须要增加如下权限:-->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
留神:
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA
须要动静申请权限,否则无奈失常实现视频性能。
sdk 自身是不会去申请权限的,所以须要咱们本人在适合的地位帮 sdk 申请好权限。
- 混同配置
咖啡厅
做形象
服装店
这里是间接应用了声网给的成果,如果本人我的项目需要的话,能够去本人去调整。
其中换装和捏脸都须要 unity 上的一些批改和 native 与 unity 的通信。整个能够参考换装和捏脸
3. 视频 1vs1
后面曾经实现了整体我的项目的构建。并且曾经把 unity 内容跑起来了,那么接下来咱们看下,如果要实现 1vs1 的视频要怎么解决。为了不便解决,我独自写了一个页面来解决视频 1vs1,成果如下:
视频聊天
这个流程图,倡议大家多看几遍,在咱们遇到问题的时候,这个图会给咱们启发,帮忙咱们解决问题。
具体流程:
1. 创立 RtcEngine 对象
该对象治理了整个的视频等场景,是一个十分外围的对象。
try {RtcEngineConfig config = new RtcEngineConfig();
config.mContext = getBaseContext();
config.mAppId = appId;
config.mEventHandler = mRtcEventHandler;
config.mAudioScenario = Constants.AudioScenario.getValue(Constants.AudioScenario.DEFAULT);
mRtcEngine = RtcEngine.create(config);
} catch (Exception e) {throw new RuntimeException("Check the error.");
}
2. 创立 RtcEngine 属性
// 视频默认禁用,你须要调用 enableVideo 启用视频流。mRtcEngine.enableVideo();
// 录音默认禁用,你须要调用 enableAudio 启用录音。mRtcEngine.enableAudio();
// 开启本地视频预览。mRtcEngine.startPreview();
3. 将本地摄像头内容显示到 local_video_view_container 上
FrameLayout container = findViewById(R.id.local_video_view_container);
// 创立一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象。SurfaceView surfaceView = new SurfaceView (getBaseContext());
container.addView(surfaceView);
// 将 SurfaceView 对象传入声网,以渲染本地视频。mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, KeyCenter.RTC_UID));
4. 设置以后的模式
ChannelMediaOptions options = new ChannelMediaOptions();
// 将用户角色设置为 BROADCASTER。options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER;
// 视频通话场景下,设置频道场景为 BROADCASTING。options.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING;
其中 clientRoleType 有两种,如果是 CLIENT_ROLE_BROADCASTER 就是能够播和收,如果是 CLIENT_ROLE_AUDIENCE 就只能收看,以后就成了主播模式。
5. 退出频道
// 应用长期 Token 退出频道。// 你须要自行指定用户 ID,并确保其在频道内的唯一性。int res = mRtcEngine.joinChannel(token, channelName, KeyCenter.RTC_UID, options);
if (res != 0)
{
// Usually happens with invalid parameters
// Error code description can be found at:
// en: https://docs.agora.io/en/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_error_code.html
// cn: https://docs.agora.io/cn/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_error_code.html
Log.e("video","join err:"+RtcEngine.getErrorDescription(Math.abs(res)));
}
joinChannel 办法有返回值,能够看到咱们退出频道是否胜利了,如果不胜利的话,咱们能够看下谬误起因,并对照解决;如果胜利了,就能够察看 IRtcEngineEventHandler 对象的回调办法,重点关注下 onError(int err) 和 onJoinChannelSuccess(String channel, int uid, int elapsed) 如果收到 onJoinChannelSuccess 办法的回调,咱们就能够关注 onUserJoined(int uid, int elapsed) 办法,咱们能够在这个办法里开始显示远端内容。
6. 显示远端内容
@Override
// 监听频道内的远端主播,获取主播的 uid 信息。public void onUserJoined(int uid, int elapsed) {Log.e(TAG, "onUserJoined->" + uid);
runOnUiThread(new Runnable() {
@Override
public void run() {
// 从 onUserJoined 回调获取 uid 后,调用 setupRemoteVideo,设置远端视频视图。setupRemoteVideo(uid);
}
});
}
private void setupRemoteVideo(int uid) {FrameLayout container = findViewById(R.id.remote_video_view_container);
SurfaceView surfaceView = new SurfaceView (getBaseContext());
surfaceView.setZOrderMediaOverlay(true);
container.addView(surfaceView);
mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, uid));
}
最终,远端的视频会显示在 remote_video_view_container 上。
4. 将本地播放的视频显示给远端用户
同步本地播放给远端
将本地视频怎么同步给远端的用户呢?其实从实质上来讲,将本地摄像头和将本地播放的视频给远端用户看,对远端用户都是一样的,不一样的是本地用户给远端用户的数据源是哪个。一个是摄像头,一个是播放器。
- 设置本地 video 的时候做下批改
FrameLayout container = findViewById(R.id.local_video_view_container);
// 创立一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象。SurfaceView surfaceView = new SurfaceView (getBaseContext());
container.addView(surfaceView);
// 将 SurfaceView 对象传入声网,以渲染本地视频。VideoCanvas videoCanvas = new VideoCanvas(surfaceView, Constants.RENDER_MODE_HIDDEN, Constants.VIDEO_MIRROR_MODE_AUTO,
Constants.VIDEO_SOURCE_MEDIA_PLAYER, mediaPlayer.getMediaPlayerId(), KeyCenter.RTC_UID);
mRtcEngine.setupLocalVideo(videoCanvas);
- 在 int res = mRtcEngine.joinChannel(token, channelName, KeyCenter.RTC_UID, options); 是 0 的时候,调用如下办法:
int res = mRtcEngine.joinChannel(token, channelName, KeyCenter.RTC_UID, options);
if (res != 0)
{
// Usually happens with invalid parameters
// Error code description can be found at:
// en: https://docs.agora.io/en/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_error_code.html
// cn: https://docs.agora.io/cn/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler_1_1_error_code.html
Log.e("video","join err:"+RtcEngine.getErrorDescription(Math.abs(res)));
}else {mediaPlayer = mRtcEngine.createMediaPlayer();
mediaPlayer.registerPlayerObserver(this);
mediaPlayer.open(MetaChatConstants.VIDEO_URL, 0);
}
3. 监听 onPlayerStateChanged 回调并在 state 是 PLAYER_STATE_OPEN_COMPLETED 的时候执行 play 办法,代码如下:
public void onPlayerStateChanged(io.agora.mediaplayer.Constants.MediaPlayerState state, io.agora.mediaplayer.Constants.MediaPlayerError error) {if(state == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_OPEN_COMPLETED){mediaPlayer.play();
}
}
至此,就实现了性能上的应用。
其它性能
除了下面提到的性能外,声网还提供了一些其余的性能,在须要的时候能够间接应用,或者大量批改就能够用的。
比如说空间音效性能,该性能基于声学原理,模仿声音在不同空间环境中的流传、反射、排汇成果。能够为用户提供游览中路人聊天声、海浪声、风声等,让用户更沉迷式体验
再比如说实时共赏影音性能。该性能能够简直无延时的实现,近程观影、听歌等性能。甚至能够实现 k 歌的能力。
更多的性能期待大家一起挖掘!
参考资料
- 注册并试用每月 10000 分钟收费的声网视频 SDK,体验四行代码、三十分钟疾速构建沉迷式实时互动场景
- 下载体验声网相干 SDK & Demo