
1. 概述
随着各互联网业务玩法的不断创新,上层业务APP往往需要控制音视频输入输出。同时开启多个音视频模块也是常见需求,但手机或PC设备往往只有一个录音或者摄像头,并只允许一个APP访问,因此为了协调模块间的设备使用情况,我们将设备管理模块单独提供给用户,以提供更好的用户体验,比如模块间切换时(从连麦模式切换到通话模式)不需要关闭摄像头再开启摄像头。
Device Manager与Render Manager是整个框架系统中两个通用模块,通话或者直播都需要这两个模块。Device Manager主要用于设备管理,而Render Manager主要用于管理与控制视频渲染View。
同时Device Manager还提供一些混音、混响、美颜、调节音量/音效、设置曝光策略等接口,用户可以通过这些接口操作设备数据源。

Render Manager主要用于管理用户设置的视频渲染View,用户创建视频渲染View以后,可以将View放到UI特定位置上,并通过Render Manager将某个View绑定到特定用户的视频流上完成对视频layout的控制。
注:对于Device Manager以及Render Manager对象,每个APP中只应维持一个单独的实例。
2. Device Manager基本功能代码示例
2.1 初始化并开启设备
xxxxxxxxxx// DeviceManager设备管理类初始化DeviceManager deviceManager = new DeviceManager(self.getApplicationContext());// 开启媒体设备, 开启设备将比较耗时,建议在加入会议之前开启设备deviceManager.startAudioDevice();//开启音频deviceManager.startCamera();//开启视频// 将Device manager传入room对象,// room对象将从device manager获取摄像头以及Microphone数据Room room = new Room(self.getApplicationContext(), deviceManager.getNativeInstance());2.2 关闭媒体设备并析构
xxxxxxxxxx// 关闭音视频设备,其它模块将不能收到数据deviceManager.stopAudioDevice();deviceManager.stopCamera();// 注意:room对象会引用并使用device manager对象,因此析构deviceManager前需要先析构roomroom.destroy();deviceManager.destroy();
3. Render Manager功能代码示例
xxxxxxxxxx// Android platformPoint size = new Point(layout.getLayoutParams().width, layout.getLayoutParams().height);// VideoView 继承于GLSurfaceView,可以设置Visibility等属性// APP可以将其放于UI layout中,视频输出位置VideoView render = rm.createRender(size);render.setVisibility(View.VISIBLE);render.setZOrderMediaOverlay(true);// 将render绑定到本地用户预览视频流rm.bindRenderWithStream(render, ""/*空字符串代表本地用户摄像头*/, true /*对于本地视频关闭纯音同步功能*/); // 将render与本地预览视频流解绑rm.unbindRenderWithStream(render);// 将render绑定到远端用户视频流rm.bindRenderWithStream(render, //remoteStreamId可以从onRemoteVidStreamCreated回调中得到 remoteStreamId, false /*对于远端视频开启纯音同步功能*/);
4. Device Manager混音功能调用框图
以MP3背景音乐混流为例,用户可以做到以下事情:
- 控制混音背景/前景音量;
- 音乐耳返、Mic数据耳返(Mic 数据耳返只在iOS上支持);
- 循环播放同一音乐;
- 暂停、恢复混音;
- 在混音结束得到通知;
目前除MP3外还支持M4A以及WAVE文件格式。

5. DeviceManager基本代码示例
- 构造并初始化DeviceManager
xxxxxxxxxx// Android platformDeviceManager dm = new DeviceManager(self.getApplicationContext());- 添加删除逻辑
xxxxxxxxxx// Android platformDeviceManager dm = new DeviceManager(self.getApplicationContext());... ...dm.destroy(); - 添加混音逻辑以及音量控制
xxxxxxxxxx// 初始化DeviceManager并开启音频设备和混音DeviceManager dm = new DeviceManager(self.getApplicationContext());dm.startAudioDevice();// 调用startMixMusic以后,如果此时系统正处于通话或者直播状态,// 则远端用户能听到音乐声音,并且本地用户也能从耳机中听到音乐声音dm.stratMixMusic("slow.mp3", true/*循环播放*/)// 设置发送出去的背景音乐音量dm.setBackgroundVolume(80); // 音量的值为0-100,值越大音量越大// 设置发送音频中本地人声的音量dm.setForegroundVolume(70); // 音量的值为0-100,值越大音量越大// 开启本地人声混响,设置混响级数int level = 4;dm.startReverberation(level); /* level的范围为1-4,值越大混响越强*/ // App层业务逻辑结束后关闭设备dm.stopAudioDevice();dm.destroy();- 静音麦克风以及扬声器
xxxxxxxxxx// 初始化DeviceManager并开启音频设备DeviceManager dm = new DeviceManager(self.getApplicationContext());dm.startAudioDevice();// 静音扬声器,混音后的Speaker数据将被重置dm.muteSpeaker();// 切换到扬声器、耳机模式手动切换// enable为true,使用扬声器模式;为false使用耳机模式;boolean enable = true;dm.setSpeaker(enable)// 静音麦克风,远端将听不到本地人声dm.muteMicrophone() // App层业务逻辑结束后关闭设备dm.stopAudioDevice();dm.destroy();
6. 监听Device Manager事件
xxxxxxxxxxpublic interface DeviceCallback { // 摄像头开启成功 public void onCameraStarted(); // 摄像头关闭完成 public void onCameraStopped(); // 麦克风开启失败, 1S钟内没有检测到音频数据则认为打开失败 // 常见的原因:1. 没有权限 2. 硬件失败 3.Mic被占用 public void onMicStartFailed(); // 摄像头开启失败,常见原因:1. 没有权限 2. 摄像头硬件故障 public void onCameraStartFailed(); // 音频文件混音结束事件,此事件意味着音频文件已经播放到文件尾 public void onAudioMixedMusicFinished();}xxxxxxxxxx// Android platformDeviceCallback deviceListener = new DeviceCallback() { //事件响应函数回调实现 ... ...};// 监听device manager相关事件,注:最多只能挂载一个事件监听者dm.attachCallback(deviceListener);// 开启摄像头,此函数调用后,如摄像头正常开启,用户将收到onStartCamera回调dm.startCamera();// 业务逻辑... ...dm.stopCamera();// 移除已经挂载的事件监听者dm.disattachCallback();7. 摄像头基本代码示例
切换摄像头代码示例
xxxxxxxxxx// 初始化DeviceManager并开启摄像头DeviceManager dm = new DeviceManager(self.getApplicationContext());// 默认将打开前置摄像头dm.startCamera();// 切换到后置摄像头dm.switchCamera();bool isFrontCamera = dm.isUsingFrontCamera();8. 视频美化代码示例
// 初始化DeviceManager并开启摄像头DeviceManager dm = new DeviceManager(self.getApplicationContext());dm.startCamera();// 开启Video前处理后,下面的美化效果才能生效dm.enableVideoPreprocess(true);// 设置视频美白程度int whiteLevel = 80;dm.setWhiteLevel(whiteLevel); // whiteLevel范围为[0-100]int currentWhiteLevel = dm.getWhiteLevel();// ASSERT(currentWhiteLevel == 80);// 设置磨皮程度int smoothLevel = 90;dm.setSmoothLevel(90); // smoothLevel范围为[0-100]int currentSmoothLevel = dm.getSmoothLevel();// ASSERT(currentSmoothLevel == 90);// 打开滤镜功能,目前支持的滤镜总类// "com.videofilter.gray" --> GRAY// "com.videofilter.nashville" --> NASHVILLE// "com.videofilter.clarendon" --> CLARENDON// "com.videofilter.juno" --> JUNO// "com.videofilter.gingham" --> GINGHAM// "com.videofilter.sweet" --> SWEET// "com.videofilter.dogpatch" --> DOGPATCH// "com.videofilter.crema" --> CREMA// "com.videofilter.aden" --> ADEN// "com.videofilter.stinson" --> STINSON// "com.videofilter.basic" --> None video filterString videoFilter = "com.videofilter.gray"; // 黑白滤镜dm.setVideoFilter(videoFilter);float value = 1.0;dm.setVideoFilterIntensity(value); // value 范围为[0-1]