如何无损地将数据传入和传出 FFmpeg?

Wut*_*taz 10 audio video ffmpeg

我将一个流从 FFmpeg 的一个实例传输到另一个实例,但由于在中间流上使用了压缩,因此最终结果很难看。我需要一个无损管道来防止这种情况发生,我希望它同时包含音频和视频。

我怀疑这个问题有不止一个答案,因此任何提供详尽解决方案列表(兼容容器和可以通过管道传输的编解码器)的人都会获得加分。任何处理其他数据(如字幕)的人也可以获得奖励积分。

编辑:我正在寻找合适的编解码器/容器组合。我不知道为什么人们很难弄清楚这一点,因为我说我已经使用了管道,现在我需要它是无损的。

我不知道如何解释这一点而不显得自负,但这是一个常见问题解答网站。提出需要非常具体的答案的问题不会帮助数百万通过将自己的问题输入搜索引擎而访问该站点的用户。我的问题旨在帮助需要在 FFmpeg 实例之间无损传输数据的任何其他人,而不会用一堵叙述墙和代码解释我在做什么,为什么它不起作用,以及为什么这是唯一的选择来分散每个人的注意力。

llo*_*gan 14

如何从管道无损的视频和音频ffmpegffmpeg

提问者的要求:

  • 从一个实例ffmpeg到另一个实例的无损管道
  • 来来去去都无所谓 /dev/null

例子:

ffmpeg -s 1280x720 -f rawvideo -i /dev/zero -ar 48000 -ac 2 -f s16le -i \
/dev/zero -c copy -f nut pipe:1 | ffmpeg -y -i pipe:0 -c copy -f nut /dev/null
Run Code Online (Sandbox Code Playgroud)

我看不出为什么有人会这样做。此外,当您最有可能只使用一个进程来做任何您想做的事情时,几乎没有理由从ffmpeg到。ffmpegffmpeg

选项的作用:

  • -s 1280x720 -f rawvideo– 描述输入的选项,因为/dev/zero不是典型的输入格式,因此需要这些附加选项。

  • -i /dev/zero– 视频输入。在这个例子中它被用来从“无”中生成一个视频流。在示例中使用了这一点,因为提问者拒绝提供有关正在使用的输入的任何信息。

  • -ar 48000 -ac 2 -f s16le– 描述输入的选项,因为/dev/zero它不是典型的音频格式。

  • -i /dev/zero– 音频输入。本示例中使用它来从“无”中生成音频流。

  • -c copy–将输入流复制或重新复用到输出。没有执行重新编码,因此该过程是无损的。不知道提问者是否可以接受流复制。也许需要重新编码?

  • -f nut– 您需要说明ffmpeg管道使用的格式。坚果是一种容器格式。查看ffmpeg -formats完整列表。另一种灵活的格式是-f matroska,但如果没有来自提问者的更多信息,就不可能建议使用合适的或特定的输出容器格式。

  • pipe:1– 使用pipe协议输出到标准输出。或者,可以省略数字(仅pipe:),默认情况下,stdout 文件描述符将用于写入,stdin 将用于读取。

  • 肯定有*有*原因你会想要这样做。一个用例是通过 SSH 隧道传输视频流以进行安全远程查看:`ssh user@example.com "ffmpeg -i $URL -c copy -f nut pipe:1" | ffplay -i 管道:0` (6认同)

Wut*_*taz 9

我学会这样做的方法(从之前的部分答案中)是使用rawvideo视频pcm_s16le编解码器、音频编解码器和 FFmpeg 的nut包装器来编码流。nutFFmpeg 之外的主要程序不支持,但它是我目前所知道的唯一可以支持在进程之间有效地传输数据所需的未压缩格式的容器。

此编码的参数可能如下所示:

... -c:v rawvideo -c:a pcm_16le -f nut - ...
Run Code Online (Sandbox Code Playgroud)

某些音频以 24 位或更大的样本存储,对于这些,您应该改用pcm_24le或 不同的格式。未压缩音频格式的完整列表将通过运行列出ffmpeg -codecs(您必须在列表中搜索它们)。如果您不知道音频的样本大小是多少,使用pcm_16le应该不会造成明显的质量损失。

在管道的接收端,将输入设置为标准输入,ffmpeg 将检测格式并解码流。

... ffmpeg -i - ...
Run Code Online (Sandbox Code Playgroud)

此答案中的省略号 (...) 不是代码的一部分。这些是您的代码所在的位置。单独的连字符 (-) 告诉 FFmpeg 使用标准输入或标准输出,具体取决于它们出现的位置。

更新:

我尝试了一个简单的实验来改进这一点,似乎更好的容器是 AVI,因为其他程序会理解它(至少 VLC 会)。

... -c:v rawvideo -c:a pcm_16le -f avi - ...
Run Code Online (Sandbox Code Playgroud)

这将与旧版本完全相同,并增加了兼容性。

事后看来,尽管我声称问题应该对每个人都有帮助,但我很遗憾发布了一个在许多情况下都没有帮助的问题。这使得答案更有用。

  • 你试过mkv吗?我支持字幕,我认为ffmpeg支持的每个编解码器都可以混合到mkv中。与 mp4 不同,mkv 无需查看文件末尾即可播放,因此它可能在管道中工作。 (2认同)