差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
im:android:basics:audiovideo [2019/11/27 04:07]
huanxinfudh
— (当前版本)
行 1: 行 1:
-====== 实时通话 ====== 
- 
----- 
- 
-实时通话分为视频通话和音频通话,与普通电话不同,它是基于网络的。 
- 
-===== 实时通话的数据流量 ===== 
- 
-实时语音和实时视频的数据流量如下: 
- 
-实时语音: 
-  * 双向 170k bytes/​minute ​ 
-实时视频(单路): 
-  * 240p: 0.75M ~ 3M  
-  * 480p: 2.2M ~ 7.5M 
-  * 720p: 6.5M ~ 18.5M 
-  * 1080p: 15M ~ 37.5M 
- 
-===== 监听呼入通话 ===== 
- 
-通过注册相应 action 的 BroadcastReceiver 来监听呼叫过来的通话,接到广播后开发者可以调起 APP 里的通话 Activity。 
- 
-<code java> 
-IntentFilter callFilter = new IntentFilter(EMClient.getInstance().callManager().getIncomingCallBroadcastAction());​ 
-registerReceiver(new CallReceiver(),​ callFilter);​ 
- 
-private class CallReceiver extends BroadcastReceiver { 
- 
- @Override 
- public void onReceive(Context context, Intent intent) { 
- // 拨打方username 
- String from = intent.getStringExtra("​from"​);​ 
- // call type 
- String type = intent.getStringExtra("​type"​);​ 
-                //​跳转到通话页面 
- 
- } 
-} 
-</​code>​ 
- 
-===== 监听通话状态 ===== 
- 
-通过 addCallStateChangeListener 监听通话状态。 
- 
-**注意:**在收到 DISCONNECTED 回调时才能 finish 当前页面(保证通话所占用的资源都释放完),然后开始下一个通话。 
- 
-<code java> 
-EMClient.getInstance().callManager().addCallStateChangeListener(new EMCallStateChangeListener() { 
-    @Override 
-    public void onCallStateChanged(CallState callState, CallError error) { 
-        switch (callState) { 
-        case CONNECTING: // 正在连接对方 
-            
-            break; 
-        case CONNECTED: // 双方已经建立连接 
-            
-            break; 
- 
-        case ACCEPTED: // 电话接通成功 
-            
-            break; 
-        case DISCONNECTED:​ // 电话断了 
- 
-            break; 
-        case NETWORK_UNSTABLE:​ //​网络不稳定 
-            if(error == CallError.ERROR_NO_DATA){ 
- //​无通话数据 
-     }else{ 
-     } 
-     break; 
- case NETWORK_NORMAL:​ //​网络恢复正常 
-  
-     break; 
-        default: 
-            break; 
-        } 
- 
-    } 
-}); 
-</​code>​ 
- 
-详细回调请参考[[http://​www.easemob.com/​apidoc/​android/​chat3.0/​annotated.html|API Doc]]。 
- 
-===== 拨打语音通话 ===== 
- 
-<code java> 
-/** 
-* 拨打语音通话 
-* @param to 
-* @throws EMServiceNotReadyException 
-*/ 
-try {//​单参数 
- EMClient.getInstance().callManager().makeVoiceCall(username);​ 
-} catch (EMServiceNotReadyException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
- 
-try {//​多参数 
- EMClient.getInstance().callManager().makeVoiceCall(username,"​ext 扩展内容"​);​ 
-} catch (EMServiceNotReadyException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
- 
-try {//​多参数,​ recordOnServer:​是否在服务器端录制该通话,​ mergeStream:​服务器端录制时是否合并流 
- EMClient.getInstance().callManager().makeVoiceCall(username,"​ext 扩展内容",​ recordOnServer,​ mergeStream);​ 
-} catch (EMServiceNotReadyException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
- 
-//​获取扩展内容 
- ​String callExt = EMClient.getInstance().callManager().getCurrentCallSession().getExt();​ 
-</​code>​ 
- 
-===== 拨打视频通话 ===== 
- 
-<code java> 
-/** 
-* 拨打视频通话 
-* @param to 
-* @throws EMServiceNotReadyException 
-*/ 
-try {//​单参数 
- EMClient.getInstance().callManager().makeVideoCall(username);​ 
-} catch (EMServiceNotReadyException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
- 
-try {//​多参数 
- EMClient.getInstance().callManager().makeVideoCall(username,"​ext 扩展内容"​);​ 
-} catch (EMServiceNotReadyException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
- 
-try {//​多参数,​ recordOnServer:​是否在服务器端录制该通话,​ mergeStream:​服务器端录制时是否合并流 
-    EMClient.getInstance().callManager().makeVideoCall(username,"​ext 扩展内容",​ recordOnServer,​ mergeStream);​ 
-} catch (EMServiceNotReadyException e) { 
-    // TODO Auto-generated catch block 
-    e.printStackTrace();​ 
-} 
- 
-//​获取扩展内容 
- ​String callExt = EMClient.getInstance().callManager().getCurrentCallSession().getExt();​ 
-</​code>​ 
- 
-视频通话需要显示自己和对方的图像,需要[[#​视频通话设置显示自己和对方图像的surfaceView|设置相应 surfaceview]]。 
- 
-===== 接听通话 ===== 
- 
-<code java> 
-/** 
-* 接听通话 
-* @throws EMNoActiveCallException 
-* @throws EMNetworkUnconnectedException 
-*/ 
-try { 
- EMClient.getInstance().callManager().answerCall();​ 
-} catch (EMNoActiveCallException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} catch (EMNetworkUnconnectedException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
-</​code>​ 
- 
-===== 拒绝接听 ===== 
- 
-<code java> 
-/** 
-* 拒绝接听 
-* @throws EMNoActiveCallException 
-*/ 
-try { 
- EMClient.getInstance().callManager().rejectCall();​ 
-} catch (EMNoActiveCallException e) { 
- // TODO Auto-generated catch block 
- e.printStackTrace();​ 
-} 
-</​code>​ 
- 
-===== 挂断通话 ===== 
- 
-<code java> 
-/** 
-* 挂断通话 
-*/ 
-EMClient.getInstance().callManager().endCall();​ 
-</​code>​ 
- 
-===== 暂停和恢复语音或视频数据传输 ===== 
- 
-暂停语音数据传输: 
- 
-''​EMClient.getInstance().callManager().pauseVoiceTransfer()''​ 
- 
-恢复语音数据传输: 
- 
-''​EMClient.getInstance().callManager().resumeVoiceTransfer()''​ 
- 
-暂停视频(图像)数据传输: 
- 
-''​EMClient.getInstance().callManager().pauseVideoTransfer()''​ 
- 
-恢复视频(图像)数据传输: 
- 
-''​EMClient.getInstance().callManager().resumeVideoTransfer()''​ 
- 
-**调用后对方会收到相应VOICE_PAUSE、VOICE_RESUME、VIDEO_PAUSE、VIDEO_RESUME的callstate的变动通知。** 
- 
-===== 视频通话设置显示自己和对方图像的 surfaceView ===== 
- 
-视频通话需要预先设置 localSurfaceView、oppositeSurfaceView, 
-而且必须在''​Activity.onCreate(Context context)''​方法中设置,之后才能正确捕捉 Surface 的变化。 
- 
-<code java> 
-EMClient.getInstance().callManager().setSurfaceView(localSurface,​ oppositeSurface);​ 
-</​code>​ 
- 
-===== 视频通话处理本地摄像头数据 ===== 
-如果需要处理自己本地视频数据,比如美颜等操作,可以自己输入视频数据进行操作,原来的回调视频数据接口''​EMCameraDataProcessor''​已经废弃,不推荐使用; 
- 
-使用方式: 
-<code java> 
-/** 
- * 首先在初始化音视频部分设置外部输入视频数据 
- * 设置是否启用外部输入视频数据,默认 false,如果设置为 true,需要自己调用 
- * {@link EMCallManager#​inputExternalVideoData(byte[],​ int, int, int)}输入视频数据 
- */ 
-EMClient.getInstance().callManager().getCallOptions().setEnableExternalVideoData(true);​ 
-... 
-/** 
- * 然后就是自己获取视频数据,进行美颜等处理,循环调用以下方法输入数据就行了(这个调用频率就相当于你的帧率,调用间隔可以自己进行控制,一般最大30帧/​秒) 
- * 视频数据的格式是摄像头采集的格式即:NV21 420sp 自己手动传入时需要将自己处理的数据转为 yuv 格式输入 
- */ 
-EMClient.getInstance().callManager().inputExternalVideoData(data,​ width, height, rotate); 
-</​code>​ 
- 
-===== 切换摄像头 ===== 
- 
-视频通话时如果有前置摄像头,默认使用前置的,提供切换 API 切换到别的摄像头。 
- 
-<code java> 
-EMClient.getInstance().callManager().switchCamera();​ 
-</​code>​ 
- 
-===== 更多视频通话相关 API ===== 
- 
-视频通话相对复杂,把视频相关的一些 API 封装到了 EMVideoCallHelper 里。 
- 
-==== 获取 CallHelper ==== 
- 
-<code java> 
-EMVideoCallHelper callHelper = EMClient.getInstance().callManager().getVideoCallHelper();​ 
-</​code>​ 
- 
-==== 设置通话最大帧率 ==== 
- 
- ​设置通话最大帧率,SDK 最大支持(30),默认(20) 
- 
-<code java> 
-  EMClient.getInstance().callManager().getCallOptions().setMaxVideoFrameRate(30);​ 
-</​code>​ 
- 
-==== 设置图像分辨率 ==== 
- 
-设置视频通话分辨率 默认是(640,​ 480) 
- 
-<code java> 
-    EMClient.getInstance().callManager().getCallOptions().setVideoResolution(640,​ 480); 
-</​code>​ 
- 
-==== 设置视频比特率 ==== 
- 
-设置视频通话最大和最小比特率(可以不设置,SDK会根据手机分辨率和网络情况自动适配),最大值默认800, 最小值默认80 
- 
-<code java> 
- 
- ​EMClient.getInstance().callManager().getCallOptions().setMaxVideoKbps(800);​ 
- ​EMClient.getInstance().callManager().getCallOptions().setMinVideoKbps(80);​ 
- 
-</​code>​ 
- 
-==== 离线推送 ==== 
- 
-音视频呼叫对方,如果对方不在线,则发送一条离线消息通知对方(true推送,false不推送) 
- 
-<code java> 
- ​EMClient.getInstance().callManager().getCallOptions().setIsSendPushIfOffline(false);​ 
-</​code>​ 
- 
- 
-==== 音视频采样率 ==== 
- 
-设置音视频采样率,一般不需要设置,除非采集声音有问题才需要手动设置(默认值48000),根据自己硬件设备确定 
- 
-<code java> 
-EMClient.getInstance().callManager().getCallOptions().setAudioSampleRate(48000);​ 
-</​code>​ 
- 
-==== 设置音频源 ==== 
-设置音视频通话时音频源,​参数表示采集语音时所设置的音频源类型(这个一般只有在外接输入源时才需要设置),具体值参考 ''​MediaRecorder.AudioSource''​ 源码类,SDK 中默认值 VOICE_COMMUNICATION 
-<code java> 
-EMClient.getInstance().callManager().getCallOptions().setCallAudioSource(AudioSource.MIC);​ 
-</​code>​ 
- 
- 
- 
-详细文档请参考 [[im:​android:​sdk:​apidoc|Java Doc]]。 
- 
- 
----- 
-<WRAP group> 
-<WRAP half column> 
-上一页:[[im:​android:​basics:​chatroom|聊天室管理]] 
-</​WRAP>​ 
- 
-<WRAP half column> 
-下一页:[[im:​android:​basics:​multiuserconference|多人音视频会议]] 
-</​WRAP>​ 
-</​WRAP>​