【问题标题】:RTSP stream to ffmpeg problemsRTSP 流到 ffmpeg 问题
【发布时间】:2019-07-14 11:39:23
【问题描述】:

我正在编写一个 Web 应用程序,用于管理和查看来自 ONVIF 网络摄像机的流。
它是用 nodejs 编写的。这个想法是在节点中运行一个子进程并将输出传递到节点,然后将缓冲区发送到客户端并在画布上呈现它。我有一个可行的解决方案,用于将数据发送到客户端并使用 websockets 在画布上呈现它,但它只适用于我的一个相机。

我拥有 2 个 IP 摄像机,它们都有 rtsp 服务器。
其中一个(我们将其命名为 camX)与这个 ffmpeg 命令一起工作(有时它只是停止,可能是由于数据包丢失):

ffmpeg -rtsp_transport tcp -re -i <rtsp_link> -f mjpeg pipe:1

但另一个(camY)返回Nonmatching transport in server reply并退出。

我发现 camY 传输是 unicast,但 ffmpeg 不支持这个特定的 lower_transport,正如我在 ffmpeg 论坛上看到的那样。

所以我开始寻找解决方案。我的第一个想法是使用openRTSP,它适用于两个流。 我查看了文档并想出了这个命令:
openRTSP -4 -c &lt;rtsp_link&gt; | 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";
}

在我看来,它似乎无法查找文件,因为它是流而不是静态文件。
有什么解决方法的建议吗?

【问题讨论】:

  • ffmpeg 需要 MOOV 标头来解析数据,并且通常在处理完所有媒体数据后写入此标头。尝试在 OpenRTSP 中输出为 AVI。
  • 也许this 可能对你有帮助,它解决了与 ffmpeg 相关的问题

标签: linux ffmpeg rtsp ip-camera openrtsp


【解决方案1】:

这里有很多东西:

  1. Nonmatching transport in server reply - 这很可能不是由于单播(因为单播是正常的方式 - 将流发送到单个客户端)。错误很可能来自这样一个事实,即您实际上是在使用-rtsp_transport tcp 标志强制通过 TCP 进行 RTP。您在这里有几个选项 - 检查不工作的摄像机,检查它们是否设置为仅 UDP 并将它们设置为 TCP,甚至更好 - 不要强制传输并让 ffmpeg 与摄像机协商。也许这可以立即解决问题。
  2. 关于 OpenRTSP - moov 原子通常在所有需要的数据都已知时写在文件的末尾,并且由于您正在管道传输它,它实际上破坏了这里的逻辑。我会假设 OpenRTSP 实际上永远不会发出moov,因为它永远不会结束流,因此 ffmpeg 永远不会得到它。我建议您按照上述方法简单地尝试修复 RTSP 传输。

【讨论】:

    猜你喜欢
    • 2015-08-24
    • 2018-08-06
    • 2020-06-05
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 2015-10-05
    • 2015-06-24
    • 2017-02-24
    相关资源
    最近更新 更多