PyAVを使って動画を音声(と字幕)をTkinterのウィンドウ内に再生するライブラリを開発しています。
(宣伝になってしまったらすみませんが、以下にGithubのリンクを貼っておきます。)
Marusoftware/tkmedia3
で、問題は何かというと、
1つ目は、
python3
1import av 2 3con = av.open("/path/to/video") 4a = con.streams.audio[0].decode() 5v = con.streams.video[0].decode()
として読めないことです。
なぜか、空のリストが出てきたりエラーになったりします。
仕方がないので、例にもあるようにすると、
python3
1import av 2 3con = av.open("/path/to/video") 4a = con.decode(audio=0) 5v = con.decode(video=0) 6 7print(next(a).index) 8print(next(v).index)
として読むと、位置がおかしなことになることです。
最初のprintで出力されるaudioの位置と
二個目のprintで出力されるvideoの位置は
同じなのですが、実際に出てくるのは
0番目のaudioと1番目?のvideoです。
マルチストリームにしなければいけないんでしょうか??
表題に書かれた問題はこれだけなのですが、
pyavでlibavfilterのフィルター(主にpad)を使いたいのですが、
それも教えていただけると幸いです。
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/03/08 00:04 編集
2021/03/08 05:15
2021/03/08 08:41
2021/03/08 09:27
2021/03/08 09:33
回答1件
0
ベストアンサー
python
1con = av.open("/path/to/video") 2a = con.streams.audio[0].decode() 3v = con.streams.video[0].decode()
audio, video は tuple の様なので、
どのようなストリームがあるかは、ファイル次第になるはずです。
ストリームを一緒に扱うという意味では
python
1for frame in con.decode(audio=0, video=0): 2 ...
但し、audio[0], video[0] が失敗する場合は、同様にエラーになるはずです。
→ 読み込むファイルの形式を確認
decode() はジェネレーターなので、コンテナ内でファイルポインタを共有してる場合、
個別に decode を呼び出すのは、読み飛ばしが発生してそうですね。
複数のストリームを対象にした読み出しは demux() を用いてます。
(decode() 内部でも呼び出される)
python
1a = con.stream.get(audio=0) 2v = con.stream.get(video=0) 3for packet in con.demux(a, v): 4 # NOTE: packet.stream.type: "audio", "video", ... 5 6 if packet.dts is None: 7 continue 8 9 for frame in packet.decode(): 10 ... 11 12# or 13 14for packet in con.demux(audio=0, video=0): 15 ...
複数のフレームが混同したストリームを、それぞれ個別に振り分けて処理したい場合、
双方向ジェネレーターを使った例の紹介。
※ PyAV に関しては全く知識はありません。audio系は扱ったことがありますが、videoは全然。
使い方は把握してないので、フレーム読み込みでロスがないかの確認程度。
python
1from itertools import groupby 2 3import av 4from av.audio.frame import AudioFrame 5from av.video.frame import VideoFrame 6 7con = av.open("/path/to/video") 8 9def limit(count, stream): # テスト確認用 10 for _, item in zip(range(count), stream): 11 yield item 12 13def process_audio_frames(): 14 while 1: 15 frame = yield 16 print("audio", frame) 17 18def process_video_frames(): 19 while 1: 20 frame = yield 21 print("video", frame) 22 23audio = process_audio_frames() 24next(audio) # ※ send() を使うため、yieldまで進める 25video = process_video_frames() 26next(video) 27 28for frame_type, group in limit(3, groupby(con.decode(audio=0, video=0), key=type)): 29 if frame_type is AudioFrame: 30 for frame in group: 31 audio.send(frame) 32 elif frame_type is VideoFrame: 33 for frame in group: 34 video.send(frame)
代替は、スレッドで処理するなら Queue にしたり、asyncio なら janus(sync <=> async Queue)
PyAV #239 -- any exmple how to use filter?
audio,video ストリームの所得
python
1 ivstrm = next(s for s in icntnr.streams if s.type == b'video') # input-video-stream 2 iastrm = next(s for s in icntnr.streams if s.type == b'audio') 3 4# 辞書順が保証される python3.7 以降なら 5# ライブラリのコードとしては、おすすめできませんが 6 7 ivstrm, iastrm = icntnr.streams.get(video=0, audio=0) 8 9 assert isinstance(iastrm, av.AudioStream) # nox等で3.6以前をテストする際に 10 assert isinstance(ivstrm, av.VideoStream) # 誤コードがテストをpassしないように確認 11 12# python3.6 13 ivstrm, iastrm = icntnr.streams.get(OrderedDict([("video", 0), ("audio", 0)]))
- Graph/Filter で filter chain を構成して
- フレーム(ifr)を末端へ push
- フレーム(ofr)を取り出し pull
python
1# 各 Graph のノードを link_to で繋ぐユーティリティ関数 2# issue 内コメントから借用 + 戻り値を追加 3def link_nodes(*nodes): 4 for c, n in zip(nodes, nodes[1:]): 5 c.link_to(n) 6 return nodes 7 8# フィルタ準備 9graph = Graph() 10nodes = link_nodes( 11 graph.add_buffer(template=ivstrm), 12 graph.add("scale", "iw/2:ih/2"), 13 graph.add('buffersink') 14) 15graph.configure() 16 17# フィルタ適用 frame を push/pull 18# ([a]buffer/[a]buffersink がある場合は、Graphのpush/pull内で自動判別) 19graph.push(inframe) 20outframe = graph.pull() 21 22# ない場合は、自分で明示的に、先端のbufferへpush, 末端のfilterから pull 23nodes[0].push(inframe) 24outframe = nodes[-1].pull()
投稿2021/03/08 04:55
編集2021/03/08 06:13総合スコア8742
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/03/08 08:47 編集
2021/03/08 09:49 編集
2021/03/08 10:20
2021/03/08 10:21
2021/03/08 11:37
2021/03/08 12:48
2021/03/08 16:26
2021/03/09 04:29 編集
2021/03/16 15:22
2021/03/16 15:28
2021/03/16 16:25
2021/03/21 02:01
2021/03/21 03:02
2021/03/21 05:51
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。