我如何通过ffmpeg将Node.js中生成的画布流式传输到youtube /其他rtmp服务器?

问题描述

我想在Node.JS中生成一些图像,将它们编译为视频并将其流式传输到youtube。为了生成图像,我正在使用节点画布模块。这听起来很简单,但是我想连续生成图像,并实时传输结果。我对这件事很陌生,在阅读互联网上的大量资源后,我正在考虑做的事情是:

  1. 使用spawn('ffmpeg',...args)打开ffmpeg,将输出设置为目标rtmp服务器
  2. 在画布上生成图像
  3. 将画布的内容转换为缓冲区,然后通过stdin将其写入ffmpeg进程
  4. 在YouTube上享受结果

但这不是那么简单,是吗?我看到人们共享他们的代码,这些代码涉及在浏览器上运行的客户端JS,但是我希望它成为Node应用程序,以便可以从远程VPS运行它。 有没有办法在我的浏览器中不使用p5之类的东西并捕获窗口以进行重播而做到这一点? 我的思考过程是否足够恰当?现在,我并不真的在乎性能/资源的使用。预先感谢。

编辑:

我花了一些时间,但我无法使它工作... 这是我的代码

const { spawn } = require('child_process');
const { createCanvas } = require('canvas');
const fs = require('fs');


const canvas = createCanvas(1920,1080);
const ctx = canvas.getContext('2d');
const ffmpeg = spawn("ffmpeg",["-re","-f","png_pipe","-vcodec","png","-i","pipe:0","h264","-re","flv","rtmp://a.rtmp.youtube.com/live2/key-i-think"],{ stdio: 'pipe' })

const randomColor = (depth) => Math.floor(Math.random() * depth)
const random = (min,max) => (Math.random() * (max - min)) + min;

let i = 0;
let drawSomething = function () {
    ctx.strokeStyle = `rgb(${randomColor(255)},${randomColor(255)},${randomColor(255)})`
    let x1 = random(0,canvas.width);
    let x2 = random(0,canvas.width);
    let y1 = random(0,canvas.height);
    let y2 = random(0,canvas.height);
    ctx.moveto(x1,y1);
    ctx.lineto(x2,y2);
    ctx.stroke();

    let out = canvas.toBuffer();
    ffmpeg.stdin.write(out)
    i++;
    if (i >= 30) {
        ffmpeg.stdin.end();
        clearInterval(int)
    };
}

drawSomething();
let int = setInterval(drawSomething,1000);

我没有任何错误,也没有从中获取任何视频数据。我已经设置了一个可以连接到的rtmp服务器,然后使用VLC获取流,但是我没有任何视频数据。难道我做错了什么?我环顾了一会儿,似乎找不到任何尝试过此方法的人,所以我真的没有任何线索...

编辑2: 显然我在正确的轨道上,但是我的方法只是给了我2秒钟的“好”视频,然后开始变得块状且混乱。我认为最有可能的是,我生成图像的方法太慢了。我将尝试使用一些GPU加速代码生成图像,而不是使用画布,这意味着我将一直在进行分形,因为我不知道该怎么做。另外,在ffmpeg中使用更大的缓冲区也可能有帮助

解决方法

您的方法很好。请记住,无论您流向何处,都将期望源端跟上潮流。如果您不能足够快地生成帧,那么各种各样的事情都会出错。 (我认为这主要是由于YouTube试图丢弃太慢的信号源,并在接收到帧后再次进行拾取,只是再次失败了。)

您可以通过在尝试流式传输到RTMP服务器之前先输出到文件来进行测试。