2017-11-03 136 views
2

所以我有看起來像這樣的一個文本文件(截)重複序列的迭代

[FRAME] 
pkt_pts_time=0.000000 
pict_type=I 
[/FRAME] 
[FRAME] 
pkt_pts_time=0.250250 
pict_type=B 
[/FRAME] 
[FRAME] 
pkt_pts_time=0.500500 
pict_type=P 
[/FRAME] 
[FRAME] 
pkt_pts_time=0.750750 
pict_type=B 
[/FRAME] 
[FRAME] 
pkt_pts_time=0.959292 
pict_type=I 
[/FRAME] 

本文用這個命令創建之前或之後發現有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輸入一個迭代編號並輸出pict_type值等於I的前一個pkt_pts_time值。

例如,如果我的幀編號是3.我將能夠輸入數字3,awk表達式將轉到第三個[Frame]到[/ Frame]序列,然後從那裏回顧,直到找到「pict_type = I」字符串。然後它會看到該序列迭代的pkt_pts_time是「pkt_pts_time = 0.00000」,它會輸出0.0000

+1

您是否生成該文本文件?因爲您只能輸出I幀數據,並避免對其進行後處理。 – LordNeckbeard

+0

如果包含迄今爲此編寫的代碼,這將非常有幫助。如果我們能夠看到您的代碼,可以更輕鬆地幫助您瞭解如何修復代碼。 – ghoti

+0

@ ghoti,這是我的代碼。 ffprobe -select_streams v -show_frames -show_entries frame = pkt_pts_time,pict_type,frame_number -v quiet input.mp4 – dne202

回答

1

選中此項。我會解釋它是如何工作的,如果它是你想要的。 我通過結束標記來統計幀 - [/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 

此版本打印下部和上部 「I」 幀的值,最接近目標幀:

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 
+0

謝謝@MiniMax!這工作完美。爲了讓它在給出I幀的幀數之後,我需要改變什麼? – dne202

+0

@ dne202很簡單,只需將'I'幀號變量添加到'I'檢查部分。我已經做到了,看到答案更新。 – MiniMax

+0

對不起,我的意思是說我如何從頂級腳本獲得相同的輸出,但輸入frame_number之後的I幀是如何獲得的?此外,我喜歡解釋,因爲你提供:) – dne202

0

它聽起來像這是你要求的,但它不會產生任何輸出從你的示例輸入給定你想與一些幀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 

反正希望它足夠它在做什麼很明顯,你可以按摩它來滿足,如果您需要不完全是。

1

另外gawk使用記錄結構

$ 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}' 

存儲給定類型的時間,當它是第三個記錄打印最近看到的時間。

+1

thx,修正了拼寫錯誤。 – karakfa