我正在编写一个用于管理和查看流的Web应用程序。
它是用nodejs编写的。这个想法是在节点和管道输出中运行子进程到节点,然后将缓冲区发送到客户端并在画布上渲染。我有一个工作解决方案,用于将数据发送给客户端并使用Websocket在画布上渲染,但它仅适用于我的一个相机。
我拥有2个IP摄像机,并且都有RTSP服务器。
其中之一(让我们命名为camx)与此FFMPEG命令一起使用(有时它只是停止,也许是由于数据包损失所致):
ffmpeg -rtsp_transport tcp -re -i <rtsp_link> -f mjpeg pipe:1
但另一个(camy)返回Nonmatching transport in server reply
并退出。
我发现Camy Transport是unicast
,但是FFMPEG在我在FFMPEG论坛上阅读时不支持此特定的Lower_transport。
所以我开始寻找解决方案。我的第一个想法是使用openRTSP
,这两个流都可以正常工作。我查看了该文档,并提出了此命令:
openRTSP -4 -c <rtsp_link> | ffmpeg -re -i pipe:0 -f mjpeg pipe:1
-4
参数将流以MP4格式返回管道
这是我遇到的另一个问题,ffmpeg返回:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x559a4b6ba900] moov atom not found
pipe:0: Invalid data found when processing input
有什么办法可以做这项工作?我尝试了发现的各种解决方案,但它们都没有起作用。
编辑
@Gyan建议我使用-i
参数,而不是-4
,但没有解决我的问题。
我的命令:
openRTSP -V -i -c -K <rtsp_link> | ffmpeg -loglevel debug -re -i pipe:0 -f mjpeg pipe:1
Created receiver for "video/H264" subsession (client ports 49072-49073)
Setup "video/H264" subsession (client ports 49072-49073)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
Outputting to the file: "stdout"
[avi @ 0x5612944268c0] Format avi probed with size=2048 and score=100
[avi @ 0x56129442f7a0] use odml:1
Started playing session
Receiving streamed data (signal with "kill -HUP 15028" or "kill -USR1 15028" to terminate)...
^C
[AVIOContext @ 0x56129442f640] Statistics: 16904 bytes read, 0 seeks
pipe:0: Invalid data found when processing input
您可以看到OpenRTSP命令返回err 29,但与此同时,它将一些数据输出到管道。
当我终止命令时,ffmpeg表明它读取了一些数据,但无法处理。
这是产生该错误的函数:
void AVIFileSink::setWord(unsigned filePosn, unsigned size) {
do {
if (SeekFile64(fOutFid, filePosn, SEEK_SET) < 0) break;
addWord(size);
if (SeekFile64(fOutFid, 0, SEEK_END) < 0) break; // go back to where we were
return;
} while (0);
// One of the SeekFile64()s failed, probable because we're not a seekable file
envir() << "AVIFileSink::setWord(): SeekFile64 failed (err "
<< envir().getErrno() << ")n";
}
我认为,它看起来不会寻找文件,因为它是流而不是静态文件。
对解决方法有任何建议吗?
这里有多件事:
-
Nonmatching transport in server reply
-这很可能不是由于单播(因为单播是正常的方式 - 将流发送给单个客户端)。错误最有可能来自这样的事实,即您实际上用-rtsp_transport tcp
标志强迫RTP在TCP上强迫RTP。您在这里有几个选项 - 检查不起作用的摄像机,检查它们是否仅设置为UDP并将其设置为TCP,甚至更好 - 不要强迫运输,让FFMPEG与相机进行协商。也许这立即解决了问题。 - 关于OpenRTSP -
moov
ATOM通常在已知所需的数据时写在文件末尾,并且由于您要管道,因此实际上会在此处打破逻辑。我认为OpenRTSP实际上永远不会发出moov
,因为它永远不会结束流,因此FFMPEG永远不会得到它。我建议简单地尝试修复上述RTSP传输。