Похоже, что это дубликат Как объединить куски входящего двоичного файла в узел видео (webm) файла js? , но в настоящее время он не имеет принятого ответа. Я также копирую свой ответ из этого поста в этот:
Я смог заставить это работать, преобразовав кодировку base64 на интерфейс с API FileReader
. На сервере создайте новый Buffer
из отправленного фрагмента данных и запишите его в поток файлов. Некоторые ключевые вещи с моим примером кода:
- Я использую
fetch
, потому что я не хотел вытягивать axios
.
- При использовании
fetch
необходимо убедиться, что вы используете bodyParser
на бэкэнде
- Я не уверен, сколько данных вы собираете в своих чанках (т. Е. Значение продолжительности, передаваемое методу
start
объекта MediaRecorder
), но вы захотите убедиться, что ваш бэкэнд может обработать размер входящего фрагмента данных. Я установил свой очень высокий на 50MB
, но это может не быть необходимым.
- Я никогда не закрываю поток записи явно ... вы могли бы сделать это в вашем
/final
маршруте. В противном случае createWriteStream
по умолчанию имеет значение AutoClose, поэтому процесс node
сделает это автоматически.
Полный рабочий пример ниже:
Внешний интерфейс:
const mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
let mediaRecorder;
let sourceBuffer;
function customRecordStream(stream) {
// should actually check to see if the given mimeType is supported on the browser here.
let options = { mimeType: 'video/webm;codecs=vp9' };
recorder = new MediaRecorder(window.stream, options);
recorder.ondataavailable = postBlob
recorder.start(INT_REC)
};
function postBlob(event){
if (event.data && event.data.size > 0) {
sendBlobAsBase64(event.data);
}
}
function handleSourceOpen(event) {
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
}
function sendBlobAsBase64(blob) {
const reader = new FileReader();
reader.addEventListener('load', () => {
const dataUrl = reader.result;
const base64EncodedData = dataUrl.split(',')[1];
console.log(base64EncodedData)
sendDataToBackend(base64EncodedData);
});
reader.readAsDataURL(blob);
};
function sendDataToBackend(base64EncodedData) {
const body = JSON.stringify({
data: base64EncodedData
});
fetch('/api', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body
}).then(res => {
return res.json()
}).then(json => console.log(json));
};
Back End:
const fs = require('fs');
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const server = require('http').createServer(app);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json({ limit: "50MB", type:'application/json'}));
app.post('/api', (req, res) => {
try {
const { data } = req.body;
const dataBuffer = new Buffer(data, 'base64');
const fileStream = fs.createWriteStream('finalvideo.webm', {flags: 'a'});
fileStream.write(dataBuffer);
console.log(dataBuffer);
return res.json({gotit: true});
} catch (error) {
console.log(error);
return res.json({gotit: false});
}
});