Помогите разобраться с MediaRecorder
решил сделать на python-flask видеоконференцию через socketio, дело в том что я могу получить blob от MediaRecorder
var mediaRecorder = new MediaRecorder(stream,options);
mediaRecorder.start(3000);
mediaRecorder.ondataavailable = (event) => {
console.log('Got blob data:', event);
if (event.data.size > 0) {
socket.send({id: stream.id, data: event.data});
}}
Получаю byte в python, пересылаю обратно по broadcast всем подключенным и не понимаю как теперь преобразовать byte в звук и видео(картинку).... помогите решить проблему.
var socket = io();
var uuid = generateUUID();
// Соединение с socketio
socket.on('connect', function() {
socket.emit('join', {'username': 'Иван', 'room': '12', 'uuid': uuid}); // Тут комната в которую входит пользователь
});
socket.on('message', function(message) { // здесь я получаю данные при каждом получении от клиента Blob
(async () => {
let blobStream = new BlobStream();
let users = {};
let user = new Receiver(uuid);
var blob = new Blob([message.data], {type: "video/webm;codecs=vp8,opus"});
user.uuid = uuid;
users[user.uuid] = user;
blobStream.addDataCallback((blob) =>
socketioDataEvent({
uuid: user.uuid,
data: blob
})
);
function socketioDataEvent({ uuid, data }) {
if (!users[uuid]) throw new Error(`Unknown user ${uuid}`);
users[uuid].appendToSourceBuffer(data);
}
})();
})
function Receiver(uuid) {
let video = createVideoEl(uuid);
let mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
let sourceBuffer = null;
mediaSource.addEventListener("sourceopen", function() {
sourceBuffer = mediaSource.addSourceBuffer("video/webm;codecs=vp8,opus");
});
this.appendToSourceBuffer = async (blob) => {
if (
mediaSource.readyState === "open" &&
sourceBuffer &&
sourceBuffer.updating === false
) {
sourceBuffer.appendBuffer(await blob.arrayBuffer());
}
if (
video.buffered.length &&
video.buffered.end(0) - video.buffered.start(0) > 100 &&
sourceBuffer &&
sourceBuffer.updating === false
) {
sourceBuffer.remove(0, video.buffered.end(0) - 100);
}
};
}
function BlobStream() {
let preview = createVideoEl(uuid);
let callbacks = [];
getWebCam().then((stream) => {
//preview.srcObject = stream;
let mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(2000);
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
socket.send({user: uuid, data: event.data, room: '12'});
//callbacks.forEach((callback) => callback(event.data));
}
};
});
this.addDataCallback = (callback) => {
if (typeof callback === "function") callbacks.push(callback);
};
}
// Генерация guid
function generateUUID() {
var d = new Date().getTime();
var d2 = (performance && performance.now && (performance.now()*1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16;
if(d > 0){
r = (d + r)%16 | 0;
d = Math.floor(d/16);
} else {
r = (d2 + r)%16 | 0;
d2 = Math.floor(d2/16);
}
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
function createVideoEl(uuid) {
if ($('#' + uuid).length == 0){
let video = document.getElementById('video_grid').appendChild( document.createElement('video'));
video.autoplay = true;
video.width = 300;
video.height = 300;
video.id = uuid;
return video;
}
else
{
let video = document.getElementById(uuid);
return video;
}
}
async function getWebCam() {
return await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
}
Ответы (1 шт):
Автор решения: Ein
→ Ссылка
Вы не уточнили как именно вы возвращаете данные, но я предположу что возвращается точно такой же Blob (в любом случае, байты в Blob вы же сможете превратить? ;) ).
Собственно, на основе вот этого и этого ответов получаем такую картину:
let video = createVideoEl();
// создаём MediaSource и крепим его к video
let mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
// создаём SourceBuffer в который будем докидывать данные
let sourceBuffer = null;
mediaSource.addEventListener("sourceopen", function () {
// по умолчанию Chrome использует этот,
// но в вопросе не было показано что лежит в options, поэтому у вас он может быть другим
// важно заметить, что если кодек указан не тот, то ничего не заработает
sourceBuffer = mediaSource.addSourceBuffer("video/webm;codecs=vp8,opus");
});
async function appendToSourceBuffer(blob) {
if (
mediaSource.readyState === "open" &&
sourceBuffer &&
sourceBuffer.updating === false
) {
// в оригинале просто передавался просто blob, но у меня не завелось
// решение найдено было тут: https://stackoverflow.com/a/62122595/14168867
sourceBuffer.appendBuffer(await blob.arrayBuffer());
}
// стараемся не переполнить память
if (
video.buffered.length &&
video.buffered.end(0) - video.buffered.start(0) > 100 &&
sourceBuffer &&
sourceBuffer.updating === false
) {
sourceBuffer.remove(0, video.buffered.end(0) - 100);
}
}
// Начинаем получать наш стрим
blobStream(appendToSourceBuffer);
async function blobStream(ondata) {
let stream = await getWebCam();
// для наглядности кинем его на страницу тоже
let preview = createVideoEl();
preview.srcObject = stream;
let mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(200);
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0 && typeof ondata === "function") {
ondata(event.data);
}
};
}
function createVideoEl() {
let video = document.createElement("video");
video.autoplay = true;
video.width = 300;
video.height = 300;
document.body.appendChild(video);
return video;
}
async function getWebCam() {
return await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
}