我对视频编码知之甚少,我遇到了一个问题,这几天我都无法访问。
目标:
- 使用VueJS前端应用程序从我的笔记本电脑的网络摄像头录制视频。
- 通过Axios和flask将此视频发送到后端FormData中的Python flask应用程序。
- 在Flask应用中接收视频。
- 只需将视频与Flask响应一起发回前端(无需对视频进行任何更改)。
- 在前端端存储和显示此视频。
代码:
- 默认情况下,元素类型为:"video/x-matroska;codecs=avc1",我没有选择它。
// 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();
},
blob文件是可读的,我可以用这几行代码显示它:
let videoURL = window.URL.createObjectURL(this.blob);
let vidSave = this.$refs.webcamRecord;
vidSave.src = videoURL;
- 我发送blob在一个formData与关键'webcam',并发送它在Flask url与axios
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)
}
});
}
- 在flask应用中,formData已经被发送和接收,我们能够在后端保存和读取视频,显示一切正常。
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')
我只是将二进制对象从Python返回到VueJS前端:
- video是一个python bytes对象,看起来像这样:
b'x1aExdfxa3xa3Bx86x81x01Bxf7x81x ... '
我们只需在flask响应中返回这个bytes对象:
return flask.Response(video, mimetype='video/x-matroska')
- 我们收到flask响应并将其存储在blob文件中(来自第2点的响应部分)
}).then((response) => {
let data = response.data;
let video = new Blob([data],{'type': "video/x-matroska;codecs=avc1;"})
state.modelVideo = video;
resolve();
})
有一次,我们尝试将blob显示为第1点中的explain,没有任何反应:
let videoURL = window.URL.createObjectURL(this.modelVideo);
let vidSave = this.$refs.webcamRecord;
vidSave.src = videoURL;
真正奇怪的是,初始blob文件和新blob文件的大小不同,当我们从两个blob对象中读取二进制文件时,我们得到了这个:
来自前端的初始blob二进制文件(带有FileReader和readAsBinaryString函数):
"u001aEߣ£B†u0001B÷u0001Bòu..."
从后端接收blob二进制(带有FileReader和readAsBinaryString函数):
"u001aEߣ�B��u0001B��..."
的意见:
我的想法是,当从后端发送回视频时,Python和Javascript之间存在加密误解。我尝试在后端以base64编码并在前端端解码,但没有任何变化。
我从后端收到的原始数据响应是:
{
"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": {}
}
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"
})