让腾讯新闻飞起来 發表於 2025-2-24 14:40:00

如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)

<p>  现在使用Uni-app开发手机端APP已经变得很普遍,同一套代码就可以打包成Android App 和 iOS App,相比原生开发,可以节省客观的人力成本。那么如何使用Uni-app来开发视频聊天软件或视频会议软件了?本文将详细介绍在Uni-app中,如何基于OMCS来快速搭建视频聊天程序。</p>
<h2>一、准备工作</h2>
<p>1.在Uni-app项目的根目录下新建如下目录结构,用来存储Android和iOS原生插件。</p>
<p>&nbsp;<img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224142522346-1028947618.png" alt=""></p>
<p>2.插件目录说明</p>
<p>android:在插件android目录下新建libs目录,将OMCS原生插件中使用的OMCS非托管库及jar包放入该目录下。将OMCS原生插件arr包放入android目录下</p>
<p>&nbsp;<img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224142549775-477033007.png" alt=""></p>
<p>ios:将OMCS原生插件中使用的OMCSFramework.framework及OMCS原生插件OMCSPlugin.framework放到ios目录下</p>
<p>&nbsp;<img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224142602501-1600928272.png" alt=""></p>
<p>3.插件配置文件:nativeplugins根目录下新建package.json文件,详细配置说明及模版请参考uni官网uni小程序SDK</p>
<p>(1)修改package.json配置文件中插件的name及id为omcs-plugin</p>
<p>&nbsp;<img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224142629458-657798538.png" alt=""></p>
<p>(2)android插件配置</p>
<p>&nbsp;<img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224142644842-2014436729.png" alt=""></p>
<p>(3)ios插件配置</p>
<p>&nbsp;<img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224142717998-506049293.png" alt=""></p>
<p>4.在uni-app项目配置文件manifest.json中将OMCS原生插件加入项目中</p>
<p><strong>注意:修改配置后,需要重新打包app基座才能生效</strong></p>
<h2>&nbsp;二、正式开发</h2>
<p>首先,我们在uni-app项目中引入OMCS-Uni.js文件,然后在依照如下步骤操作。</p>
<p>1.构造并初始化OMCS多媒体设备管理器。如果要设置一些配置参数,可以在调用初始化方法之前通过设置 multimediaManager 的相关属性来完成。</p>
<div class="cnblogs_code">
<pre>const multimediaManager =<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"> MultimediaManagerFactory</span>.GetSingleton();
multimediaManager.initialize(
    </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.userID,
    </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.password,
    </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.serverIP,
    </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.serverPort,
    (res)</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(res == 'OMCS登录成功' || res == '登录成功'<span style="color: rgba(0, 0, 0, 1)">){}
    }
);</span></pre>
</div>
<p>2.本demo中,我们定义了一个简单的客户端home页面:home.vue ,用于展示OMCS提供的各个功能。在home页面的onLoad方法中,我们请求了手机的音视频权限:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">onLoad(options) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.query =<span style="color: rgba(0, 0, 0, 1)"> options;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.loginId = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.loginid;
    MultimediaManagerFactory.GetSingleton().checkPermission();
},</span></pre>
</div>
<p>home页界面如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224143003055-477766691.png" alt="" width="477" height="356"></p>
<p>页面上的各个按钮,用于演示OMCS提供的各个多媒体连接器的功能。我们以视讯功能为例,当摄像头和话筒的checkbox都勾选上时,表示连接到目标用户的摄像头和麦克风设备。点击“语音视频”按钮,将跳转至video页面:</p>
<p><img src="https://img2024.cnblogs.com/blog/9005/202502/9005-20250224143122758-1850782505.png" alt=""></p>
<p><strong>注意:必须勾选摄像头,并进入video页面后(此时将看到自己摄像头的预览画面),其他人才可以连接到自己的摄像头。</strong></p>
<p>3.开始连接</p>
<p>(1)当点击【开始连接对方】按钮时,将连接到对方摄像头和麦克风</p>
<p>(2)我们封装了一个组件<strong>UniCameraPanel.nvue</strong>,其中使用了OMCS原生控件<strong>OMCSSurfaceView</strong>作为存放对方视频图像的容器,OMCS原生控件<strong>CameraSurfaceView</strong>作为存放自己视频预览的容器:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">&lt;template&gt;
    &lt;CameraSurfaceView
      ref="camera_self_panel_view"
      v-if="isSelf"
      class="selfVideoView"
      &gt;&lt;/CameraSurfaceView&gt;
    &lt;OMCSSurfaceView
      ref="camera_other_panel_view"
      v-if="!isSelf"
      class="otherVideoView"
      &gt;&lt;/OMCSSurfaceView&gt;
&lt;/template&gt;</span></pre>
</div>
<p>(3)video页面使用了<strong>UniCameraPanel.nvue</strong>控件,根据<strong>isSelf</strong>属性判断是否为自己预览的摄像头:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">&lt;div class="otherView" v-if="isVideo"@click.stop="changeShowIcon"&gt;
    &lt;UniCameraPanelVue
      :isSelf="false"
      ref="otherCameraPanel"
      class="otherVideoView"
    &gt;&lt;/UniCameraPanelVue&gt;
&lt;/div&gt;
&lt;div class="selfView"v-if="isVideo" &gt;
    &lt;UniCameraPanelVue
      :isSelf="true"
      ref="selfVideoView"
      class="selfVideoView"
    &gt;&lt;/UniCameraPanelVue&gt;
&lt;/div&gt;</span></pre>
</div>
<p><strong>注意:video页面必须为nvue页面才能使用UniCameraPanel.nvue控件</strong></p>
<p>(4)在video页面OnLoad初始化方法中,我们分别定义了CameraConnector和MicrophoneConnector连接器用于连接目标用户的摄像头和话筒,并通过setConnectorEventListener预定了CameraConnector和MicrophoneConnector的连接结束事件和连接断开事件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">onLoad(options) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.query =<span style="color: rgba(0, 0, 0, 1)"> options;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.othername = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.destUserID;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.username;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.isAndroid = uni.getSystemInfoSync().platform == 'android'<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.isVideo = Boolean(Number(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.openCamera));
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.isVideo){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.cameraConnector = <span style="color: rgba(0, 0, 255, 1)">new</span> CameraConnector(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.destUserID);
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.setConnectorEventListener(
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.CameraConnector_ConnectEnded,
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.CameraConnector_DisConnected
      );
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.setVideoDrawMode(VideoDrawMode.Scale);
    };
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Boolean(Number(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.openMic))){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.microphoneConnector = <span style="color: rgba(0, 0, 255, 1)">new</span> MicrophoneConnector(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.destUserID);
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.microphoneConnector.setConnectorEventListener(
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.MicrophoneConnector_ConnectEnded,
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.MicrophoneConnector_DisConnected
      );
    };
}</span></pre>
</div>
<p><strong>注意:CameraConnector连接器需要在OnLoad初始化时创建</strong></p>
<p>(5)在video页面【开始连接对方】按钮点击事件中调用了CameraConnector和MicrophoneConnector连接器的beginConnect方法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">contentOtherBtnClick(){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Boolean(Number(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.openCamera))){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.beginConnect();
    };
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Boolean(Number(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.query.openMic))){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.microphoneConnector.beginConnect();
    };
}</span></pre>
</div>
<p>注意:</p>
<p><strong>在调用CameraConnector连接器的beginConnect方法之前需要执行UniCameraPanel控件的SetVideo方法:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">SetVideo(_cameraConnector){
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(_cameraConnector){
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.isSelf){
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.$refs.camera_self_panel_view.setVideo();
            }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
                </span><span style="color: rgba(0, 0, 255, 1)">this</span>.cameraConnector =<span style="color: rgba(0, 0, 0, 1)"> _cameraConnector;
                const userID </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.destUserID;
                </span><span style="color: rgba(0, 0, 255, 1)">this</span>.videoDrawMode = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.videoDrawMode;
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.$refs.camera_other_panel_view.setVideo({destUserID:userID});
            }
      }
    }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)">(e){
      console.log(e)
    }
}</span></pre>
</div>
<p>4.当退出video页面或者主动断开连接时,需要调用CameraConnector连接器和MicrophoneConnector连接器的<strong>disconnect</strong>方法,并且通过<strong>removeConnectorEventListener</strong>方法取消预定的事件,最后还需要调用多媒体管理器的closeCamera方法断开自己的预览摄像头</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">closeVideo(){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.disconnect();
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cameraConnector.removeConnectorEventListener();
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.cameraConnector = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.microphoneConnector){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.microphoneConnector.disconnect();
      </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.microphoneConnector.removeConnectorEventListener();
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.microphoneConnector = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.isShowVideo = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
    MultimediaManagerFactory.GetSingleton().closeCamera();
},</span></pre>
</div>
<h2>三、源码下载</h2>
<p>该Demo的源码下载地址如下:OMCS.UniappDemo.rar (Android、iOS)</p>
<p>至于服务端,我们已经打包好了exe文件,可以下载后直接双击运行:</p>
<p>OMCS 服务端可执行程序(解压后,双击exe即可运行)</p>
<p>Uniapp版本的Demo还可以与PC版本(Windows、银河麒麟、统信UOS)的Demo进行音视频通话,PC版可以转到此处下载。<br><br></p><br><br>
来源:https://www.cnblogs.com/zhuweisky/p/18734018
頁: [1]
查看完整版本: 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)