6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ffmpeg (API)を用いてWebカメラからキャプチャ

Last updated at Posted at 2018-10-01

ほとんどの部分はこのへんに説明を加えたもの。

基本的には「Webカメラ用フォーマット」なるフォーマット指定(Mac: -f avfoundation、Win: -f dshow)ができるので、入力ファイルとしてデバイスの番号を指定(-i "0"とか-i "1"とか)して適当なファイルに書き出せばよい。

たとえばMacbookでFaceTimeカメラからmp4ファイルに書き込む場合:

ffmpeg -f avfoundation -framerate 25 -i "0" -target pal-vcd -vf scale=640x480 ./test.mpg

上のコマンドの場合、ffmpegは永遠に書き込みを続けるので、終わりたい時はCtrl-Cを押す。

Windows用のコマンドは更新予定(だけれども時期は未定)。

Webカメラをリストアップする

ターミナルを使用 (Mac)

WebカメラはAV Foundationなるフレームワーク経由で見えるらしい。
-fオプションでavfoundationを指定する:

$ ffmpeg -list_devices true -f avfoundation -i dummy
mac.png

たとえばsedとか使うことで、インデックスが入っているところだけ取り出すことができる:

ffmpeg -list_devices true -f avfoundation -i dummy 2>&1 \
| sed -n -e "/video devices/,/audio devices/s/\[AV[^]]*\] //gp" \
| sed -e "/video devices/d; /audio devices/d"
mac2.png

ターミナルを使用 (Windows)

Windowsでは、avfoundationではなくdshow (stands for DirectShow)になるので注意。あとはほとんど同じだが、どのように出力からデータをとってくればよいのか…

参考:ffmpeg.zeranoe.com

APIを直接使う

これもやったことない。ここの丸写し:

  1. 通常通りAVFormatContextをつくる
  2. ffmpegに渡すオプションlist_devicesAVDictionaryに渡す
  3. av_find_input_format("dshow") (Windowsの場合)を用いてキャプチャに対応したAVInputFormatを取得
  4. "video=dummy"なるファイル名を用いてavformat_open_input()を呼ぶ
  5. ログは(おそらく)av_log_set_callback()でコールバック関数を指定することでとってくることができる。

以下も参照:
How to enable ffmpeg logging

APIからWebカメラキャプチャを起動

上の節と同様。コードはこちらのページのほうが詳しい。

ただし情報が最新のものなのか未確認。ffmpegは仕様がよく変わるのでわからない。

  1. 通常通りAVFormatContextを作る。
  2. 対応するAVInputFormatを、av_find_input_format("dshow")のようにしてとってくる
  3. ファイル名は"video=<device name or index>"の形式のC文字列で指定する
  4. 上記の設定を利用してavformat_open_input()を呼ぶ
  5. あとは通常のAPI操作と同じ:
    • AVFormatContextオブジェクトは個々のストリームへのポインタを持っている。そのうちどれかがビデオストリームに対応している:coder_typeメンバーがAVMEDIA_TYPE_VIDEOになっているかどうかでチェックできる(でよいのか?未確認)
    • ビデオストリームに対応するデコーダをavcodec_find_decoder()で取得
    • ビデオフレームを取得するためのAVFrameオブジェクトを用意して、avpicture_fill()でバッファと関連づける(これも未確認)
    • ストリームからデコーダに渡していくためのAVPacketを用意する
    • あとはAVFormatContextオブジェクトに対してav_read_frame()を用いてパケットにデータを転送、avcodec_decode_video2()を呼んで随時AVFrameを自分の用途に用いていく(未確認)
    • 最後に*_free*()するのを忘れない
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?