如何启用FFMPEG日志记录以及在哪里可以找到FFMPEG日志文件?

45

我希望能够记录FFMPEG进程,因为我想计算一分钟视频转换需要多长时间,以帮助规划我的视频编码服务器的容量。如何启用日志记录,以及日志文件保存在哪里?我在一个CentOS LAMP机器上安装了FFMPEG。

8个回答

41

FFmpeg不会将输出写入特定的日志文件,而是将其发送到标准错误流。要捕获它,您需要:

  • 在生成时捕获和解析它
  • 将标准错误重定向到文件并在进程完成后读取该文件

标准错误流重定向示例:

ffmpeg -i myinput.avi {a-bunch-of-important-params} out.flv 2> /path/to/out.txt

一旦进程完成,您可以检查out.txt

第一种选项有点棘手,但是它是可行的。(我自己也做过。其他人也做过。请在SO和网络上寻找详细信息。)


虽然ffmpeg可能没有提供编写日志文件的选项,但根据您的编解码器和选项,编码器将创建日志。这可能非常具有破坏性,因为它是在执行位置写入的,这可能会导致权限问题。在我的例子中,这是一个与PHP和使用-pass 1/2有关的问题。 - cregox
1
@Stu Thompson,这里的问题是当ffmpeg不是从控制台运行而是以编程方式执行时(它会检查是否为TTY),ffmpeg不会向stderr输出正常的调试信息。 - Tom
@Tom:我没有那个问题,我的Java代码以编程方式调用FFmpeg没有任何问题。而且我不是唯一一个这样做的人。 - Stu Thompson
1
@Stu,我和其他人也有这个问题。FFMpeg在以编程方式调用时可以正常运行,但是它生成的stderr输出不正确或者没有输出。 - commonpike
@commonpike:我认为它不会检查标准输出或标准错误,因为将这两者重定向到管道不会改变输出。(在Linux终端上运行FFmpeg 3.3)。它可能会检查是否有控制tty,即使进程的stdin、stdout和stderr被重定向了,它仍然存在。或者也许不同版本的ffmpeg是不同的。(特别是如果你的系统上的ffmpeg命令实际上使用了avconv fork of FFmpeg,那么肯定有些东西可能已经改变了。) - Peter Cordes
安卓怎么样? - user25

27
从ffmpeg文档中:
“-report” 将完整的命令行和日志输出转储到当前目录中名为“program-YYYYMMDD-HHMMSS.log”的文件中。该文件对于错误报告非常有用。它还意味着“-loglevel debug”。 将环境变量“FFREPORT”设置为任何值都具有相同的效果。
还有其他选项可用于更改文件名和详细程度。

https://ffmpeg.org/ffmpeg.html#Generic-options


3
最近似乎FFREPORT也能指定输出文件名,参见https://dev59.com/sGXWa4cB1Zd3GeqPNoEb#14417386 ,同时请注意指定“-report”会自动将日志记录设置为详细模式。 - rogerdpack
你能使用-report并将日志级别更改为debug吗? - MarcusJ
2
@MarcusJ:是的,使用of=out.mkv; FFREPORT="level=32:file=$of.log" ffmpeg -v verbose ... "$of"将stderr的日志级别设置为“verbose”,并将out.mkv.log的日志级别设置为“status”(AV_LOG_WARNING=24AV_LOG_INFO=32AV_LOG_VERBOSE=40)。支持此功能已于2年前添加,因此您需要使用非古老版本的ffmpeg。 - Peter Cordes
@MarcusJ FFREPORT=file="/my/log/location/%p-%t.log":level=48 ffmpeg -i [...]参考 - Suuuehgi

8
我找到了答案。 1/首先输入预设,我有一个例子是“输出格式MPEG2 DVD HQ”。
-vcodec mpeg2video -vstats_file MFRfile.txt -r 29.97 -s 352x480 -aspect 4:3 -b 4000k -mbd rd -trellis -mv0 -cmp 2 -subcmp 2 -acodec mp2 -ab 192k -ar 48000 -ac 2

如果您想要一个报告包含像示例中那样的命令“-vstats_file MFRfile.txt”到预设中,这可以生成一个报告,它位于您的文件源目录中。 如果您愿意,您可以使用任何名称。我通过阅读有关MPEG属性的完整.docx文档解决了我的问题,最终我可以通过阅读生成的txt文件来完成我的进度条。
问候。

5

FFmpeg记录日志到标准错误输出(stderr),可以使用不同的日志级别记录到文件中。命令行选项-report无法控制日志文件名或日志级别,因此设置环境变量更可取。

(-v-loglevel的同义词。运行ffmpeg -v help查看级别。运行ffmpeg -h full | less查看所有信息。或参考在线文档或其维基页面,如h.264编码指南)。

#!/bin/bash

of=out.mkv
FFREPORT="level=32:file=$of.log" ffmpeg -v verbose   -i src.mp4 -c:a copy -preset slower -c:v libx264 -crf 21 "$of"

这将使用x264重新编码src.mp4,并将stderr的日志级别设置为“verbose”,将out.mkv.log的日志级别设置为“status”。

AV_LOG_WARNING=24AV_LOG_INFO=32AV_LOG_VERBOSE=40等)。这项功能支持是在2年前添加的,因此您需要使用非古老版本的ffmpeg。(出于安全/错误修复和加速的考虑,这总是一个好主意)


有一些编解码器,例如-c:v libx265,直接写入标准错误输出而不是使用FFmpeg的日志记录系统。因此,它们的日志消息不会出现在报告文件中。我认为这是一个错误/待办事项。

要记录标准错误输出,并仍然在终端上查看它,您可以使用tee(1)


如果您使用包括状态行更新的日志级别(默认为-v info或更高),它们将被包含在日志文件中,并用^M(回车符,也称为\r)分隔。没有日志级别包括编码器统计信息(如SSIM),但不包括状态行更新,因此最好的选择可能是过滤该流。

如果不想进行过滤(例如,每个状态更新间隔的fps /比特率都在文件中),可以使用less -r直接将它们传递到终端,以便您可以清晰地查看文件。如果您有多个编码的.enc日志要翻阅,less -r ++G *.enc非常适合。 (++G表示从所有文件的末尾开始。) 使用像.,这样的single-key key bindings来进行下一个文件和上一个文件的翻转,您可以非常好地翻阅一些日志文件。(默认绑定是:n:p.)

如果你想进行过滤,sed 's/.*\r//' 对于 ffmpeg 输出非常完美。(在一般情况下,你需要像 vt100.py 这样的东西,但不仅限于回车符)。使用 tee + sed 至少有两种方法:将 tee 重定向到 /dev/tty 并将 tee 的输出管道传递给 sed,或者使用进程替换将 tee 传递到一个管道中的 sed。
# pass stdout and stderr through to the terminal, 
## and log a filtered version to a file (with only the last status-line update).

of="$1-x265.mkv"
ffmpeg -v info -i "$1" -c:a copy -c:v libx265 ... "$of" |&    # pipe stdout and stderr
   tee /dev/tty | sed 's/.*\r//' >> "$of.enc"

## or with process substitution where tee's arg will be something like /dev/fd/123

ffmpeg -v info -i "$1" -c:a copy -c:v libx265 ... "$of" |&
  tee >(sed 's/.*\r//' >> "$of.enc")

为了测试几种不同的编码参数,您可以创建一个函数,就像我最近用来测试一些东西的这个函数一样。我将所有内容都放在一行上,这样我就可以轻松地向上箭头和编辑它,但在这里,我将解密它。 (这就是为什么每行末尾有 ;

ffenc-testclip(){
  # v should be set by the caller, to a vertical resolution.  We scale to WxH, where W is a multiple of 8 (-vf scale=-8:$v)
  db=0;   # convenient to use shell vars to encode settings that you want to include in the filename and the ffmpeg cmdline
  of=25s@21.15.${v}p.x265$pre.mkv; 
  [[ -e "$of.enc" ]]&&echo "$of.enc exists"&&return;   # early-out if the file exists

  # encode 25 seconds starting at 21m15s (or the keyframe before that)
  nice -14 ffmpeg -ss $((21*60+15))  -i src.mp4 -t 25  -map 0 -metadata title= -color_primaries bt709 -color_trc bt709 -colorspace bt709 -sws_flags lanczos+print_info -c:a copy -c:v libx265 -b:v 1500k -vf scale=-8:$v  -preset $pre -ssim 1 -x265-params ssim=1:cu-stats=1:deblock=$db:aq-mode=1:lookahead-slices=0 "$of" |&
   tee /dev/tty | sed 's/.*\r//' >> "$of.enc";
}

# and use it with nested loops like this.
for pre in fast slow;  do for v in  360 480 648 792;do  ffenc-testclip ;done;done

less -r ++G *.enc       # -r is useful if you didn't use sed

请注意,它测试输出视频文件的存在性,以避免在日志文件中产生额外的垃圾,如果该文件已经存在。即使如此,我仍然使用并追加(>>)重定向。
编写一个shell函数以取代查看shell变量会更加“清晰”,但这对于我自己的使用来说很方便且易于编写。这也是为什么我保存空间而没有正确引用所有变量扩展。($v而不是"$v"

4
似乎如果在命令行中添加此内容:
 -loglevel debug

或者

 -loglevel verbose

您可以在命令行中获取更详细的调试输出。


1

你可以通过添加选项-loglevel debug来查找更多调试信息,完整命令如下:

ffmpeg -i INPUT OUTPUT -loglevel debug -v verbose

0

如果您只想知道命令执行需要多长时间,可以考虑使用time命令。例如,您可以使用time ffmpeg -i myvideoofoneminute.aformat out.anotherformat


0

你必须将reportfile声明为控制台的变量。

问题是所有可以找到的文档都无法运行,所以我花了一天时间找到正确的方法...

例如:对于批处理/控制台

cmd.exe /K set FFREPORT=file='C:\ffmpeg\proto\test.log':level=32 && C:\ffmpeg\bin\ffmpeg.exe -loglevel warning -report -i inputfile f outputfile

Javascript示例:

var reortlogfile = "cmd.exe /K set FFREPORT=file='C:\ffmpeg\proto\" + filename + ".log':level=32 && C:\ffmpeg\bin\ffmpeg.exe" .......;

您可以根据需要更改目录和文件名。

来自柏林的Frank


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接