diff --git a/api/main.py b/api/main.py index b366019..9801119 100644 --- a/api/main.py +++ b/api/main.py @@ -3,7 +3,7 @@ from pymongo import MongoClient from bson import ObjectId import hashlib import json -from flask import Flask, render_template, request +from flask import Flask, request from flask_socketio import SocketIO, emit, join_room, leave_room import time @@ -46,7 +46,9 @@ def on_disconnect(): def handle_video_frame(message): # 广播视频帧给老师 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加密 diff --git a/front/src/views/student.vue b/front/src/views/student.vue index 6062af2..2ea55a6 100644 --- a/front/src/views/student.vue +++ b/front/src/views/student.vue @@ -185,17 +185,8 @@ export default { canvas.height = video.offsetHeight; let sendFrame = () => { ctx.drawImage(video, 0, 0, canvas.width, canvas.height); - canvas.toBlob((blob) => { - let reader = new FileReader(); - 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'); + let dataURL = canvas.toDataURL('image/jpeg', 0.3); + that.socket.emit('video', { userId: this.userId, data: dataURL }); }; setInterval(sendFrame, 1000 / 30); // 30 FPS }, diff --git a/front/src/views/teacher.vue b/front/src/views/teacher.vue index 61885d7..6b99501 100644 --- a/front/src/views/teacher.vue +++ b/front/src/views/teacher.vue @@ -20,18 +20,19 @@ - - + + + - - + @@ -204,6 +205,8 @@ export default { formDisabled: false, socket: null, videoStream: null, + imageSrc: "", + canvasObj: {}, }; }, watch: {}, @@ -213,6 +216,7 @@ export default { this.dealFormHeader() await this.init(); await this.initWebSocket() + await this.initCanvas() }, methods: { @@ -243,7 +247,7 @@ export default { let res = await getUser({ ...params, }); - this.tableData = res.list; + this.tableData = _.filter(res.list, o => o.isAdmin === 0); }, // 打开新增学生的模态框 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() { this.socket = io('http://localhost:5000/ws/video', @@ -360,19 +373,14 @@ export default { }); this.socket.on('teacherVideo', (data) => { // 在这里处理接收到的视频帧 - - const arrayBuffer = event.data; - const blob = new Blob([arrayBuffer], { type: 'image/jpeg' }); - const urlCreator = window.URL || window.webkitURL; - const imageUrl = urlCreator.createObjectURL(blob); - const img = new Image(); - img.onload = function () { - urlCreator.revokeObjectURL(this.src); + let blob = this.dataURLToBlob(data.data); + let urlCreator = window.URL || window.webkitURL; + let imageUrl = urlCreator.createObjectURL(blob); + let image = new Image(); + image.onload = () => { + this.canvasObj[`context${data.userId}`].drawImage(image, 0, 0, image.width, image.height, 0, 0, 300, 150); }; - img.src = imageUrl; - this.$refs.videoEL1.srcObject = null; // 清空当前流 - this.$refs.videoEL1.src = imageUrl; // 设置新图像作为视频源 - this.$refs.videoEL1.play(); + image.src = imageUrl; }); }, stopVideoStream() { @@ -385,6 +393,24 @@ export default { 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() { this.stopVideoStream();