video.nvue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <template>
  2. <view class="video_box" :style="'height:' + phoneHeight + 'px'">
  3. <!-- 本地预览视图 -->
  4. <view class="video_me" :style="'height:' + phoneHeight + 'px'">
  5. <zego-local-view v-if="videoShow" :viewMode="publisherViewModeIndex"
  6. style="width: 100%; flex: 1; border: 1px solid #0000; z-index: 20">
  7. </zego-local-view>
  8. </view>
  9. <!-- 服务器传来的预览图 -->
  10. <view class="video_you" v-if="allUserViewObjectList.length > 0" v-for="(item, index) in allUserViewObjectList" :key="item.userID">
  11. <zego-remote-view v-if="item.streamID" :streamID="item.streamID" :viewMode="item.viewMode"
  12. style="height: 403.84rpx; flex: 1;">
  13. </zego-remote-view>
  14. </view>
  15. <view class="video_btn">
  16. <view class="video_imgList">
  17. <view class="video_imgList1">
  18. <view class="video_view" @click="turn">
  19. <image class="video_view_img" src="../../static/image/9.png" mode=""></image>
  20. </view>
  21. <text class="video_view_txt">翻转镜头</text>
  22. </view>
  23. <view class="video_imgList2">
  24. <view class="video_view">
  25. <image class="video_view_img" src="../../static/image/8.png" mode=""></image>
  26. </view>
  27. <text class="video_view_txt">切换语音通话</text>
  28. </view>
  29. </view>
  30. <image @click="offVideo()" style="width: 50px; height: 50px; margin: 0 0 0 330rpx;"
  31. src="../../static/image/10.png" mode=""></image>
  32. </view>
  33. <!-- 消息提醒 -->
  34. <u-toast ref="uToast"></u-toast>
  35. </view>
  36. </template>
  37. <script>
  38. import permision from "@/zego-express-video-uniapp/permission.js";
  39. import ZegoExpressEngine from '@/zego-express-video-uniapp/lib/ZegoExpressEngine';
  40. import {
  41. ZegoScenario,
  42. ZegoRoomState,
  43. ZegoUpdateType,
  44. // ZegoViewMode
  45. } from '@/zego-express-video-uniapp/lib/ZegoExpressDefines'
  46. import {
  47. AppID,
  48. AppSign
  49. } from '@/zego-express-video-uniapp/KeyCenter.js'
  50. import ZegoLocalView from '@/zego-express-video-uniapp/zego-view/ZegoLocalView';
  51. import ZegoRemoteView from '@/zego-express-video-uniapp/zego-view/ZegoRemoteView';
  52. export default {
  53. data() {
  54. return {
  55. phoneHeight: '', // 获取当前的屏幕高度
  56. // 即构
  57. publisherViewModeIndex: 0, // 本地预览图
  58. viewModeA: 0, // 服务器预览图
  59. serveViewModeIndex: "", // 服务器拉流预览图
  60. engine: undefined,
  61. videoObj: null,
  62. userid: "Uni" + Math.floor(Math.random() * 1000000).toString(),
  63. isPublishingStream: false,
  64. shotShow: false, // 翻转镜头
  65. videoShow: true, // 切换视频显示
  66. allStreamList: [],
  67. allUserViewObjectList: [],
  68. }
  69. },
  70. components: {
  71. ZegoLocalView: ZegoLocalView,
  72. ZegoRemoteView: ZegoRemoteView
  73. },
  74. watch: {
  75. allUserViewObjectList(val) {
  76. if (val.length > 0) {
  77. val.forEach((item) => {
  78. if (item.streamID) {
  79. this.tensile(item)
  80. return true
  81. }
  82. })
  83. }
  84. }
  85. },
  86. methods: {
  87. // 即构 - 视频通话 初始化
  88. async setup() {
  89. var that = this
  90. // 创建引擎
  91. let profile = {
  92. appID: AppID,
  93. appSign: AppSign,
  94. scenario: ZegoScenario.General
  95. }
  96. this.engine = await ZegoExpressEngine.createEngineWithProfile(profile);
  97. this.engine.useFrontCamera(this.shotShow); // 设置前后摄像头
  98. // console.log(this.engine)
  99. this.addListeners();
  100. // console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + that.videoObj.room_id)
  101. this.engine.loginRoom(that.videoObj.room_id, {
  102. userID: that.videoObj.room_id,
  103. userName: that.videoObj.room_id
  104. }, {
  105. isUserStatusNotify: true
  106. });
  107. },
  108. // 即构 - 翻转镜头
  109. turn() {
  110. this.shotShow = !this.shotShow
  111. this.engine.useFrontCamera(this.shotShow)
  112. },
  113. // 切换视频显示
  114. changeShow() {
  115. this.videoShow = !this.videoShow
  116. // this.onPublish()
  117. this.engine.startPreview();
  118. this.engine.startPublishingStream(this.videoObj.room_id);
  119. this.publishBtnName = "Stop Publishing";
  120. console.log(this.videoShow)
  121. },
  122. // 即构 - 视频通话 监听房间
  123. addListeners() {
  124. // 房间状态变化通知
  125. this.engine.on("roomStateUpdate", (roomID, state, errorCode, extendedData) => {
  126. // console.log('房间状态变化')
  127. if (state == "CONNECTED") {
  128. // 与房间连接成功,只有当房间状态是连接成功时,才能进行推流、拉流等操作。
  129. // 接下来的“预览并推流”的代码写在这里
  130. console.log("房间连接成功");
  131. }
  132. if (state == "DISCONNECTED") {
  133. // 与房间断开了连接
  134. console.log("与房间断开连接");
  135. }
  136. if (state == "CONNECTING") {
  137. // 与房间尝试连接中
  138. console.log("与房间尝试连接中");
  139. }
  140. });
  141. // 房间用户变化通知
  142. this.engine.on("roomUserUpdate", (roomID, updateType, userList) => {
  143. console.log(updateType)
  144. console.log(userList)
  145. console.log("有其他用户进出房间");
  146. if (updateType == ZegoUpdateType.Add) {
  147. for (let user of userList) {
  148. for (let stream of this.allStreamList) {
  149. if (user.userID == stream.user.userID) {
  150. user.streamID = stream.streamID;
  151. }
  152. }
  153. this.allUserViewObjectList.push(user);
  154. }
  155. } else if (updateType == ZegoUpdateType.Delete) {
  156. this.allUserViewObjectList = this.allUserViewObjectList.filter((object) => {
  157. for (let user of userList) {
  158. if (user.userID == object.userID) {
  159. return false;
  160. }
  161. }
  162. return true;
  163. });
  164. }
  165. if (updateType == "1") {
  166. // 有其他用户退出房间
  167. this.offVideo()
  168. }
  169. });
  170. // 房间内其他用户推的流变化通知
  171. this.engine.on("roomStreamUpdate", (roomID, updateType, streamList) => {
  172. // if (updateType == "0") {
  173. // // 流新增,开始拉流
  174. // this.tensile(streamList[0].streamID)
  175. // } else if (updateType == "1") {
  176. // // 流删除,停止拉流
  177. // this.notTensile(streamList[0].streamID);
  178. // }
  179. console.log('---------updateType-----------', updateType)
  180. console.log('---------streamList-----------', streamList)
  181. console.log('---------ZegoUpdateType-----------', ZegoUpdateType)
  182. console.log('---------ZegoUpdateType.Add-----------', ZegoUpdateType.Add)
  183. console.log('---------ZegoUpdateType.Delete-----------', ZegoUpdateType.Delete)
  184. console.log('---------allUserViewObjectList-----------', this.allUserViewObjectList)
  185. if (updateType == ZegoUpdateType.Add) {
  186. for (let object of this.allUserViewObjectList) {
  187. for (let stream of streamList) {
  188. if (object.userID == stream.user.userID) {
  189. object.streamID = stream.streamID;
  190. }
  191. }
  192. }
  193. this.allStreamList = this.allStreamList.concat(streamList);
  194. } else if (updateType == ZegoUpdateType.Delete) {
  195. for (let object of this.allUserViewObjectList) {
  196. for (let stream of streamList) {
  197. if (object.streamID == stream.streamID) {
  198. object.streamID = undefined;
  199. }
  200. }
  201. }
  202. this.allStreamList = this.allStreamList.filter((object) => {
  203. for (let stream of streamList) {
  204. if (object.streamID == stream.streamID) {
  205. return false;
  206. }
  207. }
  208. return true;
  209. });
  210. }
  211. });
  212. // 房间内在线用户数量回调
  213. // this.engine.on("roomOnlineUserCountUpdate", (roomID, count) => {
  214. // // console.log(roomID)
  215. // console.log(count)
  216. // console.log('>?>>>>>>>>>>>>>>>>>>>>>>>在线用户有变化')
  217. // });
  218. // 拉流质量回调
  219. this.engine.on("playerQualityUpdate", (streamID, quality) => {
  220. console.log('拉流质量回调')
  221. });
  222. // 拉流后的事件回调
  223. this.engine.on("playerStateUpdate", (streamID, state, errorCode, extendedData) => {
  224. console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + '拉流后的事件触发了')
  225. })
  226. },
  227. // 拉流
  228. // tensile(roomId) {
  229. // console.log('拉流进入了啊')
  230. // console.log(roomId)
  231. // this.serveViewModeIndex = roomId
  232. // console.log(this.serveViewModeIndex)
  233. // this.engine.startPlayingStream(roomId);
  234. // },
  235. tensile(item) {
  236. console.log(this.allStreamList)
  237. console.log(item)
  238. console.log(this.allUserViewObjectList)
  239. this.engine.startPlayingStream(item.streamID)
  240. },
  241. // 停止拉流
  242. notTensile(roomId) {
  243. console.log(roomId)
  244. this.serveViewModeIndex = roomId
  245. console.log(this.serveViewModeIndex)
  246. this.engine.stopPlayingStream(roomId)
  247. },
  248. // 推流 - 展示视图 - 本地视频流
  249. onPublish() {
  250. // 设置视频配置
  251. // ZegoExpressEngine.instance().setVideoConfig(this.videoObj.room_id);
  252. if (this.isPublishingStream) {
  253. // 停止推流
  254. this.engine.stopPreview();
  255. this.engine.stopPublishingStream();
  256. this.publishBtnName = "Start Publishing";
  257. } else {
  258. // 开始推流
  259. this.engine.startPreview();
  260. this.engine.startPublishingStream(this.videoObj.room_id);
  261. this.publishBtnName = "Stop Publishing";
  262. }
  263. this.isPublishingStream = !this.isPublishingStream;
  264. },
  265. // 挂断退出
  266. offVideo() {
  267. console.log('进入了啊')
  268. this.engine.logoutRoom(this.videoObj.room_id)
  269. this.$refs.uToast.show({
  270. type: 'default',
  271. message: '结束视频通话!',
  272. })
  273. setTimeout(() => {
  274. uni.navigateBack({
  275. delta: 1
  276. })
  277. }, 1500)
  278. // uni.redirectTo({
  279. // url: "/pages/response/index"
  280. // })
  281. },
  282. },
  283. async onLoad(optinos) {
  284. var that = this
  285. that.videoObj = JSON.parse(optinos.videoObj)
  286. // console.log(that.videoObj)
  287. // 即构 - 视频通话
  288. // 获取系统信息同步接口
  289. if (uni.getSystemInfoSync().platform === 'android') {
  290. await permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
  291. await permision.requestAndroidPermission('android.permission.CAMERA');
  292. }
  293. await this.setup()
  294. this.onPublish(); // 推流
  295. uni.getSystemInfo({ //异步获取。
  296. success(res) {
  297. // that.phoneHeight = res.windowHeight - 13; //窗口高度
  298. that.phoneHeight = res.windowHeight; //窗口高度
  299. }
  300. });
  301. },
  302. // 监听页面返回
  303. onBackPress() {
  304. console.log('返回了!')
  305. },
  306. }
  307. </script>
  308. <style lang="scss">
  309. .video_box {
  310. background: #000;
  311. .video_you {
  312. border: 1px solid;
  313. background: #fff;
  314. width: 150px;
  315. height: 200px;
  316. position: absolute;
  317. right: 10px;
  318. top: 10px;
  319. overflow: hidden;
  320. }
  321. .video_me {
  322. z-index: 100;
  323. background: #000;
  324. position: relative;
  325. right: 0;
  326. top: 0;
  327. }
  328. .video_btn {
  329. position: absolute;
  330. bottom: 35rpx;
  331. left: 0;
  332. width: 750rpx;
  333. .video_imgList {
  334. display: flex;
  335. flex-direction: row;
  336. justify-content: space-around;
  337. // 翻转
  338. .video_imgList1 {
  339. .video_view {
  340. background: rgba(0, 0, 0, .5);
  341. border-radius: 50px;
  342. width: 50px;
  343. height: 50px;
  344. margin: 0 auto;
  345. .video_view_img {
  346. height: 25px;
  347. width: 25px;
  348. margin: 24rpx 0 0 25rpx;
  349. }
  350. }
  351. .video_view_txt {
  352. color: #fff;
  353. font-size: 14px;
  354. line-height: 30px;
  355. text-align: center;
  356. }
  357. }
  358. // 语音通话
  359. .video_imgList2 {
  360. .video_view {
  361. background: rgba(0, 0, 0, .5);
  362. border-radius: 50px;
  363. width: 50px;
  364. height: 50px;
  365. margin: 0 0 0 30rpx;
  366. .video_view_img {
  367. height: 25px;
  368. width: 25px;
  369. margin: 24rpx 0 0 25rpx;
  370. }
  371. }
  372. .video_view_txt {
  373. color: #fff;
  374. font-size: 14px;
  375. line-height: 30px;
  376. text-align: center;
  377. }
  378. }
  379. }
  380. }
  381. }
  382. </style>