0

如何在我的节点 js 服务器中实时保存转换为 blob 的流块

客户端.js | 我是我的 cam 流作为我的节点 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 或二进制文件存储到一个视频文件中。

4

2 回答 2

2

这似乎是如何将传入的二进制块连接到视频(webm)文件节点 js 中的副本?,但目前没有公认的答案。我也将该帖子中的答案复制到该帖子中:

我可以通过在前端使用FileReaderapi 转换为 base64 编码来完成这项工作。在后端,Buffer从发送的数据块创建一个新的并将其写入文件流。我的代码示例的一些关键事项:

  1. 我正在使用fetch,因为我不想拉进去axios
  2. 使用时fetch,你必须确保你bodyParser在后端使用
  3. 我不确定您在块中收集了多少数据(即传递给对象start方法的持续时间值MediaRecorder),但您需要确保您的后端可以处理传入的数据块的大小。我把我的设置得很高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});
  }
});
于 2019-07-05T19:23:40.017 回答
0

如果不尝试实现这一点(对不起,现在没有时间),我会建议以下内容:

  1. 读入 Node 的 Stream API,express 请求对象是一个http.IncomingMessage,它是一个 Readable Stream。这可以在另一个基于流的 API 中进行管道传输。https://nodejs.org/api/stream.html#stream_api_for_stream_consumers

  2. 读入 Node 的 Filesystem API,它包含诸如fs.createWriteStream可以处理块流并附加到文件中的函数,以及您选择的路径。https://nodejs.org/api/fs.html#fs_class_fs_writestream

  3. 完成流到文件后,只要文件名具有正确的扩展名,文件应该是可播放的,因为通过浏览器发送的 Buffer 只是一个二进制流。进一步阅读 Node 的 Buffer API 将是值得您花时间的。 https://nodejs.org/api/buffer.html#buffer_buffer

于 2019-07-04T11:02:34.490 回答