如何从 Flask 检索二进制文件视频并将其保存到 Blob?
How to retrieve and save to Blob a binary file video from Flask?
我对视频编码知之甚少,我遇到了一个困扰我几天的问题。
目标:
- 使用 VueJS 前端应用程序从笔记本电脑的网络摄像头录制视频。
- 通过 Axios 和 Flask 将此视频发送到后端的 Python Flask 应用。
- 在 Flask 应用程序中接收视频。
- 只需使用 Flask 响应将视频发回前端(不对视频应用任何更改)。
- 在前端存储和显示此视频。
代码:
- 默认ev元素类型为:“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;
- 我使用密钥 'webcam' 在 formData 中发送 blob,然后使用 axios
在 Flask url 上发送它
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 app 上,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')
我只是 return 将二进制对象从 Python 返回到 VueJS 前端:
- 视频是一个 python 字节对象,如下所示:
b'\x1aE\xdf\xa3\xa3B\x86\x81\x01B\xf7\x81\x ... '
我们只是 return 烧瓶响应中的这个字节对象:
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();
})
有一次,我们尝试按照第 1 点中的说明显示 blob,但没有任何反应:
let videoURL = window.URL.createObjectURL(this.modelVideo);
let vidSave = this.$refs.webcamRecord;
vidSave.src = videoURL;
真正奇怪的是,初始和新的 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": {}
}
将 responseType blob 添加到请求初始化选项:
axios.post('http://127.0.0.1:5000/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
responseType: 'blob' // default is "json"
})
我对视频编码知之甚少,我遇到了一个困扰我几天的问题。
目标:
- 使用 VueJS 前端应用程序从笔记本电脑的网络摄像头录制视频。
- 通过 Axios 和 Flask 将此视频发送到后端的 Python Flask 应用。
- 在 Flask 应用程序中接收视频。
- 只需使用 Flask 响应将视频发回前端(不对视频应用任何更改)。
- 在前端存储和显示此视频。
代码:
- 默认ev元素类型为:“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;
- 我使用密钥 'webcam' 在 formData 中发送 blob,然后使用 axios 在 Flask url 上发送它
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 app 上,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')
我只是 return 将二进制对象从 Python 返回到 VueJS 前端:
- 视频是一个 python 字节对象,如下所示:
b'\x1aE\xdf\xa3\xa3B\x86\x81\x01B\xf7\x81\x ... '
我们只是 return 烧瓶响应中的这个字节对象:
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();
})
有一次,我们尝试按照第 1 点中的说明显示 blob,但没有任何反应:
let videoURL = window.URL.createObjectURL(this.modelVideo);
let vidSave = this.$refs.webcamRecord;
vidSave.src = videoURL;
真正奇怪的是,初始和新的 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": {}
}
将 responseType blob 添加到请求初始化选项:
axios.post('http://127.0.0.1:5000/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
responseType: 'blob' // default is "json"
})