在重复序列的迭代之前或之后查找带有AWK的字符串

在重复序列的迭代之前或之后查找带有AWK的字符串,awk,ffmpeg,Awk,Ffmpeg,我有一个文本文档,看起来像这样(被截断) 此文本是使用以下命令创建的: ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type,frame_number -v quiet input.mp4 如您所见,[Frame]到[/Frame]序列是重复的。这是一种计算帧的方法,找出哪一帧是I帧。在每个序列中,“pict_type=”值都会发生变化。我想知道是否有一种方法可以让我使用AWK输入一个

我有一个文本文档,看起来像这样(被截断)

此文本是使用以下命令创建的:

ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type,frame_number -v quiet input.mp4
如您所见,[Frame]到[/Frame]序列是重复的。这是一种计算帧的方法,找出哪一帧是I帧。在每个序列中,“pict_type=”值都会发生变化。我想知道是否有一种方法可以让我使用AWK输入一个迭代数并输出前面的pkt_pts_time值,其中pict_type值等于I


例如,如果我的帧号是3。我可以输入数字3,awk表达式将转到第三个[Frame]到[Frame]序列,然后从那里向后看,直到找到一个“pict_type=I”字符串。然后它会看到序列迭代的pkt_pts_时间是“pkt_pts_time=0.00000”它将输出0.0000

听起来这是您要求的,但它不会从您的示例输入中产生任何输出,因为您需要与第3帧相关的内容,因为您的示例输入中没有任何内容符合我理解的要求:

$ cat tst.awk
BEGIN { FS="=" }
$1=="[FRAME]" { ++frameNr }
{ frame[$1] = $2 }
$1=="[/FRAME]" {
    if ( frameNr == n ) {
        if ( frame["pict_type"] == "I" ) {
            print frame["pkt_pts_time"]
        }
    }
    delete frame
}

$ awk -v n=3 -f tst.awk file

$ awk -v n=5 -f tst.awk file
0.959292

不管怎样,希望它的作用很明显,如果它不是你所需要的,你可以按摩它以适应它。

检查这个。如果你愿意的话,我会解释它是如何工作的。 我通过结束标记计数帧-
[/FRAME]
,但它可以更改为开始标记
[FRAME]

awk -F '=' -v frame_number=3 '
$1 == "[/FRAME]" {
    frame_cnt++;    
}
$1 == "pkt_pts_time" {
    tmp_time = $2;
}
$2 == "I" {
    i_time = tmp_time;
}
frame_cnt == frame_number {
    print i_time;
    exit;
}' input.txt
帧编号在I帧之后的版本:

awk -F '=' -v frame_number=3 '
$1 == "[/FRAME]" {
    frame_cnt++;    
}
$1 == "pkt_pts_time" {
    tmp_time = $2;
}
$2 == "I" {
    i_time = tmp_time;
    i_frame_number = frame_cnt + 1;
}
frame_cnt == frame_number {
    print "The I frame time = " i_time;
    print "The I frame number + 1 = " i_frame_number + 1;
    exit;
}' input.txt
awk -F '=' -v frame_number=3 '
# The frame counter - each time the first field of the line 
# equals to the [FRAME] string, the counter increments.

$1 == "[FRAME]" {
    frame_cnt++;    
}
# The "tmp_time" variable is updated each time the "pkt_pts_time" occurs.
# So, it does not have fixed value, it changing each time - floating.

$1 == "pkt_pts_time" {
    tmp_time = $2;
}
# Here we are determining the nearest "I" frame, before the target frame.
# It works this way: each time the "I" frame occurs, the "i_lower" value
# updated. It happens, while we are not reach the target frame. Then, it is 
# last time, whey the "i_lower" variable is updated. So, we found the nearest
# "I" frame before the target frame.

frame_cnt <= frame_number && $2 == "I" {
    i_lower = tmp_time;
}
# Here, we are determining the nearest "I" frame, after the target frame.
# When it occurs, the lower and upper "I" frame values are printed
# and the script execution stops.
# Note, that if the upper "I" frame does not exist, the script will print nothing,
# because, the condition returns false.

frame_cnt >= frame_number && $2 == "I" {
    print "lower I = " i_lower;
    print "upper I = " tmp_time;
    exit;
}' input.txt
此版本打印最接近目标帧的上下“I”帧值:

awk -F '=' -v frame_number=3 '
$1 == "[/FRAME]" {
    frame_cnt++;    
}
$1 == "pkt_pts_time" {
    tmp_time = $2;
}
$2 == "I" {
    i_time = tmp_time;
    i_frame_number = frame_cnt + 1;
}
frame_cnt == frame_number {
    print "The I frame time = " i_time;
    print "The I frame number + 1 = " i_frame_number + 1;
    exit;
}' input.txt
awk -F '=' -v frame_number=3 '
# The frame counter - each time the first field of the line 
# equals to the [FRAME] string, the counter increments.

$1 == "[FRAME]" {
    frame_cnt++;    
}
# The "tmp_time" variable is updated each time the "pkt_pts_time" occurs.
# So, it does not have fixed value, it changing each time - floating.

$1 == "pkt_pts_time" {
    tmp_time = $2;
}
# Here we are determining the nearest "I" frame, before the target frame.
# It works this way: each time the "I" frame occurs, the "i_lower" value
# updated. It happens, while we are not reach the target frame. Then, it is 
# last time, whey the "i_lower" variable is updated. So, we found the nearest
# "I" frame before the target frame.

frame_cnt <= frame_number && $2 == "I" {
    i_lower = tmp_time;
}
# Here, we are determining the nearest "I" frame, after the target frame.
# When it occurs, the lower and upper "I" frame values are printed
# and the script execution stops.
# Note, that if the upper "I" frame does not exist, the script will print nothing,
# because, the condition returns false.

frame_cnt >= frame_number && $2 == "I" {
    print "lower I = " i_lower;
    print "upper I = " tmp_time;
    exit;
}' input.txt
awk-F'='-v帧编号=3'
#帧计数器-每行的第一个字段
#等于[FRAME]字符串,计数器递增。
$1==“[帧]”{
frame_cnt++;
}
#“tmp_时间”变量在每次出现“pkt_pts_时间”时更新。
#所以,它没有固定的值,它每次都在变化-浮动。
$1==“pkt\U pts\U时间”{
tmp_时间=2美元;
}
#在这里,我们确定目标帧之前最近的“I”帧。
#它是这样工作的:每次“I”帧出现时,“I_lower”值
#更新。它发生在我们没有到达目标帧的时候。那么,是的
#上次,更新了“i_lower”变量。所以,我们找到了最近的
#目标帧之前的“I”帧。
帧号=帧号&&$2==“I”{
打印“下I=”I\u下;
打印“上I=”tmp\U时间;
出口
}'input.txt

另一个
呆呆地看
使用记录结构

$ awk RS='\\[/FRAME\\]' '/pict_type=I/{for(i=1;i<=NF;i++) 
                                         if($i~/pkt_pts_time/) 
                                           {time=$i; break}};
                          NR==3 {split(time,t,"="); print t[2]; exit}'

$awk RS='\\[/FRAME\\]'/pict\\'u type=I/{for(i=1;iDid您生成了这个文本文件吗?因为您可以只输出i-frame数据,而不必对其进行后期处理。如果您包含迄今为止为此编写的代码,这将非常有帮助。如果我们可以看到您的代码,则可以更容易地帮助您确定如何修复代码。@ghoti,这是我的代码。ffprobe-select_streams v-show_frames-show_输入帧=pkt\U pts\U时间,图像类型,帧编号-v安静输入。mp4@LordNeckbeard不过,我需要计算帧数,因此如果只包含I-frame数据,则无法正确计算帧数。就我所搜索的而言,您无法在FFProbe中输出帧数。@dne202,这听起来与您的问题完全相关。我建议您提供注释糟糕的格式设置,当人们试图确定需要回答的问题时,经常会被遗漏/忽略。谢谢,@MiniMax!这非常有效。为了让它提供我之后的I帧的帧数,我需要更改什么?@dne202很简单,只需将
I
帧号变量添加到
I
检查s中即可节。我已经做了,请参阅答案更新。对不起,我想说的是如何从顶部脚本中获得相同的输出,但如何在输入的帧_编号之后获得I帧的输出?此外,我希望得到解释,因为您提供了:)@dne202也就是说,您需要输入帧编号,例如
3
,并在其之前获得最近的“I”帧时间,在其之后获得最近的“I”帧时间。换句话说,I帧类似于范围边界-上部
I
帧和下部
I
帧,中间是
3
帧。正确吗?这是正确的。Al那么,出于好奇,有没有办法在上一个
I
帧之前获得帧的
pkt\u pts\u时间
?我知道我可以通过存储
I\u帧编号
并减去1,然后再运行一些代码来实现这一点,但我想知道是否有办法将其构建到这段代码中。只是好奇,我对awk感到敬畏!