detailmetting.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <template>
  2. <div id="detailmetting">
  3. <el-row>
  4. <el-col :span="24" class="info">
  5. <el-col :span="4" class="left">
  6. <el-col :span="24" class="leftTop">
  7. <el-image :src="roomInfo.filedir"></el-image>
  8. <p>{{ roomInfo.title }}</p>
  9. <p>{{ roomInfo.content }}</p>
  10. </el-col>
  11. <el-col :span="24" class="leftDown">
  12. <el-col :span="8" class="btn" @click.native="shexiangBtn()">
  13. <i class="iconfont iconshexiangtou"></i>
  14. <p>摄像头</p>
  15. </el-col>
  16. <el-col :span="8" class="btn" @click.native="tianchongBtn()">
  17. <i class="iconfont iconmaikefeng-tianchong"></i>
  18. <p>麦克风</p>
  19. </el-col>
  20. </el-col>
  21. </el-col>
  22. <el-col :span="20" class="right">
  23. <el-col :span="24" class="rightTop">
  24. <span @click="liveon"><i class="iconfont iconshexiangtou"></i>摄像头</span>
  25. <span @click="liveclose">关闭</span>
  26. </el-col>
  27. <el-col :span="2" class="noVideo"> </el-col>
  28. <el-col :span="20" class="video">
  29. <el-col :span="24" class="videoMeet">
  30. <el-col :span="18" class="one">
  31. <div id="main-video" class="video-box col-div" style="justify-content: flex-end"></div>
  32. </el-col>
  33. <el-col :span="6" class="two">
  34. <el-col :span="24" class="twoOne">
  35. <div id="look-video-1" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  36. </el-col>
  37. <el-col :span="24" class="twoOne">
  38. <div id="look-video-2" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  39. </el-col>
  40. <el-col :span="24" class="twoOne">
  41. <div id="look-video-3" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  42. </el-col>
  43. </el-col>
  44. <el-col :span="6" class="three">
  45. <div id="look-video-4" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  46. </el-col>
  47. <el-col :span="6" class="three">
  48. <div id="look-video-5" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  49. </el-col>
  50. <el-col :span="6" class="three">
  51. <div id="look-video-6" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  52. </el-col>
  53. <el-col :span="6" class="three">
  54. <div id="look-video-7" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  55. </el-col>
  56. </el-col>
  57. </el-col>
  58. <el-col :span="2" class="noVideo"> </el-col>
  59. <el-col :span="24" class="rightDown"> <!-- 开始直播 --> </el-col>
  60. </el-col>
  61. </el-col>
  62. </el-row>
  63. <el-dialog title="摄像头" :visible.sync="shexiangDia" width="30%" :before-close="handleClose">
  64. <el-select @change="cameraChange" v-model="cameraId" filterable placeholder="请选择摄像头">
  65. <el-option v-for="item in cameras" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
  66. </el-select>
  67. </el-dialog>
  68. <el-dialog title="麦克风" :visible.sync="tianchongDia" width="30%" :before-close="handleClose">
  69. <el-select @change="micrChange" v-model="microphoneId" filterable placeholder="请选择麦克风">
  70. <el-option v-for="item in microphones" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
  71. </el-select>
  72. </el-dialog>
  73. </div>
  74. </template>
  75. <script>
  76. import { mapState, createNamespacedHelpers } from 'vuex';
  77. const { mapActions: gensign } = createNamespacedHelpers('gensign');
  78. import TRTC from 'trtc-js-sdk';
  79. export default {
  80. name: 'detailmetting',
  81. props: {
  82. roomInfo: null,
  83. },
  84. components: {},
  85. data: function() {
  86. return {
  87. // 摄像头
  88. shexiangDia: false,
  89. cameraId: '',
  90. cameras: [],
  91. // 麦克风
  92. tianchongDia: false,
  93. microphoneId: '',
  94. microphones: [],
  95. client_: '',
  96. localStream_: '',
  97. sdkAppId_: '1400380125',
  98. userId_: '1111',
  99. open_: false,
  100. };
  101. },
  102. created() {
  103. this.initclient();
  104. this.getDevices();
  105. },
  106. methods: {
  107. ...gensign(['gensignFetch']),
  108. async getDevices() {
  109. this.cameras = await TRTC.getCameras();
  110. this.microphones = await TRTC.getMicrophones();
  111. },
  112. async initclient() {
  113. console.log(this.user.uid);
  114. this.userId_ = this.user.uid;
  115. const res = await this.gensignFetch({ userid: this.userId_ });
  116. if (this.$checkRes(res)) {
  117. console.log(res.data);
  118. this.client_ = TRTC.createClient({
  119. mode: 'live',
  120. sdkAppId: this.sdkAppId_,
  121. userId: this.userId_,
  122. userSig: res.data,
  123. });
  124. }
  125. },
  126. async liveon() {
  127. this.open_ = true;
  128. console.log('8888--' + this.userId_);
  129. if (this.cameraId === '' || this.microphoneId === '') {
  130. this.$message({
  131. message: '请选择摄像头和麦克风',
  132. type: 'warning',
  133. });
  134. return;
  135. }
  136. await this.client_.join({ roomId: this.name, role: 'anchor' });
  137. this.localStream_ = await TRTC.createStream({
  138. audio: true,
  139. video: true,
  140. cameraId: this.cameraId,
  141. microphoneId: this.microphoneId,
  142. userId: this.userId_,
  143. });
  144. this.localStream_.setVideoProfile('480p');
  145. await this.localStream_.initialize();
  146. console.log('initialize local stream success');
  147. // publish the local stream
  148. await this.client_.publish(this.localStream_);
  149. this.localStream_.play('main-video');
  150. //$('#mask_main').appendTo($('#player_' + this.localStream_.getId()));
  151. // 订阅其他用户音视频
  152. let i = 0;
  153. this.client_.on('stream-subscribed', event => {
  154. const remoteStream = event.stream;
  155. // 远端流订阅成功,播放远端音视频流
  156. console.log('111' + remoteStream.getType());
  157. i = i + 1;
  158. if (i < 8) {
  159. const id_ = 'look-video-' + i;
  160. remoteStream.play(id_);
  161. }
  162. });
  163. // 监听远端流增加事件
  164. this.client_.on('stream-added', event => {
  165. const remoteStream = event.stream;
  166. console.log('222' + remoteStream.getType());
  167. // 订阅远端音频和视频流
  168. this.client_.subscribe(remoteStream, { audio: true, video: true }).catch(e => {
  169. console.error('failed to subscribe remoteStream');
  170. });
  171. });
  172. },
  173. async liveclose() {
  174. // 关闭视频通话
  175. console.log(this.open_);
  176. if (this.open_) {
  177. const videoTrack = this.localStream_.getVideoTrack();
  178. if (videoTrack) {
  179. this.localStream_.removeTrack(videoTrack).then(() => {
  180. console.log('remove video call success');
  181. // 关闭摄像头
  182. videoTrack.stop();
  183. this.client_.unpublish(this.localStream_).then(() => {
  184. // 取消发布本地流成功
  185. });
  186. });
  187. }
  188. }
  189. },
  190. async cameraChange() {
  191. //await this.localStream_.switchDevice('video', this.cameraId);
  192. },
  193. async micrChange() {
  194. //await this.localStream_.switchDevice('audio', this.microphoneId);
  195. },
  196. // 选择打开摄像头
  197. shexiangBtn() {
  198. this.shexiangDia = true;
  199. },
  200. // 选择打开麦克风
  201. tianchongBtn() {
  202. this.tianchongDia = true;
  203. },
  204. // 关闭摄像头&麦克风
  205. handleClose(done) {
  206. done();
  207. },
  208. },
  209. computed: {
  210. ...mapState(['user']),
  211. id() {
  212. return this.$route.query.id;
  213. },
  214. name() {
  215. return this.$route.query.name;
  216. },
  217. pageTitle() {
  218. return `${this.$route.meta.title}`;
  219. },
  220. },
  221. metaInfo() {
  222. return { title: this.$route.meta.title };
  223. },
  224. };
  225. </script>
  226. <style lang="less" scoped>
  227. .info {
  228. background-color: #2a2b30;
  229. min-height: 840px;
  230. .left {
  231. .leftTop {
  232. min-height: 540px;
  233. padding: 0 15px;
  234. margin: 20px 0;
  235. p {
  236. color: #ccc;
  237. }
  238. p:nth-child(2) {
  239. padding: 10px 0;
  240. }
  241. p:nth-child(3) {
  242. line-height: 25px;
  243. }
  244. }
  245. .leftDown {
  246. padding: 10px 0 0 0;
  247. border-top: 1px solid #000;
  248. .btn {
  249. margin: 0 0 15px 0;
  250. color: #cccccc;
  251. text-align: center;
  252. }
  253. .btn:hover {
  254. cursor: pointer;
  255. }
  256. }
  257. }
  258. .right {
  259. .rightTop {
  260. height: 100px;
  261. background-color: #232428;
  262. text-align: right;
  263. color: #ccc;
  264. line-height: 100px;
  265. span {
  266. margin: 0 10px 0 0;
  267. }
  268. span:hover {
  269. cursor: pointer;
  270. color: #409eff;
  271. }
  272. }
  273. .video {
  274. min-height: 640px;
  275. background-color: #000;
  276. overflow: hidden;
  277. position: relative;
  278. .videoMeet {
  279. .one {
  280. height: 480px;
  281. overflow: hidden;
  282. }
  283. .two {
  284. height: 480px;
  285. overflow: hidden;
  286. .twoOne {
  287. height: 160px;
  288. overflow: hidden;
  289. }
  290. }
  291. .three {
  292. height: 160px;
  293. overflow: hidden;
  294. }
  295. }
  296. }
  297. .noVideo {
  298. min-height: 640px;
  299. background-color: #151618;
  300. }
  301. .rightDown {
  302. height: 100px;
  303. background-color: #232428;
  304. }
  305. }
  306. }
  307. /deep/.el-dialog__body {
  308. min-height: 100px;
  309. }
  310. #main-video {
  311. width: 100%;
  312. height: 480px;
  313. min-height: 480px;
  314. grid-area: 1/1/3/4;
  315. }
  316. .lookvideo {
  317. width: 100%;
  318. height: 160px;
  319. min-height: 160px;
  320. grid-area: 1/1/3/4;
  321. }
  322. </style>