回答編集履歴

3

訂正: seek 時のフラグの変更点について、情報を訂正

2021/07/11 09:24

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -14,11 +14,11 @@
14
14
 
15
15
   正しく読み出すには、必ず近くの keyframe から読み出しを開始する必要があります。
16
16
 
17
-  任意のフレームに移動したい場合は seek 後に自分で読み進める。(PyAV側では対応しない)
17
+  任意のフレームに移動したい場合は ~~seek 後に自分で読み進める。(PyAV側では対応しない)~~
18
18
 
19
-   参考した情報が古くいかを確認
19
+  ~~time以外を指定する whence オプションは廃止になってます~~
20
20
 
21
-  time以外を指定する whence オプションは廃止になって
21
+  訂正: オプションの仕様が変更され any_frame オプションが有りした
22
22
 
23
23
  - seek 後に demux/decode を呼び出す。(途中でseekは出来ない、理由は上述)
24
24
 

2

補足

2021/07/11 09:24

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -43,6 +43,8 @@
43
43
  - 別スレッドからthreading.Eventでメインスレッドへ通知。
44
44
 
45
45
  - 毎ループ時間を確認する。`if pts * time_base > 20.0: seek ...`
46
+
47
+  → 事前にパケット単位で確認する等で、効率化は出来そう。
46
48
 
47
49
  - sched モジュールをノンブロッキングで使う。
48
50
 

1

検証に使ったコードを追記

2021/07/11 04:10

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -66,6 +66,60 @@
66
66
 
67
67
  ----
68
68
 
69
+ 検証用コード追記
70
+
71
+ ```python
72
+
73
+
74
+
75
+ def read_frame_until(timestamp):
76
+
77
+ for p in a.demux(video=0, audio=0):
78
+
79
+ if p.pts * p.time_base >= timestamp:
80
+
81
+ # XXX: packet の区切り位置の確認
82
+
83
+ # この条件で packet のループを抜けていいかどうかは未検証。
84
+
85
+ break
86
+
87
+ for f in p.decode():
88
+
89
+ if f.pts * p.time_base >= timestamp:
90
+
91
+ break
92
+
93
+ yield p, f
94
+
95
+
96
+
97
+ for p, f in read_frame_until(20):
98
+
99
+ print(f, f.pts * float(p.time_base)) # frame, 秒数を表示
100
+
101
+
102
+
103
+ # 00:00:10 直近の keyframe 迄 seek
104
+
105
+ print("SEEK 10")
106
+
107
+ a.seek(10 * av.time_base)
108
+
109
+
110
+
111
+ # keyframe 次第では、9秒付近から再開されることもある。
112
+
113
+ for p, f in read_frame_until(13):
114
+
115
+ print(f, f.pts * float(p.time_base)) # frame, 秒数を表示
116
+
117
+ ```
118
+
119
+
120
+
121
+ ----
122
+
69
123
  - [PyAV seek](https://github.com/PyAV-Org/PyAV/blob/9ac05d9ac902d71ecb2fe80f04dcae454008378c/av/container/input.pyx#L186)
70
124
 
71
125