使用 ffmpeg、node.js 和 socket.io 将 Flv 流式传输到套接字
Flv stream to sockets with ffmpeg, node.js and socket.io
所以我在理解如何解决这个问题时遇到了一些问题。我知道流式视频是一个很难的话题,而且有很多需要考虑的地方,但无论如何我们还是开始学习如何流式视频。
我正在使用 SocketIoClientDotNet 作为 c# 应用程序的 node.js 客户端。
我正在将视频的字节数组发送到正在创建临时文件并将缓冲区附加到其中的节点。我试图将视频元素的源设置为该文件,但它不会将其读取为视频并且全黑。我试图下载该文件的副本,因为它不起作用,结果发现 vlc 也无法播放它。确定代码:
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 = true,
Arguments = " -loglevel panic -hide_banner -y -f gdigrab -draw_mouse 1 -i desktop -f flv -"
};
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);
clientSocket.Emit("video", ms.ToArray());
ms.Flush();
if (!ffWorkerIsWorking)
{
ffWorker.CancelAsync();
break;
}
}
}
}
});
ffWorker.RunWorkerAsync();
}
JS(服务器)
var buffer = new Buffer(32768);
var isBuffering = false;
var wstream;
socket.on('video', function(data) {
if(!isBuffering){
wstream = fs.createWriteStream('fooTest.flv');
isBuffering = true;
}
buffer = Buffer.concat([buffer, data]);
fs.appendFile('public/fooTest.flv', buffer, function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
});
我做错了什么?
通过 OutputDataReceived
事件,您可以捕获进程标准输出的 text
输出。这就是为什么在第一种情况下服务器抱怨 UTF-8 编码。您的第二个示例有效,因为您发送的是二进制流。
您需要捕获二进制基本流。请参阅此答案以了解如何操作:Capturing binary output from Process.StandardOutput
我不知道您打算如何进行流式传输,但如果您使用 FLV,则已经有 HTTP/RTMP 个服务器可以使用(例如,带有 RTMP 模块的 Nginx)。
所以我在理解如何解决这个问题时遇到了一些问题。我知道流式视频是一个很难的话题,而且有很多需要考虑的地方,但无论如何我们还是开始学习如何流式视频。
我正在使用 SocketIoClientDotNet 作为 c# 应用程序的 node.js 客户端。
我正在将视频的字节数组发送到正在创建临时文件并将缓冲区附加到其中的节点。我试图将视频元素的源设置为该文件,但它不会将其读取为视频并且全黑。我试图下载该文件的副本,因为它不起作用,结果发现 vlc 也无法播放它。确定代码:
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 = true,
Arguments = " -loglevel panic -hide_banner -y -f gdigrab -draw_mouse 1 -i desktop -f flv -"
};
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);
clientSocket.Emit("video", ms.ToArray());
ms.Flush();
if (!ffWorkerIsWorking)
{
ffWorker.CancelAsync();
break;
}
}
}
}
});
ffWorker.RunWorkerAsync();
}
JS(服务器)
var buffer = new Buffer(32768);
var isBuffering = false;
var wstream;
socket.on('video', function(data) {
if(!isBuffering){
wstream = fs.createWriteStream('fooTest.flv');
isBuffering = true;
}
buffer = Buffer.concat([buffer, data]);
fs.appendFile('public/fooTest.flv', buffer, function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
});
我做错了什么?
通过 OutputDataReceived
事件,您可以捕获进程标准输出的 text
输出。这就是为什么在第一种情况下服务器抱怨 UTF-8 编码。您的第二个示例有效,因为您发送的是二进制流。
您需要捕获二进制基本流。请参阅此答案以了解如何操作:Capturing binary output from Process.StandardOutput
我不知道您打算如何进行流式传输,但如果您使用 FLV,则已经有 HTTP/RTMP 个服务器可以使用(例如,带有 RTMP 模块的 Nginx)。