showinfo¶
- doc
https://ffmpeg.org/ffmpeg-filters.html#showinfo, https://ffmpeg.org/ffmpeg-filters.html#movie, https://ffmpeg.org/ffprobe.html, https://ffmpeg.org/ffprobe-all.html
- see also
Using `showinfo’ from `ffprobe’¶
You can not use it with “drawtext” directly because this filter seems not to expose the metadata. Thus although this filter can be used from ffmpeg and ffplay as well as other filters, but if you just want to get information, doing so is not worth much. For this reason, it is usually better to use this filter from ffprobe.
The command line interface of ffprobe in terms of usage for the filter is quite different from that of ffmpeg, so you will be confused if you are not used to it. You have to use it with format option and “movie” filter like this:
[me@host: Videos]$ ffprobe -f lavfi movie=input.mp4,showinfo
...
There is no explanation for the reason, but it seems to be affected by the -show_frames option when used from ffprobe, if you don’t use this option, it seems that the filter graph will abort the input prematurely. (The information that -show_frames gives you is very similar to that of showinfo, but they are different.) So, it is usually better to add -show_frames. However, in this case, showinfo information and -show_frames information are mixed, so it will be hard to use. Fortunately, one goes to standard output and the other to standard error, so you can:
#! /bin/sh
ifn="${1}"
#
exec 1> ${ifn}.show_frames.txt # stdout
exec 2> ${ifn}.showinfo.txt # stderr
ffprobe -hide_banner -f lavfi "movie=${ifn},showinfo" -show_frames
[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=0
pkt_pts_time=0.000000
pkt_dts=0
pkt_dts_time=0.000000
best_effort_timestamp=0
best_effort_timestamp_time=0.000000
pkt_duration=N/A
pkt_duration_time=N/A
pkt_pos=48
pkt_size=345600
width=640
height=360
pix_fmt=yuv420p
sample_aspect_ratio=1:1
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]
[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=400
pkt_pts_time=0.033367
pkt_dts=400
pkt_dts_time=0.033367
best_effort_timestamp=400
best_effort_timestamp_time=0.033367
pkt_duration=N/A
pkt_duration_time=N/A
pkt_pos=57323
pkt_size=345600
width=640
height=360
pix_fmt=yuv420p
sample_aspect_ratio=1:1
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]
... (snip) ...
[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=359600
pkt_pts_time=29.996663
pkt_dts=359600
pkt_dts_time=29.996663
best_effort_timestamp=359600
best_effort_timestamp_time=29.996663
pkt_duration=400
pkt_duration_time=0.033367
pkt_pos=6640218
pkt_size=345600
width=640
height=360
pix_fmt=yuv420p
sample_aspect_ratio=1:1
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]
[Parsed_showinfo_1 @ 000000000051fda0] config in time_base: 1/11988, frame_rate: 2997/100
[Parsed_showinfo_1 @ 000000000051fda0] config out time_base: 0/0, frame_rate: 0/0
[Parsed_showinfo_1 @ 000000000051fda0] n: 0 pts: 0 pts_time:0 pos: 48 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:1 type:I checksum:2FDEE560 plane_checksum:[53F7D422 D7750E37 534C0307] mean:[123 125 131] stdev:[64.1 7.1 6.3]
[Parsed_showinfo_1 @ 000000000051fda0] n: 1 pts: 400 pts_time:0.0333667 pos: 57323 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:B checksum:A1A0E544 plane_checksum:[4DC9D323 DBB80E8C 65E30395] mean:[123 125 131] stdev:[64.2 7.1 6.3]
[Parsed_showinfo_1 @ 000000000051fda0] n: 2 pts: 800 pts_time:0.0667334 pos: 52149 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:B checksum:B0642D1D plane_checksum:[54A120C3 6AB2F3B0 8D96189B] mean:[123 125 131] stdev:[64.1 7.0 6.1]
[Parsed_showinfo_1 @ 000000000051fda0] n: 3 pts: 1200 pts_time:0.1001 pos: 57668 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:B checksum:4C91C68F plane_checksum:[D57EC18B B1A2DA13 90532AE2] mean:[122 125 131] stdev:[64.0 6.8 6.0]
... (snip) ...
[Parsed_showinfo_1 @ 000000000051fda0] n: 249 pts: 99600 pts_time:8.30831 pos: 2137767 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:P checksum:D1AC99B9 plane_checksum:[0BF0FD03 2E211E1D 36CD7E8A] mean:[138 124 130] stdev:[58.9 10.9 7.3]
[Parsed_showinfo_1 @ 000000000051fda0] n: 250 pts: 100000 pts_time:8.34168 pos: 2148636 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:1 type:I checksum:A696E2B6 plane_checksum:[C92C2895 D6ED3866 606D81BB] mean:[138 124 130] stdev:[59.0 10.8 7.3]
[Parsed_showinfo_1 @ 000000000051fda0] n: 251 pts: 100400 pts_time:8.37504 pos: 2204693 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:B checksum:CA895C25 plane_checksum:[31C18F1A 7DB84F87 E9457D75] mean:[138 124 130] stdev:[58.9 10.7 7.3]
... (snip) ...
Input #0, lavfi, from 'movie=myinput.mp4.mp4,showinfo':
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 11988 tbn, 11988 tbc
... (snip) ...
[Parsed_showinfo_1 @ 000000000051fda0] n: 897 pts: 358800 pts_time:29.9299 pos: 6619504 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:P checksum:A84A7C37 plane_checksum:[791396A6 86006DAE C3C377D4] mean:[115 126 134] stdev:[64.3 9.4 14.1]
[Parsed_showinfo_1 @ 000000000051fda0] n: 898 pts: 359200 pts_time:29.9633 pos: 6644735 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:B checksum:EE6808E2 plane_checksum:[83D31197 397778DF BA4E7E5D] mean:[115 126 134] stdev:[64.2 9.4 14.1]
[Parsed_showinfo_1 @ 000000000051fda0] n: 899 pts: 359600 pts_time:29.9967 pos: 6640218 fmt:yuv420p sar:1/1 s:640x360 i:P iskey:0 type:P checksum:F4702B23 plane_checksum:[085F41FF A2936E3F 32327AD6] mean:[115 126 134] stdev:[64.3 9.4 14.1]
to json (etc.)¶
For example, if you are only interested in pts and iskey, it’s easy to extract them even with relatively poor tools:
[me@host: Videos]$ grep 'Parsed_' showinfo_result.txt | grep pts: | \
> sed 's@^.* \(pts: *[0-9]*\) .*\(iskey:[01]\).*$@\1, \2@'
pts: 0, iskey:1
pts: 400, iskey:0
pts: 800, iskey:0
pts: 1200, iskey:0
pts: 1600, iskey:0
... (snip) ...
pts: 358000, iskey:0
pts: 358400, iskey:0
pts: 358800, iskey:0
pts: 359200, iskey:0
pts: 359600, iskey:0
But if you want to get “all” the information that “showinfo” reports, in a form that is easy to machine processing, it is better to use a proper programming language because of the difficulty of handling the “human-oriented form”. Here is an example of jsonization using Python:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
import sys
import io
import re
import json
from collections import defaultdict
_nop = lambda x: x
_numlist = lambda x: json.loads(
re.sub(r"\s+", ",",
re.sub(r"\s*([\[\]])\s*", r"\1", x)))
_strlist = lambda x: json.loads(
re.sub(r"\s+", ",",
re.sub(r"(\w+)", r'"\1"',
re.sub(r"\s*([\[\]])\s*", r"\1", x))))
_type_map = {
"pos": int,
"n": int,
"pts": int,
"iskey": int,
"pts_time": float,
"mean": _numlist,
"stdev": _numlist,
"plane_checksum": _strlist,
"rate": int,
"channels": int,
"nb_samples": int,
"plane_checksums": _strlist,
}
def from_file(fn):
rawtext = io.open(fn, "rb").read()
lines = [
line
for line in re.split(r"\r*\n", re.sub(br".\x08", b"", rawtext).decode().rstrip())
if line.startswith("[Parsed_")]
result = defaultdict(list)
kvrgx = re.compile(r"\b[a-z_,]+:")
for line in lines:
tlk, _, cnt = line.partition("]")
tlk = tlk[len("[Parsed_"):]
m = kvrgx.search(cnt)
frr = {}
while m:
k = m.group(0)[:-1]
cnt = cnt[m.end():]
v = cnt.strip()
m = kvrgx.search(cnt)
if m:
v = cnt[:m.start()]
k, v = re.sub(r"^\s*,\s*", "", k.strip()), v.strip()
frr[k] = _type_map.get(k, _nop)(v)
result[tlk].append(frr)
return result
if __name__ == '__main__':
fn = sys.argv[1]
result = from_file(fn)
print(json.dumps(result, indent=4))
{
"showinfo_1 @ 00000000004916a0": [
{
"time_base": "1/11988,",
"frame_rate": "2997/100"
},
{
"time_base": "0/0,",
"frame_rate": "0/0"
},
{
"fmt": "yuv420p",
"pts_time": 0.0,
"i": "P",
"plane_checksum": [
"53F7D422",
"D7750E37",
"534C0307"
],
"type": "I",
"s": "640x360",
"sar": "1/1",
"pts": 0,
"checksum": "2FDEE560",
"stdev": [
64.1,
7.1,
6.3
],
"iskey": 1,
"mean": [
123,
125,
131
],
"n": 0,
"pos": 48
},
{
"fmt": "yuv420p",
"pts_time": 0.0333667,
"i": "P",
"plane_checksum": [
"4DC9D323",
"DBB80E8C",
"65E30395"
],
"type": "B",
"s": "640x360",
"sar": "1/1",
"pts": 400,
"checksum": "A1A0E544",
"stdev": [
64.2,
7.1,
6.3
],
"iskey": 0,
"mean": [
123,
125,
131
],
"n": 1,
"pos": 57323
},
/* ... snip ... */
{
"fmt": "yuv420p",
"pts_time": 0.633967,
"i": "P",
"plane_checksum": [
"3BD1BDCC",
"76E248FA",
"B7406C1E"
],
"type": "B",
"s": "640x360",
"sar": "1/1",
"pts": 7600,
"checksum": "0BE672F3",
"stdev": [
63.3,
6.3,
5.4
],
"iskey": 0,
"mean": [
121,
124,
131
],
"n": 19,
"pos": 200453
},
{
"fmt": "yuv420p",
"pts_time": 0.667334,
"i": "P",
"plane_checksum": [
"7B718EE2",
"9CFC4906",
"53745BFF"
],
"type": "P",
"s": "640x360",
"sar": "1/1",
"pts": 8000,
"checksum": "712633F6",
"stdev": [
63.5,
6.4,
5.4
],
"iskey": 0,
"mean": [
121,
124,
131
],
"n": 20,
"pos": 181717
}
]
}