mattintosh note

どこかのエンジニアモドキの備忘録

Raspberry Piで艦これをYouTube Liveにストリーミング配信する(その他サンプル)

GStreamer を色々弄ってるけどどんどんカオスな状態になっていくのでメモっとく。

「もう OpenMAX 対応したし ffmpeg でいいじゃん!」とは言ってはいけない。

YouTube Live に艦隊これくしょんのプレイ動画をストリーミング配信

艦隊これくしょんに限らず、画面の一部分を切り出してストリーミング配信するのでデュアルディスプレイの片方を配信用として使ったりすることもできる。サンプルではテキスト描画や HD 化などのも入れてあるので少々長い。

YouTube に「キーフレーム間隔長すぎんぞ」って言われるけどどこを弄ればいいのかわからない。(omxh264enc にそんなパラメータあるの?)

パラメータはまだ調整中。

ximagesrc xname="艦隊これくしょん -艦これ- - オンラインゲーム - DMM GAMES" と指定すると艦これのウィンドウだけを拾ってくる(アクティブの場合のみ録画する?)。このウィンドウ名は xwininfo で調べられる。

Raspberry Pi & OpenMAX

  • omxh264enc は x264enc に比べてオプションが少なく、gst-inspect-1.0 omxh264enc を読んでもわかりづらい
  • target-bitrate=control-rate= が無いと使えない
  • プロパティの値は 0x000000000xffffffff がデフォルトのようなので printf で10進数に変換させている
  • target-bitrate=0x01000000 以上は指定できない(?)
  • alsasrc はチャンネルを指定しないとモノラルになる
  • このサンプルでは VNC サーバを 16-bit で起動しているので ximagesrc の出力が RGB16 になっているが 24-bit で起動しておいた方が良さそう
gst-launch-1.0 -v -e \
flvmux streamable=true name=m ! rtmpsink sync=false location="rtmp://a.rtmp.youtube.com/live2/hvd4-k0rb-xp1p-e3ua" \
ximagesrc display-name=:0 show-pointer=false startx=$x starty=$y endx=$((x+800-1)) endy=$((y+480-1)) \
    ! videoconvert ! video/x-raw, framerate=24000/1001 \
    ! videoscale ! video/x-raw, width=1280, height=720, pixel-aspect-ratio=1/1, method=0 \
    ! textoverlay font-desc="Droid Sans 8" draw-outline=false shaded-background=true valignment=top    halignment=left  text="Raspberry Pi 3 - `uname -srm`" \
    ! timeoverlay font-desc="Droid Sans"   draw-outline=false shaded-background=true valignment=bottom halignment=right \
    ! videoconvert ! omxh264enc control-rate=variable target-bitrate=$(printf '%d' 0x00ffffff) ! h264parse config-interval=4 ! queue ! m. \
alsasrc buffer-time=$((1*1000*1000)) ! audio/x-raw, channels=2 ! faac ! aacparse ! queue ! m.

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009190121_original.png?1476007523

X86_64 & VAAPI

艦これの画面は800×480ピクセルだが、720p に変換して YouTube Live に投げる。H.264 への変換は VAAPI を使うことで負荷を少なくする。H.264 への変換はデバイスによってハードウェアエンコードが可能だが、それぞれ名称やプロパティが異なるのでネットを徘徊して情報を集める場合は予めその辺に注意しておく必要がある。(例えば Raspberry Pi なら omxh264enc

PulseAudio のデバイスが正しく選択されない場合は pavucontrol を使うことで GUI でデバイスを変更することができる。

gst-launch-1.0 -e \
  flvmux name=m ! rtmpsink sync=false location="rtmp://a.rtmp.youtube.com/live2/STREAM-KEY" \
  ximagesrc display-name=:0 startx=${x} starty=${y} endx=$((x+800-1)) endy=$((y+480-1)) show-pointer=false \
  ! video/x-raw, framerate=30/1 \
  ! videoscale ! video/x-raw, width=1280, height=720, pixel-aspect-ratio=1/1 \
  ! textoverlay font-desc="Droid Sans" halignment=left  valignment=top    shaded-background=true text="$(set -- $(lscpu | grep "^Model name:"); shift 2; echo $*)" \
  ! timeoverlay font-desc="Droid Sans" halignment=right valignment=bottom shaded-background=true \
  ! videoconvert ! video/x-raw, format=YV12 \
  ! vaapih264enc rate-control=cbr bitrate=$((4*1024)) cabac=true max-bframes=2 ! queue ! m. \
  pulsesrc volume=1 buffer-time=1000000 \
  ! audio/x-raw, format=S16LE, rate=44100, channels=2 ! voaacenc ! aacparse ! queue ! m.

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009003540_original.png?1475941043

Screen Shot & Interval/Time Lapse

スナップショットとして1枚記録する。

gst-launch-1.0 ximagesrc ! videoconvert ! pngenc snapshot=true compression-level=9 ! filesink location=screenshot.png

毎秒撮影。

gst-launch-1.0 ximagesrc ! video/x-raw, framerate=1/1 ! videoconvert ! pngenc snapshot=false compression-level=9 ! multifilesink location=%04d.png

エンコード

multifilesrc を使って複数の画像ファイルを入力に指定する。入力タイプおよびフレームレートは caps= で指定する。ポイントとしては PNG をエンコーダの入力形式に合うよう正しく変換すること(ここでは sRGB から I420 の変換を行っている)。進捗が確認できないので ffmpeg で変換した方がいいかもしれない。

gst-launch-1.0 multifilesrc location="%04d.png" index=0 caps="image/png, framerate=5/1" ! pngdec ! videoconvert ! video/x-raw, format=I420 ! vaapih264enc ! qtmux ! filesink location=video.mp4

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009195053_original.png?1476010274

音楽 CD の再生と取り込み

  • mode=1 はディスク全体を指定する
  • cdda://{TRACK} または track= を指定しなかった場合のデフォルトは 1
  • cdda:// 書式では mode= が指定できない(?)

再生

■ cdda プロトコルによる再生

(内部的に cdparanoiasrc を呼び出してる?)

gst-inspect-1.0 cdda:// ! autoaudiosink
gst-inspect-1.0 cdda://3 ! autoaudiosink

■ cdiocddasrc による再生

gst-inspect-1.0 cdiocddasrc mode=1 ! autoaudiosink
gst-inspect-1.0 cdiocddasrc track=3 ! autoaudiosink

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009015614_original.png?1475945927

■ cdparanoiasrc による再生

gst-inspect-1.0 cdparanoiasrc mode=1 ! autoaudiosink
gst-inspect-1.0 cdparanoiasrc track=3 ! autoaudiosink

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009015612_original.png?1475945854

■ スペクトラグラム 付きで再生する

tee を使って1つを autoaudiosink へ。もう1つを audioconvert を通して spectrascope に投げる。

gst-launch-1.0 cdparanoiasrc ! \
  tee   ! queue ! autoaudiosink \
  tee0. ! queue ! audioconvert ! spectrascope shader=8 ! video/x-raw, width=640, height=480 ! ximagesink

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161008/20161008174256_original.png

上の例に更にエンコード(ファイル保存)を追加すると以下のようになる。

gst-launch-1.0 cdparanoiasrc track=3 ! \
  tee   ! queue ! autoaudiosink \
  tee0. ! queue ! audioconvert ! spectrascope shader=8 ! video/x-raw, width=640, height=480 ! ximagesink \
  tee0. ! queue ! filesink location=track03.wav

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009022043_original.png?1475947275

WAV エンコード

gst-launch-1.0 cdparanoiasrc track=1 ! wavenc ! filesink location=track01.wav

http://cdn-ak.f.st-hatena.com/images/fotolife/m/mattintosh4/20161009/20161009020729_original.png?1475946473

DOT ファイルの出力と変換

GST_DEBUG_DUMP_DOT_DIR= が設定されていれば指定されたディレクトリに DOT ファイルが作成される。

GST_DEBUG_DUMP_DOT_DIR=. gst-launch-1.0 [PIPELINE-DESCRIPTION]

Graphvizdot コマンドでも変換できるけど、サイズの指定ができないようなので ImageMagick を使う。フォント名は DOT ファイルに直書きされているので sed などで好みのものに変換する。

仮にこのファイルを dotconv.sh とする。

#!/bin/bash
sed 's|fontname="sans"|fontname="Noto Sans CJK JP"|
     s|fontname="BitStream Vera Sans"|fontname="Noto Sans CJK JP"|
     s|fontname="monospace"|fontname="DejaVu Sans Mono"|
' "$@"
dotconv.sh DOTFILE.dot | convert -density 96 -format dot - converted.png