lichong 9 months ago
parent
commit
d3c86811ba
  1. 6
      api/main.py
  2. 13
      front/src/views/student.vue
  3. 66
      front/src/views/teacher.vue

6
api/main.py

@ -3,7 +3,7 @@ from pymongo import MongoClient
from bson import ObjectId from bson import ObjectId
import hashlib import hashlib
import json import json
from flask import Flask, render_template, request from flask import Flask, request
from flask_socketio import SocketIO, emit, join_room, leave_room from flask_socketio import SocketIO, emit, join_room, leave_room
import time import time
@ -46,7 +46,9 @@ def on_disconnect():
def handle_video_frame(message): def handle_video_frame(message):
# 广播视频帧给老师 # 广播视频帧给老师
global adminSid global adminSid
socketio.emit("teacherVideo", message, room=adminSid) # print(f"Received video frame from {message['userId']}")
socketio.emit("teacherVideo", message, to=adminSid, namespace="/ws/video")
#
# md5加密 # md5加密

13
front/src/views/student.vue

@ -185,17 +185,8 @@ export default {
canvas.height = video.offsetHeight; canvas.height = video.offsetHeight;
let sendFrame = () => { let sendFrame = () => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height); ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => { let dataURL = canvas.toDataURL('image/jpeg', 0.3);
let reader = new FileReader(); that.socket.emit('video', { userId: this.userId, data: dataURL });
reader.onloadend = () => {
let arrayBuffer = reader.result;
that.socket.emit('video', arrayBuffer,);
};
reader.readAsArrayBuffer(blob);
// let arrayBufferView = new Uint8Array(blob);
// console.log(89444, video)
// that.socket.emit('video', arrayBufferView.buffer);
}, 'image/png');
}; };
setInterval(sendFrame, 1000 / 30); // 30 FPS setInterval(sendFrame, 1000 / 30); // 30 FPS
}, },

66
front/src/views/teacher.vue

@ -20,18 +20,19 @@
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12" v-for="studentItem in tableData" :key="studentItem._id">
<video ref="videoEL1" class="canvasClass"></video> <!-- <img v-if="imageSrc" :src="imageSrc" class="canvasClass" alt="Video Frame" /> -->
<canvas :ref="`videoEL${studentItem._id}`" class="canvasClass"></canvas>
</el-col> </el-col>
<el-col :span="12"> <!-- <el-col :span="12">
<video ref="videoEL2" class="canvasClass"></video> <canvas ref="videoEL2" class="canvasClass"></canvas>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<video ref="videoEL3" class="canvasClass"></video> <canvas ref="videoEL3" class="canvasClass"></canvas>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<video ref="videoEL4" class="canvasClass"></video> <canvas ref="videoEL4" class="canvasClass"></canvas>
</el-col> </el-col> -->
</el-row> </el-row>
</el-col> </el-col>
</el-row> </el-row>
@ -204,6 +205,8 @@ export default {
formDisabled: false, formDisabled: false,
socket: null, socket: null,
videoStream: null, videoStream: null,
imageSrc: "",
canvasObj: {},
}; };
}, },
watch: {}, watch: {},
@ -213,6 +216,7 @@ export default {
this.dealFormHeader() this.dealFormHeader()
await this.init(); await this.init();
await this.initWebSocket() await this.initWebSocket()
await this.initCanvas()
}, },
methods: { methods: {
@ -243,7 +247,7 @@ export default {
let res = await getUser({ let res = await getUser({
...params, ...params,
}); });
this.tableData = res.list; this.tableData = _.filter(res.list, o => o.isAdmin === 0);
}, },
// //
async addUserData() { async addUserData() {
@ -349,6 +353,15 @@ export default {
}); });
}) })
}, },
//
async initCanvas() {
for (let i = 0; i < this.tableData.length; i++) {
let element = this.tableData[i];
if (this.$refs[`videoEL${element._id}`]) {
this.canvasObj[`context${element._id}`] = this.$refs[`videoEL${element._id}`][0].getContext('2d');
}
}
},
// //
async initWebSocket() { async initWebSocket() {
this.socket = io('http://localhost:5000/ws/video', this.socket = io('http://localhost:5000/ws/video',
@ -360,19 +373,14 @@ export default {
}); });
this.socket.on('teacherVideo', (data) => { this.socket.on('teacherVideo', (data) => {
// //
let blob = this.dataURLToBlob(data.data);
const arrayBuffer = event.data; let urlCreator = window.URL || window.webkitURL;
const blob = new Blob([arrayBuffer], { type: 'image/jpeg' }); let imageUrl = urlCreator.createObjectURL(blob);
const urlCreator = window.URL || window.webkitURL; let image = new Image();
const imageUrl = urlCreator.createObjectURL(blob); image.onload = () => {
const img = new Image(); this.canvasObj[`context${data.userId}`].drawImage(image, 0, 0, image.width, image.height, 0, 0, 300, 150);
img.onload = function () {
urlCreator.revokeObjectURL(this.src);
}; };
img.src = imageUrl; image.src = imageUrl;
this.$refs.videoEL1.srcObject = null; //
this.$refs.videoEL1.src = imageUrl; //
this.$refs.videoEL1.play();
}); });
}, },
stopVideoStream() { stopVideoStream() {
@ -385,6 +393,24 @@ export default {
this.socket.disconnect(); this.socket.disconnect();
} }
}, },
dataURLToBlob(dataURL) {
let parts = dataURL.split(';base64,');
let contentType = parts[0].split(':')[1];
let byteCharacters = atob(parts[1]);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 1024) {
let slice = byteCharacters.slice(offset, offset + 1024);
let byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
let blob = new Blob(byteArrays, { type: contentType });
return blob;
},
}, },
beforeUnmount() { beforeUnmount() {
this.stopVideoStream(); this.stopVideoStream();

Loading…
Cancel
Save