2017-11-03 13 views
2

の反復の前または後にAWKで文字列を検索するだから私はこのようになりますテキストドキュメント(切り捨て)は、反復配列

[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] 

を持っているこのテキストは、このコマンドで作成されました:

ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type,frame_number -v quiet input.mp4 

ご覧のとおり、[フレーム]〜[/フレーム]のシーケンスが繰り返されます。これは私がフレームを数え、どのフレームがIフレームであるかを見つける方法です。各シーケンスにおいて、「pict_type =」値が変化する。 AWKを使って反復番号を入力し、pict_type値がIと等しい先行のpkt_pts_time値を出力する方法があるかどうか疑問に思っていました。

たとえば、フレーム番号が3の場合、数字3を入力し、awk式は3番目の[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

これはあなたの求めるものですが、サンプル入力からの出力は生成されません

$ 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 

とにかくうまくいけば、それはそれはあなたが必要な正確に何ではない場合、あなたが合うようにそれをマッサージできることをやっているものを十分に明らかです:あなたは、私はそれらを理解して、あなたのサンプル入力が要件を満たしている中で何もするので3をフレームに関連する何かが欲しいです。

1

もう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}' 

指定されたタイプの時間を格納します.3回目のレコード印刷時には最新のものが表示されます。

+1

thx、入力ミス。 – karakfa