将webm从c#应用程序中流式传输到node.js

时间:2015-08-07 18:09:37

标签: c# node.js ffmpeg socket.io video-streaming

我正在学习node.js与socket.io和c#之间的流媒体。

我有使用ffmpeg成功记录屏幕的代码,将其重定向到StandardOutput.BaseStream并将其存储到Memorybuffer中,当我在我的应用程序中单击停止时,它将内存流作为字节数组发送到存储的node.js服务器该文件,以便客户端可以播放它。这工作得很好,这是我的设置:

C#

bool ffWorkerIsWorking = false;
private void btnFFMpeg_Click(object sender, RoutedEventArgs e)
{
    BackgroundWorker ffWorker = new BackgroundWorker();
    ffWorker.WorkerSupportsCancellation = true;
    ffWorker.DoWork += ((ffWorkerObj,ffWorkerEventArgs) =>
    {
        ffWorkerIsWorking = true;
        using (var FFProcess = new Process())
        {
            var processStartInfo = new ProcessStartInfo
            {
                FileName = "ffmpeg.exe",
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = false,
                Arguments = " -loglevel panic -hide_banner -y -f gdigrab -draw_mouse 1 -i desktop -threads 2 -deadline realtime  -f webm -"
            };
            FFProcess.StartInfo = processStartInfo;
            FFProcess.Start();

            byte[] buffer = new byte[32768];
            using (MemoryStream ms = new MemoryStream())
            {
                while (!FFProcess.HasExited)
                {
                    int read = FFProcess.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                        break;
                    ms.Write(buffer, 0, read);
                    Console.WriteLine(ms.Length);
                    if (!ffWorkerIsWorking)
                    {                                
                        clientSocket.Emit("video", ms.ToArray());                                 
                        ffWorker.CancelAsync();
                        break;
                    }
                }
            }
        }
    });
    ffWorker.RunWorkerAsync();
}

JS(服务器)

socket.on('video', function(data) {
    fs.appendFile('public/fooTest.webm', data, function (err) {
      if (err) throw err;
      console.log('File uploaded');
    });
});

现在我需要更改此代码,因此它不应发送整个文件,而应发送字节数组块而不是整个视频,然后节点将首先创建一个文件然后附加那些字节数组块,因为它们是接收。好听的声音很容易,但显然不是。

我需要以某种方式指示代码使用偏移量,然后只使用该偏移量后的字节,然后更新偏移量。

在服务器端,我认为最好的方法是创建一个文件,并在接收到该文件时将字节数组附加到该文件中。

在服务器端,我会做这样的事情:

JS(服务器)

var buffer = new Buffer(32768);
var isBuffering = false;
socket.on('video', function(data) {
    //concatenate the buffer with the incoming data and broadcast.emit to clients

});

我如何设置要发送的字节的偏移量并更新该偏移量,以及如何处理将数据连接到初始化缓冲区的方式?

我曾尝试编写一些只能从偏移读取到最后的代码,虽然在节点中添加的视频只是黑色,但它似乎仍在工作:

C#

while (!FFProcess.HasExited)
{
    int read = FFProcess.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
    if (read <= 0)
        break;
    int offset = (read - buffer.Length > 0 ? read - buffer.Length : 0);
    ms.Write(buffer, offset, read);
    clientSocket.Emit("videoChunk", buffer.ToArray());
    if (!ffWorkerIsWorking)
    {                                
        ffWorker.CancelAsync();
        break;
    }
}

节点控制台输出

Bytes read

JS(服务器)

socket.on('videoChunk', function(data) {
    if (!isBufferingDone) {
        buffer = Buffer.concat([buffer, data]);
        console.log(data.length);
    }
});

socket.on('cancelVideo', function() {
    isBufferingDone = true;
    setTimeout(function() {
        fs.writeFile("public/test.webm", buffer, function(err) {
            if(err) {
                return console.log(err);
            }
            console.log("The file was saved!");
            buffer = new Buffer(32768);
        }); 
    }, 1000); 
});

JS(客户端)

socket.on('video', function(filePath) {
   console.log('path: ' + filePath);
   $('#videoSource').attr('src',filePath);
   $('#video').play();
});

谢谢!

0 个答案:

没有答案