Reputation: 55
I know few things about video encoding and I encountered an issue that is blocking me for few days.
Goal:
Code:
// 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();
},
The blob file is readable and I am able to display it with these few coding lines:
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')
I simply return back the binary object from Python to the VueJS frontend:
b'\x1aE\xdf\xa3\xa3B\x86\x81\x01B\xf7\x81\x ... '
We simply return this bytes object in a flask response:
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();
})
Once, we try to display the blob as explain in point 1, nothing happens:
let videoURL = window.URL.createObjectURL(this.modelVideo);
let vidSave = this.$refs.webcamRecord;
vidSave.src = videoURL;
Something really strange is that the initial and new blob files do not have the same size and when we read binary from both blob object we have this:
Initial blob binary from frontend (with a FileReader and readAsBinaryString function) :
"\u001aEߣ£B†\u0001B÷\u0001Bò\u..."
Received blob binary from backend (with a FileReader and readAsBinaryString function):
"\u001aEߣ�B��\u0001B��\..."
Opinion:
My thought is that when sending back video from backend side, there is an encryption misunderstanding between Python and Javascript. I tried to encode in base64 on backend side and decode on frontend side but nothing changes.
The raw data response I received from backend is:
{
"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": {}
}
Upvotes: 3
Views: 2397
Reputation: 101
add responseType blob to request init option:
axios.post('http://127.0.0.1:5000/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
responseType: 'blob' // default is "json"
})
Upvotes: 2