赞
踩
1. 接入腾讯云 - 直接在mounted里引入createClient方法就可以了
- <template>
- <!-- 视频会诊 -->
- <div class="videoCon">
- <div class="topBar">
- <el-form
- :inline="true"
- :model="formInline"
- class="demo-form-inline"
- :label-position="labelPosition"
- label-width="100px"
- >
- <el-form-item label="申请医生:">
- <el-input v-model="formInline.doctor" size="mini"></el-input>
- </el-form-item>
- <el-form-item label="手机号:">
- <el-input v-model="formInline.phone" size="mini"></el-input>
- </el-form-item>
- <el-form-item label="请求时间:">
- <el-input v-model="formInline.time" size="mini"></el-input>
- </el-form-item>
- <el-form-item label="申请医院:">
- <el-input v-model="formInline.hospital" size="mini"></el-input>
- </el-form-item>
- </el-form>
- <div class="rightBox">
- <div class="recording">
- <i></i>
- <span>录制中 :</span>
- <span>1:20:02</span>
- </div>
- <el-button type="primary" @click="signOut">退出</el-button>
- </div>
- </div>
- <div class="main">
- <div class="video">
- <div class="bigScreen">
- <span class="iconfont iconicon-03-17"></span>
-
- </div>
- <div style="width: 22px"></div>
- <div class="smallScreem">
- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- <div class="center-page">
- <div v-html="remoteStream"
- :class="remoteStream?'distant-stream':''">
- </div>
- </div>
- </div>
- <!-- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-16"></span>
- <span class="iconfont iconicon-03-17"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-16"></span>
- <span class="iconfont iconicon-03-17"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- </div>
- <div>
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16"></span>
- </div> -->
- <div style="marginTop: 10px;">
- <span class="iconfont iconicon-03-17"></span>
- <span class="iconfont iconicon-03-16" @click="snapshot"></span>
- <div id='local_stream'
- class="local-stream">
- </div>
- </div>
- </div>
- </div>
- <div class="operation">
- <div>
- <span class="iconfont iconicon-03-31"></span>
- <p>控制</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-30"></span>
- <p>测量</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-42"></span>
- <p>注释</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-34"></span>
- <p>截图</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-32"></span>
- <p>截图附件</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-33"></span>
- <p>患者查看详情</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-15"></span>
- <p>邀请</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-29"></span>
- <p>聊天</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-28"></span>
- <p>声音</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-14"></span>
- <p>麦克风</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-10"></span>
- <p>视频</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-18"></span>
- <p>录制</p>
- </div>
- </div>
- </div>
-
-
- <img src="" alt="" ref="picture">
- </div>
- </template>
-
- <script>
- // 一定要引入这个-去下个demo里面就有
- import LibGenerateTestUserSig from '@/utils/lib-generate-test-usersig.min';
-
- import TRTC from 'trtc-js-sdk';
- export default {
- data() {
- return {
- formInline: {
- doctor: "",
- phone: "",
- time: "",
- hospital: "",
- },
- labelPosition: "right",
-
-
- userId: 'user_' + parseInt(Math.random() * 100000000),//用户id --可更改
- roomId: 88888,//房间号--加入相同房间才能聊
- client: '',//客户端服务
- remoteStream: '',//远方播放流
- localStream: '',//本地流
- };
- },
- methods: {
- // 退出
- signOut() {
- Bus.$emit('code', "true");
- this.$router.go(-1);
- },
- //创建链接
- createClient (userId) {
- //获取签名
- const config = this.genTestUserSig(userId);
- const sdkAppId = config.sdkAppId;
- const userSig = config.userSig;
- this.client = TRTC.createClient({
- mode: 'videoCall',
- sdkAppId,
- userId,
- userSig
- });
- //注册远程监听,要放在加入房间前--这里用了发布订阅模式
- this.subscribeStream(this.client);
- //初始化后才能加入房间
- this.joinRoom(this.client, this.roomId);
- },
- //加入房间
- joinRoom (client, roomId) {
- client.join({ roomId }).then(() => {
- console.log('进房成功');
- //创建本地流
- this.createStream(this.userId);
- //播放远端流
- this.playStream(this.client);
- }).catch(error => {
- console.error('进房失败 ' + error);
- })
- },
- //创建本地音视频流
- createStream (userId) {
- const localStream = TRTC.createStream({ userId, audio: false, video: true });
- this.localStream =localStream;
-
- localStream
- .initialize().then(() => {
- console.log('初始化本地流成功');
- // 创建好后才能播放 本地流播放 local_stream 是div的id
- localStream.play('local_stream');
- //创建好后才能发布
- // this.$nextTick(() => {
- this.publishStream(localStream, this.client);
- // });
- }).catch(error => {
- console.error('初始化本地流失败 ' + error);
- })
- },
- //发布本地音视频流
- publishStream (localStream, client) {
- client.publish(localStream).then(() => {
- console.log('本地流发布成功');
- }).catch(error => {
- console.error('本地流发布失败 ' + error);
- });
- },
- //订阅远端流--加入房间之前
- subscribeStream (client) {
- client.on('stream-added', event => {
- console.log(client,'client9696');
- const remoteStream = event.stream;
- console.log('远端流增加: ' + remoteStream.getId());
- //订阅远端流
- client.subscribe(remoteStream);
- });
- },
- //播放远端流
- playStream (client) {
- client.on('stream-subscribed', event => {
-
- const remoteStream = event.stream;
- console.log('远端流订阅成功:' + remoteStream.getId());
- // 创建远端流标签,因为id是动态的,所以动态创建,用了v-html
-
- this.remoteStream = `<view id="${'remote_stream-' + remoteStream.getId()}" ></view>`;
-
- //做了dom操作 需要使用$nextTick(),否则找不到创建的标签无法进行播放
- this.$nextTick(() => {
- //播放
- remoteStream.play('remote_stream-' + remoteStream.getId());
- })
- });
- },
- //退出音视频
- leaveRoom (client) {
- client
- .leave()
- .then(() => {
- console.log('退房成功')
- // 停止本地流,关闭本地流内部的音视频播放器
- this.localStream.stop();
- // 关闭本地流,释放摄像头和麦克风访问权限
- this.localStream.close();
- this.localStream = null;
- this.client = null
- // 退房成功,可再次调用client.join重新进房开启新的通话。
- })
- .catch(error => {
- console.error('退房失败 ' + error);
- // 错误不可恢复,需要刷新页面。
- });
- },
- //获取用户签名--前端测试用
- genTestUserSig (userID) {
- /**
- * 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
- *
- * 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ) 创建应用,即可看到 SDKAppId,
- * 它是腾讯云用于区分客户的唯一标识。
- */
- const SDKAPPID = 1400371155;
- /**
- * 签名过期时间,建议不要设置的过短
- * <p>
- * 时间单位:秒
- * 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
- */
- const EXPIRETIME = 604800;
- /**
- * 计算签名用的加密密钥,获取步骤如下:
- *
- * step1. 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ),如果还没有应用就创建一个,
- * step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。
- * step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中
- *
- * 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
- * 文档:https://cloud.tencent.com/document/product/647/17275#Server
- */
- const SECRETKEY = "41b790cbcc2e6672ebd921abb4a2ad8a75e1c80705f787926ba5a77425f772af";
-
- // a soft reminder to guide developer to configure sdkAppId/secretKey
- if (SDKAPPID === "" || SECRETKEY === "") {
- alert(
- "请先配置好您的账号信息: SDKAPPID 及 SECRETKEY " +
- "\r\n\r\nPlease configure your SDKAPPID/SECRETKEY in js/debug/GenerateTestUserSig.js"
- );
- }
- const generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME);
- const userSig = generator.genTestUserSig(userID);
- return {
- sdkAppId: SDKAPPID,
- userSig: userSig
- };
- },
- // 获取详情
- async getDetails() {
- // this.roomId = this.$route.query.id;
- let id = this.$route.query.id;
- let res = await meetApi.meetInfoApply(id);
- if(res.code != 200) return;
- let s = res.data;
- this.formInline = {
- doctor: s.applyDoctorDicName,
- phone: s.applyDoctorPhone,
- time: s.applyDateTime,
- hospital: s.applyHospitalDicName
- };
-
-
- this.createClient(this.userId)
- },
- //截图
- snapshot() {
- let canvas = this.$refs.picture;
- canvas.width = 400;
- canvas.height = 300;
- canvas.getContext("2d").drawImage(this.localVideo, 0, 0, canvas.width, canvas.height);
- },
- },
- mounted() {
- //测试用,所以直接创建了,其他需求可自行更改
- this.getDetails();
- }
- };
- </script>
-
- <style lang="scss" scoped>
- .videoCon::-webkit-scrollbar {
- display: none;
- }
- .videoCon {
- height: 100%;
- width: 100%;
- overflow-y: scroll;
- .topBar {
- width: 100%;
- height: 135px;
- // opacity: 0.25;
- background: #42464d;
- box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
- padding: 30px 32px;
- display: flex;
- justify-content: space-between;
- .demo-form-inline {
- width: 65%;
- .el-form-item {
- margin: 0 15px;
- width: 375px;
- .el-input__inner {
- background-color: #42464d;
- color: #fff;
- }
- }
- }
- .rightBox {
- width: 35%;
- display: flex;
- justify-content: space-between;
- .recording {
- font-size: 20px;
- color: #fff;
- font-weight: 700;
- margin-top: 52px;
- i {
- display: inline-block;
- width: 15px;
- height: 15px;
- background: #e60012;
- border-radius: 15px;
- margin-right: 16px;
- }
- span {
- margin-right: 5px;
- }
- }
- }
- }
- .main {
- // height: calc(100% - 135px);
- // height: 100%;
- width: 100%;
- background-color: #272e43;
- padding: 30px;
- .video {
- padding: 0 15px;
- display: flex;
- // justify-content: space-between;
- margin-bottom: 40px;
- .bigScreen {
- width: 1290px;
- height: 720px;
- background-color: #ccc;
- span {
- color: #a0a0a0;
- font-size: 48px;
- cursor: pointer;
- }
- }
- .smallScreem {
- width: 492px;
- height: 720px;
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- // align-content: space-between;
- div {
- width: 492px;
- height: 355px;
- background-color: #ccc;
- position: relative;
- span {
- color: #a0a0a0;
- font-size: 24px;
- cursor: pointer;
- float: right;
- z-index: 2;
- }
- //远端流
- .distant-stream {
- width: 100%;
- height: 100%;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1;
- }
-
- .iconicon-03-17 {
- position: absolute;
- z-index: 2;
- }
-
- .iconicon-03-16 {
- position: absolute;
- z-index: 2;
- left: 30px;
- }
-
- //本地流
- .local-stream {
- width: 100%;
- height: 100%;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1;
- }
- }
- }
- }
- .operation {
- height: 106px;
- width: 100%;
- background-color: #1d2335;
- border-radius: 20px;
- display: flex;
- align-items: center;
- justify-content: space-around;
- font-size: 20px;
- font-weight: 400;
- color: #fff;
- text-align: center;
- div {
- cursor: pointer;
- span {
- font-size: 36px;
- }
- p {
- margin-top: 12px;
- }
- }
- }
- }
- }
- </style>
- <style lang="scss">
- .videoCon {
- .demo-form-inline {
- .el-form-item {
- .el-form-item__label {
- color: #fff;
- font-size: 20px;
- }
- .el-input__inner {
- background-color: #42464d;
- border-color: #42464d;
- color: #fff;
- font-size: 20px;
- height: 40px;
- }
- }
- }
- .rightBox {
- .el-button--primary {
- background-color: #d33594;
- border-color: #d33594;
- width: 116px;
- height: 55px;
- margin-top: 10px;
- padding-top: 10px;
- span {
- font-size: 20px;
- color: #e6e6e6;
- font-weight: 700;
- }
- }
- }
- }
- </style>
2. 采用vue + webRtc + websocket制作
- <template>
- <!-- 视频会诊 -->
- <div class="startConsultation" ref="imageWrapper">
- <div class="topBar">
- <el-form :inline="true" :model="formInline" class="demo-form-inline" :label-position="labelPosition" label-width="100px">
- <el-form-item label="申请医生:">
- <!-- <el-input v-model="formInline.doctor" size="mini"></el-input> -->
- <div>{{formInline.doctor}}</div>
- </el-form-item>
- <el-form-item label="手机号:">
- <!-- <el-input v-model="formInline.phone" size="mini"></el-input> -->
- <div>{{formInline.phone}}</div>
- </el-form-item>
- <el-form-item label="请求时间:">
- <!-- <el-input v-model="formInline.time" size="mini"></el-input> -->
- <div>{{formInline.time}}</div>
- </el-form-item>
- <el-form-item label="申请医院:">
- <!-- <el-input v-model="formInline.hospital" size="mini"></el-input> -->
- <div>{{formInline.hospital}}</div>
- </el-form-item>
- </el-form>
- <div class="rightBox">
- <div class="recording">
- <i></i>
- <span>录制中 :</span>
- <span>1:20:02</span>
- </div>
- <el-button type="primary" @click="signOut">退出</el-button>
- </div>
- </div>
- <div class="main">
- <div class="video">
- <div class="bigScreen">
- <span class="iconfont iconicon-03-17"></span>
- </div>
- <div style="width: 22px"></div>
- <div class="smallScreem">
- <div class="bigBox">
- <div class="icon">
- <span class="iconfont iconicon-03-16"></span>
- <span class="iconfont iconicon-03-17"></span>
- </div>
- <video id="remoteVideo"></video>
- </div>
- <div class="bigBox">
- <div class="icon">
- <span class="iconfont iconicon-03-16"></span>
- <span class="iconfont iconicon-03-17"></span>
- </div>
- <video id="localVideo" autoplay muted></video>
- </div>
- </div>
- </div>
- <div class="operation">
- <div>
- <span class="iconfont iconicon-03-31"></span>
- <p>控制</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-30"></span>
- <p>测量</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-42"></span>
- <p>注释</p>
- </div>
- <div @click="snapshot">
- <span class="iconfont iconicon-03-34"></span>
- <p>截图</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-32"></span>
- <p>截图附件</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-33"></span>
- <p>患者查看详情</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-15"></span>
- <p>邀请</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-29"></span>
- <p>聊天</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-28"></span>
- <p>声音</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-14"></span>
- <p>麦克风</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-10"></span>
- <p>视频</p>
- </div>
- <div>
- <span class="iconfont iconicon-03-18"></span>
- <p>录制</p>
- </div>
- </div>
- <div class="logger"></div>
- </div>
-
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return {
- formInline: {
- doctor: "潘远航",
- phone: "13066990173",
- time: "2021-03-08 12:00:11",
- hospital: "普博医院",
- },
- labelPosition: "right",
- //websocket
- socket: null,
- //webrtc
- peer: null,
- //send data
- sendData: {
- Id: "1",
- SenderId: "1",
- Type: "join"
- },
- target: null,
- // videos
- localVideo: {},
- remoteVideo: {},
- logger: {},
-
- //source
- audioSourceOption: [],
- audioOutputOption: [],
- videoSourceOption: [],
-
- //Constraints(媒体约束)
- videoConstraints: '',
- // Media config
- constraints: {
- audio: {
- noiseSuppression: true,
- echoCancellation: true
- },
- video: {
- width: 1920,
- height: 1080,
- frameRate: 30,
- facingMode: "environment"
- }
- },
- // local video stream
- localStream: undefined,
- isOpenMediaStream: false
- }
- },
- async created() {
- this.sendData.Id = this.$route.query.id;
- this.sendData.SenderId = this.$route.query.sid;
- if (!this.sendData.SenderId) {
- this.sendData.SenderId = "1";
- }
- this.target = this.$route.query.t > 1 ? "answer" : "offer";
- console.info("target:", this.target);
- await this.getUserMedia();
- await this.getDevices();
- await this.getAudioVideo();
- },
- watch: {
-
- },
- mounted() {
- this.localVideo = document.getElementById("localVideo");
- this.remoteVideo = document.getElementById("remoteVideo");
- this.logger = document.querySelector('.logger');
- //获取浏览器支持的连接
- const PeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
- if (!PeerConnection) {
- this.error('浏览器不支持WebRTC!');
- return;
- }
- // stun 服务,如果要做到 NAT 穿透,还需要 turn 中转服务
- let iceServer = {
- "iceServers": [
- {
- "url": "stun:stun.l.google.com:19302"
- },
- // {
- // "url": "stun:192.168.1.162:3478"
- // },
- ]
- };
- this.peer = new PeerConnection(iceServer);
- this.peer.ontrack = e => {
- if (e && e.streams) {
- this.log('收到对方音频/视频流数据...');
- remoteVideo.srcObject = e.streams[0];
- setTimeout(() => {
- remoteVideo.play();
- }, 150);
- }
- };
-
- this.peer.onicecandidate = e => {
- if (e.candidate) {
- this.log('搜集并发送候选人');
- this.sendData.Type = "send";
- this.sendData.Data = JSON.stringify({
- type: `${this.target}_ice`,
- iceCandidate: e.candidate
- });
- this.socket.send(JSON.stringify(this.sendData));
- } else {
- this.log('候选人收集完成!');
- }
- };
-
-
- this.log('信令通道(WebSocket)创建中......');
- var socketUrl = location.protocol + "//" + location.host + "/ws";
- socketUrl = socketUrl.replace("https", "wss").replace("http", "ws");
- this.log("连接地址:" + socketUrl);
- this.socket = new WebSocket(socketUrl);
- this.socket.onopen = () => {
- this.log('信令通道已打开!');
- this.log("当前角色: " + this.target);
- this.sendData.Type = "join";
- this.socket.send(JSON.stringify(this.sendData));
- }
-
- this.socket.onclose = (e) => {
- this.error("断开连接");
- console.log('断开连接', e);
- }
-
- this.socket.onerror = () => this.error('信令通道创建失败!');
- //设置别名
- let _this = this;
- this.socket.onmessage = e => {
- const { Type, Code, Msg, Data } = JSON.parse(e.data);
- if (Code != 200) {
- console.warn(Msg);
- return;
- }
- //加入
- if (Type === "join") {
- this.log("当前工作间在线人数:" + Data);
- if (!this.target) {
- this.target = Data > 1 ? "answer" : "offer";
- }
- this.startLive();
- return;
- }
- let resultData;
- if (typeof Data !== "object") {
- resultData = JSON.parse(Data);
- } else {
- resultData = Data;
- }
- const { type, sdp, iceCandidate } = resultData;
- if (type === 'answer') {
- _this.peer.setRemoteDescription(new RTCSessionDescription({ type, sdp }));
- } else if (type === 'answer_ice') {
- _this.peer.addIceCandidate(iceCandidate);
- } else if (type === 'offer') {
- this.startLive(new RTCSessionDescription({ type, sdp }));
- } else if (type === 'offer_ice') {
- _this.peer.addIceCandidate(iceCandidate);
- }
- };
- },
- beforeDestroy() {
- if (this.socket.readyState == WebSocket.OPEN) {
- this.sendData.Type = "leave";
- this.socket.send(JSON.stringify(this.sendData));
- this.socket.close();
- }
- if (this.isOpenMediaStream) {
- this.localStream.getVideoTracks()[0].stop();
- this.localStream.getAudioTracks()[0].stop();
- }
- },
-
- methods: {
- //拉起本地音视频流
- async startLocalMedia() {
- await this.getUserMedia();
- await this.getAudioVideo();
- },
- //拿到媒体流
- async getUserMedia() {
- // log(`Requesting video stream`);
- navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
- if ("mediaDevices" in navigator) {
- try {
- const stream = await navigator.mediaDevices.getUserMedia(this.constraints);
- this.localVideo.srcObject = stream;
- this.localStream = stream;
- // log("Received local video stream");
- } catch (error) {
- // log(`getUserMedia error: ${error}`);
- }
- }
- },
- //拿到音视频轨道
- async getAudioVideo() {
- if (this.localStream == undefined) {
- await this.getUserMedia();
- }
- console.log("localStream", this.localStream);
- if (this.localStream !== undefined && this.localStream != null) {
- this.isOpenMediaStream = true;
- } else {
- this.isOpenMediaStream = false;
- return;
- }
- let videoTrack = this.localStream.getVideoTracks()[0];
- let audioTrack = this.localStream.getAudioTracks();
- console.log(videoTrack);
- console.log(audioTrack);
-
- let videoConstraintsData = videoTrack.getSettings();
- console.log(videoConstraintsData)
- this.videoConstraints = JSON.stringify(videoConstraintsData, null, 4)
- console.log(this.videoConstraints)
- },
- //获取设备信息
- getDevices() {
- if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
- console.log('不支持获取设备信息!');
- this.isOpenMediaStream = false;
- } else {
- navigator.mediaDevices.enumerateDevices().then(this.showDevice).catch((err) => {
- this.error(err.name + ":" + err.message);
- });
- }
- },
- //展示设备信息
- showDevice(deviceInfos) {
- let _this = this;
- deviceInfos.forEach(function (deviceinfo) {
- var option = {
- text: deviceinfo.label,
- value: deviceinfo.deviceId
- }
- if (deviceinfo.kind === "audioinput") {
- _this.audioSourceOption.push(option);
- } else if (deviceinfo.kind === "audiooutput") {
- _this.audioOutputOption.push(option);
- } else if (deviceinfo.kind === "videoinput") {
- _this.videoSourceOption.push(option);
- }
- })
- },
- // 退出
- signOut() {
- Bus.$emit('code', "true");
- this.$router.go(-1);
- },
-
- async startLive(offerSdp) {
- let stream = this.localStream;
- let _this = this;
- // if (!this.isOpenMediaStream) {
- // this.error("尚未开启媒体流!");
- // return;
- // }
- if (stream == undefined) {
- stream = await navigator.mediaDevices.getUserMedia(this.constraints);
- }
- this.log('将媒体轨道添加到轨道集');
- stream.getTracks().forEach(track => {
- //console.info("startLive", _this.peer, track, stream);
- _this.peer.addTrack(track, stream);
- });
- this.sendData.Type = "send";
- if (!offerSdp) {
- this.log('创建本地SDP');
- const offer = await this.peer.createOffer();
-
- await this.peer.setLocalDescription(offer);
- offer.sdp = offer.sdp;
- this.log(`传输本地SDP`);
- this.sendData.Data = offer;
- this.socket.send(JSON.stringify(this.sendData));
- } else {
- this.log('接收远程SDP');
- //设置接收到的远端offer
- await this.peer.setRemoteDescription(offerSdp);
- this.log('创建回复(应答)SDP');
- //创建answer并发送给对方。
- const answer = await this.peer.createAnswer();
- console.warn(answer);
- this.log(`传输回复接收(应答)SDP`);
- this.sendData.Data = answer;
- this.socket.send(JSON.stringify(this.sendData));
- await this.peer.setLocalDescription(answer);
- }
- },
- log(msg) {
- this.logger.innerHTML += `<span>${new Date().toLocaleTimeString()}:${msg}</span><br/>`;
- },
- error(msg) {
- this.logger.innerHTML += `<span class="error">${new Date().toLocaleTimeString()}:${msg}</span><br/>`;
- }
- }
- };
- </script>
-
- <style lang="scss" scoped>
- .startConsultation::-webkit-scrollbar {
- display: none;
- }
- .startConsultation {
- width: 100vw;
- height: 100vh;
- display: flex;
- flex-direction: column;
- // overflow-y: scroll;
- .topBar {
- width: 100%;
- height: 105px;
- // opacity: 0.25;
- background: #42464d;
- box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
- padding: 15px 32px;
- box-sizing: border-box;
- display: flex;
- justify-content: space-between;
- .demo-form-inline {
- width: 65%;
- .el-form-item {
- margin: 0 15px;
- width: 375px;
- div {
- color: #fff;
- font-size: 20px;
- }
- // .el-input__inner {
- // background-color: #42464d;
- // color: #fff;
- // }
- }
- }
- .rightBox {
- width: 35%;
- display: flex;
- justify-content: space-between;
- .recording {
- font-size: 20px;
- color: #fff;
- font-weight: 700;
- margin-top: 52px;
- i {
- display: inline-block;
- width: 15px;
- height: 15px;
- background: #e60012;
- border-radius: 15px;
- margin-right: 16px;
- }
- span {
- margin-right: 5px;
- }
- }
- }
- }
- .main {
- // height: calc(100% - 135px);
- // height: 100%;
- width: 100%;
- background-color: #272e43;
- padding: 30px;
- box-sizing: border-box;
- flex: 1;
- display: flex;
- flex-direction: column;
- .video {
- flex: 1;
- padding: 0 15px;
- display: flex;
- // justify-content: space-between;
- margin-bottom: 40px;
- .bigScreen {
- width: 1290px;
- height: 100%;
- background-color: #ccc;
- span {
- color: #a0a0a0;
- font-size: 48px;
- cursor: pointer;
- }
- }
- .smallScreem {
- width: 492px;
- height: 100%;
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- align-content: space-between;
-
- .bigBox {
- width: 500px;
- height: 48%;
- background-color: #ccc;
- position: relative;
- border: 1px solid #ccc;
- .icon {
- position: absolute;
- right: 5px;
- top: 5px;
- }
- video {
- width: 100%;
- height: 100%;
- }
- span {
- color: #a0a0a0;
- font-size: 24px;
- cursor: pointer;
- }
- }
- }
- }
- .operation {
- // height: 106px;
- width: 100%;
- flex-basis: 106px;
- background-color: #1d2335;
- border-radius: 20px;
- display: flex;
- align-items: center;
- justify-content: space-around;
- font-size: 20px;
- font-weight: 400;
- color: #fff;
- text-align: center;
- div {
- cursor: pointer;
- span {
- font-size: 36px;
- }
- p {
- margin-top: 12px;
- }
- }
- }
- }
- }
- </style>
- <style lang="scss">
- .startConsultation {
- .demo-form-inline {
- .el-form-item {
- .el-form-item__label {
- color: #fff;
- font-size: 20px;
- }
- .el-input__inner {
- background-color: #42464d;
- border-color: #42464d;
- color: #fff;
- font-size: 20px;
- height: 40px;
- }
- }
- }
- .rightBox {
- .el-button--primary {
- background-color: #d33594;
- border-color: #d33594;
- width: 116px;
- height: 55px;
- margin-top: 10px;
- padding-top: 10px;
- span {
- font-size: 20px;
- color: #e6e6e6;
- font-weight: 700;
- }
- }
- }
- .logger {
- // width: 40%;
- // padding: 14px;
- // line-height: 1.5;
- // color: #4fbf40;
- // border-radius: 6px;
- // background-color: #272727;
- width: 400px;
- height: 600px;
- padding: 14px;
- line-height: 1.5;
- color: #4fbf40;
- border-radius: 6px;
- left: 100px;
- top: 160px;
- z-index: 1;
- position: absolute;
- // transform: translateY(-800px);
- background-color: #272727;
- }
- .logger .error {
- color: #dd4a68;
- }
- }
-
- .vue-cropper {
- position: absolute !important;
- top: 0;
- left: 0;
- z-index: -1;
- }
- </style>
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。