Sé algunas cosas sobre la codificación de video y encontré un problema que me bloquea durante algunos días.
Meta:
Código:
// Start webcam stream startCameraStream() { const windowConstraints = (window.constraints = { audio: false, video: true }); navigator.mediaDevices .getUserMedia(windowConstraints) .then(stream => { this.$refs.webcamStream.srcObject = stream; }).catch(error => { alert("Browse doesn't support or there is some errors." + error); }); }, // Stop webcam stream stopCameraStream() { let tracks = this.$refs.webcamStream.srcObject.getTracks(); tracks.forEach(track => { track.stop(); }); }, // Start to record webcam and save it into chunks array and create a blob object startRecordCameraStream(stream) { this.mediaRecorder = new MediaRecorder(stream); this.mediaRecorder.ondataavailable = (ev) => { this.chunks.push(ev.data); }; this.mediaRecorder.onstop = () => { this.blob = new Blob(this.chunks, { 'type': "video/x-matroska;codecs=avc1" }); this.chunks = []; }; this.mediaRecorder.start(); }, // Stop to record webcam stopRecordCameraStream() { this.mediaRecorder.stop(); },El archivo blob es legible y puedo mostrarlo con estas pocas líneas de codificación:
let videoURL = window.URL.createObjectURL(this.blob); let vidSave = this.$refs.webcamRecord; vidSave.src = videoURL; submitVideo(state, blob) { let formData = new FormData(); formData.append('webcam', blob); return new Promise((resolve, reject) => { try { axios.post('http://127.0.0.1:5000/', formData, { headers: { 'Content-Type': 'multipart/form-data', } }).then((response) => { // TOO SEE IN STEP 5 resolve(); }).catch((error) => { console.log(error); }) } catch (error) { reject(error) } }); } from flask import Flask, request from flask_cors import CORS import flask #Instance of Flask class app = Flask(__name__) cors = CORS(app, resources={r"/*": {"origins": "*"}}) #Route function @app.route('/', methods=["POST","GET"]) def model(): if request.method == "POST": video = request.files['webcam'].stream.read() return flask.Response(video, mimetype='video/x-matroska')Simplemente devuelvo el objeto binario de Python a la interfaz de VueJS:
b'\x1aE\xdf\xa3\xa3B\x86\x81\x01B\xf7\x81\x ... 'Simplemente devolvemos este objeto de bytes en una respuesta de matraz:
return flask.Response(video, mimetype='video/x-matroska') }).then((response) => { let data = response.data; let video = new Blob([data],{'type': "video/x-matroska;codecs=avc1;"}) state.modelVideo = video; resolve(); })Una vez que intentamos mostrar el blob como se explica en el punto 1, no pasa nada:
let videoURL = window.URL.createObjectURL(this.modelVideo); let vidSave = this.$refs.webcamRecord; vidSave.src = videoURL;Algo realmente extraño es que los archivos blob iniciales y nuevos no tienen el mismo tamaño y cuando leemos binarios de ambos objetos blob tenemos esto:
Binario de blob inicial desde la interfaz (con una función FileReader y readAsBinaryString):
"\u001aEߣ£B†\u0001B÷\u0001Bò\u..."Binario de blob recibido del backend (con una función FileReader y readAsBinaryString):
"\u001aEߣ�B��\u0001B��\..."Opinión:
Mi opinión es que al enviar un video desde el backend, hay un malentendido de cifrado entre Python y Javascript. Traté de codificar en base64 en el lado del backend y decodificar en el lado del frontend, pero nada cambia.
La respuesta de datos sin procesar que recibí del backend es:
{ "data": "\u001aEߣ�B��\u0001B��\u0001B��..." "status": 200, "statusText": "OK", "headers": { "content-length": "15661", "content-type": "video/x-matroska" }, "config": { "url": "http://127.0.0.1:5000/", "method": "post", "data": {}, "headers": { "Accept": "application/json, text/plain, */*" }, "transformRequest": [ null ], "transformResponse": [ null ], "timeout": 0, "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN", "maxContentLength": -1, "maxBodyLength": -1 }, "request": {} }agregue el blob de tipo de respuesta para solicitar la opción de inicio:
axios.post('http://127.0.0.1:5000/', formData, { headers: { 'Content-Type': 'multipart/form-data', }, responseType: 'blob' // default is "json" })