Как сохранить мой поток с камеры на узле js моего сервера в реальном времени?

как я могу сохранить свои фрагменты потоков, которые были преобразованы в большие двоичные объекты, на моем сервере node js в режиме реального времени

клиент.js | Я передаю свой кулачковый поток в виде бинарного файла на мой сервер node js

    handleBlobs = async (blob) => {

        let arrayBuffer = await new Response(blob).arrayBuffer()

        let binary = new Uint8Array(arrayBuffer)

        this.postBlob(binary)


    };

 postBlob = blob => {

        axios.post('/api',{blob})
            .then(res => {
                console.log(res)
            })
    };

сервер.js

app.post('/api', (req, res) => {
    console.log(req.body)
});

как я могу сохранить входящие BLOB-объекты или двоичные файлы в один видеофайл в конце завершения видеозаписи.


person Nane    schedule 29.06.2019    source источник
comment
Проверьте это: medium.com/@daspinola/ Похоже, он делает что-то похожее на то, что вы хотите.   -  person Michele    schedule 03.07.2019
comment
Спасибо, что поделились. Я уже читал эту статью, но получаю фрагменты данных от клиента, поэтому эта статья может не помочь.   -  person Nane    schedule 03.07.2019
comment
Привет, Нэн, это выглядит как дубликат stackoverflow.com/questions/56826079/. За это назначена награда, поэтому не уверен, что вы можете удалить его сейчас... если нет, я также рад предоставить свой ответ здесь :) :)   -  person willascend    schedule 05.07.2019


Ответы (2)


Похоже, это дубликат Как объединить фрагменты входящего двоичного файла в файл видео (webm) node js?, но в настоящее время на него нет принятого ответа. Я также копирую свой ответ из этого поста в этот:

Я смог заставить это работать, преобразовав кодировку base64 на интерфейсе с помощью API FileReader. На бэкенде создайте новый Buffer из отправленного фрагмента данных и запишите его в файловый поток. Некоторые ключевые вещи с моим примером кода:

  1. Я использую fetch, потому что не хочу тянуть axios.
  2. При использовании fetch вы должны убедиться, что используете bodyParser на бэкенде.
  3. Я не уверен, сколько данных вы собираете в своих фрагментах (т. е. значение продолжительности, переданное методу start в объекте MediaRecorder), но вы должны убедиться, что ваш сервер может обрабатывать размер поступающего фрагмента данных. in. Я установил очень высокое значение 50MB, но это может и не понадобиться.
  4. Я никогда не закрываю поток записи явно... вы могли бы сделать это в своем маршруте /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));
}; 

Внутренняя часть:

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});
  }
});
person willascend    schedule 05.07.2019

Не пытаясь реализовать это (извините, сейчас нет времени), я бы предложил следующее:

  1. Считайте в Node Stream API, объект экспресс-запроса — это http.IncomingMessage, который является доступным для чтения потоком. Это может быть передано в другой потоковый API. https://nodejs.org/api/stream.html#stream_api_for_stream_consumers

  2. Прочтите API файловой системы Node, он содержит такие функции, как fs.createWriteStream, которые могут обрабатывать поток фрагментов и добавлять их в файл с путем по вашему выбору. https://nodejs.org/api/fs.html#fs_class_fs_writestream

  3. После завершения потока в файл, если имя файла имеет правильное расширение, файл должен воспроизводиться, потому что буфер, отправляемый через браузер, представляет собой просто двоичный поток. Дальнейшее изучение Node Buffer API будет стоить вашего времени. https://nodejs.org/api/buffer.html#buffer_buffer

person wntwrk    schedule 04.07.2019