P2P双向视频通话SDK使用说明
简介
P2P双向视频通话SDK是由深圳市穿透科技有限公司(以下简称穿透科技)开发软件SDK。可以实现一对多视频直播(单向)和一对一视频对讲(双向)。
产品特点
- 支持音视频通过P2P的方式传输。
- 支持多种视频分辨率。
- 支持H264,H265等视频传输格式。
- 支持PCM的音频传输格式。
应用场景
- 视频通话:可实现类似微信一样的一对一或多人视频通话。
- 视频直播:一对多视频直播和音频会议。
产品规格
规格项 | 规格说明 | |
功能规格 | 回音消除 | 对讲时消除减轻音频回音,使音频更清晰 |
硬件加速 | 使用GPU等硬件来进行视频编解码、合成的加速 | |
H.264 | 应用最广的高性能视频编码器 | |
H.265 | 更高压缩比、更节省带宽的视频编码器 | |
参数规格 | 最大采集分辨率 | 可设置,不建议超过1080P |
最大传输分辨率 | 可设置,不建议超过1080P | |
最大码率 | 可设置,不建议过大 | |
最大帧率 | 可设置,不建议超过30fps |
平台兼容性
规格/平台/ 功能规格 | Android | iOS | Web |
回音消除 | ✓ | ✓ | ✓ |
硬件加速 | ✓ | ✓ | – |
H.264编码 | ✓ | ✓ | ✓ |
H.265编码 | ✓ | ✓ | ✓ |
与P2P视频直播SDK、P2P会议SDK的区别
P2P视频双向对讲SDK具有P2P直播SDK的全部功能:
采集端采集视频,可以被多个播放端同时播放。
播放端也可以采集视频,只能传输给采集端播放。
P2P直播SDK,采集端采集的视频可以被多个播放端同时播放,视频流是单向的。
(图2)直播模块SDK视频流向图
P2P会议模块视频流向,会议SDK视频流是双向的,两两个节点之间都可以相互打开视频。
准备工作
准备工作
P2P双向视频对讲SDK基于P2P视频直播SDK,都基于穿透科技Peergine中间件开发,所以最好可以了解Peergine中间件的节点对象、组对象和音视频对象。
其次需要数据P2P视频直播的API和编程方式。了解异步编程。P2PSDK都是使用异步的方式调用和反馈。反馈是通过注册总的回调实现的。
使用流程图
术语说明
ExtVideo:是指P2P视频对讲扩展模块,也只实现这个功能的Java类ExtVide.java;
采集端:是指P2P直播模块中负责采集视频的设备和程序;(DemoCaptureMulti)
播放端:是指P2P直播模块中负责播放视频的设备和程序;(DemoRenderMulti)
设备端:一般指特殊设备,集成了直播模块采集端的设备;
手机端:一般指手机设备,集成了直播模块播放端的设备。
Demo使用
使用流程
- 1) 安装运行: 安卓可以直接安装DemoApp文件夹下的APK,IOS需要用XCODE打开工程编译安装。
- 2)登录进入主界面:采集端输入穿透科技分配的ID,播放端可输入任意字符串作为ID即可登录,播放端ID建议不要使用和别人相同的ID。
- 3)管理对端列表:可以添加删除对端ID列表,播放端添加采集端ID,采集端添加播放端ID。
- 4)呼叫:点击显示的ID进入呼叫界面。
- 5)对讲:呼叫对端后对端如果在主界面会弹出对话框是否接受对讲,点击接受后进入对讲界面。
- 6)挂断:点击挂断按钮就能挂断对讲。退回主界面。
Demo程序流程结构

前提条件
ANDROID
请确保满足以下开发环境要求:
- Android SDK API Level Level ≥ 15
- Android Studio 3.0 或以上版本
- App 要求 Android 4.1 或以上设备
IOS
请确保满足以下开发环境要求:
- Xcode 10.0+
- iOS 8.0+ 真机(iPhone 或 iPad)
- 请确保您的项目已设置有效的开发者签名
WebHtml5
请确保满足以下开发环境要求:
- 操作系统: Microsoft Windows 7+
- 安装Chrome 75+浏览器
- 安装 pgHtml5Bridge 后台服务插件
- 确保部署环境为localhost或http协议
添加SDK
ANDROID
- 下载 Android SDK
- Import Module 导入安卓支持库: ExtVideo、livemulti、pgPluginLib,并添加到你的工程Module的依赖中
- 后期升级是替换
ExtVideo、livemulti、pgPluginLib 中的java、jar、so等文件。 - 配置环境AndroidManifest.xml 添加下列代码:
1 2 3 4 5 6 7 |
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> |
build.gradle添加下列代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
apply plugin: 'com.android.application' android { … defaultConfig { … ndk { //选择要添加的对应 cpu 类型的 .so 库。 //如果包含其他第三方库,请保证选择的架构的SO是所有第三方都具备的 //armeabi文件夹下的SO可以拷贝到armeabi-v7a abiFilters 'armeabi', 'arm64-v8a' // 还可以添加 'x86', 'x86_64', 'mips', 'mips64' } … } … } dependencies { … implementation project(':pgPluginLib') implementation project(':ExtVideo') implementation project(':livemulti') … } |
现在你已经设置好了 Android Studio 开发环境,可以开始使用 Android SDK 了!
IOS
- 下载 IOS SDK,解压并打开。
- 将文件夹 ExtVideo拷贝到创建的工程。
- 将文件夹
pgDybLiveMulti_device.framework、
pgDybLiveMulti.framework 、
pgDybLiveMulti_simulator.framework 拷贝并添加
pgDybLiveMulti.framework 到工程依赖。 -
pgDybLiveMulti_device.framework:包含arm和arm64架构,老版有这个framework,新版已经删除,改名为 pgDybLiveMulti.framework ;
pgDybLiveMulti_simulator.framework :最新SDK带的framework,其中包含arm和arm64以及x86-64架构,用于模拟器调试;即需要发布到App Store时将pgDybLiveMulti_device.framework改名为 pgDybLiveMulti.framework ,需要模拟器调试时 pgDybLiveMulti_simulator.framework 改名为 pgDybLiveMulti.framework - 后期升级可以替换ExtVideo中的.mm文件和替换*.framework
- 在BuildSetting的Other Link Flags参数中增加:-liconv -lz -lresolv链接选项。
- 禁止使用bitcode
- 工程中引用
ExtVideo 文件夹下的所有源文件。 - 添加一系列的系统framework
CoreVideo.framework |
CoreAudioKit.framework |
UIKit.framework |
AdSupport.framework |
CoreGraphics.framework |
CoreMedia.framework |
AVFoundation.framework |
AudioToolbox.framework |
现在你已经设置好了 XCode 开发环境,可以开始使用 IOS SDK 了!
Web HTML5
- 下载 Web HTML5 SDK,解压并打开。
- 拷贝并引用 js/pgLibExtVideo.js
- 拷贝并引用 js/pgLibLive*.js 相关文件
- 拷贝并引用 js /pgHtml5Bridge.js
- 安装SDK包中附带的pgHtml5Bridge服务程序
- 后期升级时需要安装最新的
pgHtml5Bridge 以及替换相关的js文件
现在你已经设置好了 Web开发环境,可以开始使用Web HTML5 SDK 了!
调试指南和常见问题
- 直播模块详细文档在pgLiveDoc目录下,ExtVideoAPI详细介绍在ExtVideojavaApiDoc目录下。ExtVideo是开源代码,API功能和参数说明以代码注释为准。
- 初始化失败,检查是否添加了网络权限,检查是否导入并implementation集成了Module pgPluginLib。
- 上报常见登录错误:
错误码12,一般是网络连接失败,超时,请检查网络环境问题。
错误码8,请输入正确的ID。输入已经注册的ID。
- 关于预览或者音频有时不能打开的问题。
预览不能打开最可能是是没有打开摄像头的权限,请先检查摄像头权限是否给了Demo。
音频不能打开,或者某一端没有声音,先检查没有声音的对端的Demo是否有录音权限。
- 关于对讲的播放端预览打开了,但是采集端看不到播放端视频的情况可能的问题及处理办法。
- 可1:是没有点击获取按钮并进行确认,这种情况下是某种通道没有建立,所以按对讲后不能进行视频对讲。
- 可能2:有多个相同的ID的播放端,因为历史原因,直播模块的播放端初始化ID和内部的实际ID是不同的。所以通过初始化ID查找,可能会找到多个播放端。于是可能在“获取”过程中,后响应的播放端的视频通道会覆盖前面的通道,导致播放端视频不能传到采集端。
- 可能3: 播放端没有摄像头权限,表现为播放端预览是黑屏状态。
- 为什么使用connect.peergine.com:7781 的服务器可以正常双向对讲,使用自建P2P服务器地址只能单向对讲,不能双向对讲?
是因为直播双向对讲模块需要依赖一个服务器转发消息的插件,请联系穿透科技工程是帮助安装。
进阶教程
怎样修改播放端到采集端视频的分辨率?
在P2P SDK中分辨率由视频参数Mode表示,我们定义的常用视频分辨率Mode分别是:

所以我们要修改ExtVideo的分辨率,需要注意的是ExtVideo两端都要修改成一致才能生效:


ExtVideoAPI说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
API 接口: /** * 获取版本号 * * @return Version */ public String version() /** * 获取Ext模块的钩子函数 * * @return 钩子对象 */ public Object getHook() /** * 设置Event */ public void setOnEvent(OnEvent event) /** * 采集端初始化 * * @param node node对象 * @param sObjSelf 本节点对象名 * @param sVideoParam 视频参数 * @param sAudioParam 音频参数 * @return View对象,采集端返回播放端视频播放View,播放端返回预览View */ public int initialize(pgLibJNINode node, String sObjSelf, String sVideoParam, String sAudioParam) /** * 清理退出 */ public void clean() /** * 获取预览Surface ,某些模块自身没有预览,比如直播模块的播放端,就需要通过这个获取预览。 * * @param iW 宽 * @param iH 高 * @return 预览Surface */ public SurfaceView getPrewview(int iW, int iH) /** * 删除预览 */ public void delPrewview() /** * 发送获取ID的完整对象名的消息 * * @param sPeer 对端ID 或者节点对象objpeer * @param sParam 自定义参数 * @return 错误码 */ public int sendGetObjPeer(String sPeer, String sParam) /** * 发送自身对象名称到ID所示的节点 * * @param sPeer 对端ID 或者节点对象objpeer * @param sParam 自定义参数 * @return 错误码 */ public int sendGetObjPeerNotify(String sPeer, String sParam) /** * 播放端有效,和播放端的 API Start同时调用。 * * @param sObjPeer 采集端ID * @return 错误码 */ public int start(String sObjPeer) /** * 停止 */ public void stop(String sObjPeer) /** * 打开预览 * * @return 错误码 */ private int prvwStart() /** * 关闭预览 */ private void prvwStop() /** * 打开视频 * * @param sObjPeer 视频发送端节点名称 * @param peerView 显示对端视频的SurfaceView * @param bPrvw 是否打开预览 * @return 错误码 */ public int videoStart(String sObjPeer, SurfaceView peerView, boolean bPrvw) /** * 回复视频请求 * * @param sObjV 节点对象名, * @param uErrCode 0 同意,>0 错误码。 * @param uHandle 视频句柄 * @param sObjPeer 节点名称,传入onVideoStart 回调的sObjPeer的值 * @param peerView 显示对端的视频的View * @param bPrvw 是否打开预览 * @return 错误码 */ public int videoHandle(String sObjV, int uErrCode, int uHandle, String sObjPeer, SurfaceView peerView, boolean bPrvw) /** * 关闭视频。 */ public void videoStop(String sObjPeer, boolean bPrvw) /** * 动态修改摄像头部分参数 * @param sParam 示例"(Portraiti){0}(CameraNo){"+ iCameraNo + "}" * @return 错误码 */ public int videoSource(String sParam) 回调接口: public interface OnEvent { /** * 对端调用sendObjPeer产生的事件 * * @param sObjPeer 对端的节点对象名 * @param sParam sendObjPeer 传入的参数,保留参数 */ void onGetObjPeer(String sObjPeer, String sParam); /** * 调用sendObjPeer后产生的服务器回复结果事件 * @param uErr 错误码 * @param sParam 自定义参数 */ void onGetObjPeerReply(int uErr, String sParam); /** * 接收sendObjPeerNotify 发送的对端的节点对象的值。 * @param sObjPeer 节点对象名 * @param sParam 自定义参数 */ void onGetObjPeerNotify(String sObjPeer, String sParam); /** * Video 对象同步 * @param sObj 对象名称 * @param sAct 0 是同步,1是去同步 * @param sObjPeer 节点对象名称 * @return 错误码 正常返回PG_ERR_Normal */ int onVideoSync(String sObj, String sAct, String sObjPeer); /** * 收到视频请求 * @param sObj 视频对象 * @param uHandle 视频请求句柄 * @param sObjPeer 对端的对象名称 * @return 错误码 @link pgLibError, -1表示异步调用videoHandle 应答。 正常 返回PG_ERR_Normal */ int onVideoStart(String sObj, int uHandle, String sObjPeer); /** * 收到videoStart视频请求的结果。 * @param sObj 视频对象名称 * @param uErr 错误码, PG_ERR_Normal 表示打开成功 * @return 错误码,正常返回 PG_ERR_Normal */ int onVideoStartReply(String sObj, int uErr); /** * 收到视频结束通知 * @param sObj 视频对象名称 * @param sObjPeer 对端节点对象名称 * @return 错误码 ,正常返回 PG_ERR_Normal */ int onVideoStop(String sObj, String sObjPeer); /** * 视频传输状态 * @param sObj 对象名称 * @param sInfo 进度状态信息 */ void onVideoFrameStat(String sObj, String sInfo); /** * 音频对象同步 * @param sObj 对象名称 * @param sAct 1同步,0 去同步 */ int onAudioSync(String sObj, String sAct); /** * 音频对象 请求打开音频 * @param sObj 音频对象名称 * @param sObjPeer 对端对象名称 * @return 错误码 */ int onAudioStart(String sObj, String sObjPeer); /** * 音频打开请求结果 * @param sObj 音频对象名称 * @param uErr 错误码 * @return 返回错误码 */ int onAudioStartRelay(String sObj, int uErr); /** * 音频已经被关闭 * @param sObjPeer 节点对象名称 * @return 错误码 */ int onAudioStop(String sObjPeer); } |