- cleemy desu wayo authoreda2a11ff5
Outvoke
これはライブラリであると同時にフレームワークです。そして同時に内部DSLです。
If you need English Edition of this README, see README.md
注意
作者であるcleemy desu wayoは、Linuxでしか動作確認してません。
2024年の夏から秋にかけて、互換性が失われるような破壊的な変更が加えられる可能性があります。samples/ 以下に置いたサンプルコードはなるべく従来通りの動作になるようにするつもりです。
これらの変更が加えられる前の最後のバージョンは、version 0.0.99.20240619です。
システム要件
- Ruby 3.0 or later
概要
Outvokeを使用すれば、流れていくデータストリームをフックするようなコードが容易に書けます。
セットアップ
カレントディレクトリに outvoke.rb を置き、実行権限を与えてください。
以下のように -e
オプションを使用して起動し、5秒おきに出力があるなら、とりあえず起動はできています。
$ ./outvoke.rb -e 'hook "every-sec", /[012][0-9]:[0-9][0-9]:[0-9][05]/'
# starting Outvoke 0.1 (version 0.0.99.20240815) ---- 2024-08-16 12:46:06 +0900
# ----
# given ruby code:
# hook "every-sec", /[012][0-9]:[0-9][0-9]:[0-9][05]/
# ----
[2024-08-16 12:46:06 +0900] [outvoke-system] vrchat-001: a new log file was found.
[2024-08-16 12:46:07 +0900] [outvoke-system] vrchat-001: first time log check has done.
[2024-08-16 12:46:10 +0900] 2024-08-16 12:46:10 +0900
[2024-08-16 12:46:15 +0900] 2024-08-16 12:46:15 +0900
[2024-08-16 12:46:20 +0900] 2024-08-16 12:46:20 +0900
[2024-08-16 12:46:25 +0900] 2024-08-16 12:46:25 +0900
[2024-08-16 12:46:30 +0900] 2024-08-16 12:46:30 +0900
終了は Ctrl + C で行います。
VRChatがインストールされていなかったり、ログファイルの場所が違っていれば、エラーの行があるかもしれません。
VRChatがインストールされていて、かつVRChatが起動されてから長い時間が経過しているような場合、Outvoke を起動してから first time log check has done.
の行が出るまでに長い時間がかかる場合があります。VRChatを再起動すれば、この時間は短縮できます。
設定ファイル
カレントディレクトリに outvoke.conf.rb
というファイルがあると、Outvokeはまずそのファイルをインクルードします。
例えば outvoke.conf.rb
に以下のような行があれば、VRChatのログファイルを探すディレクトリを指定することができます。
$outvoke.sources['vrchat-001'].log_dir = "#{Dir.home}/.steam/debian-installation/steamapps/compatdata/438100/pfx/drive_c/users/steamuser/AppData/LocalLow/VRChat/VRChat"
基本的な使い方
引数なしでOutvoke本体を起動すると、カレントディレクトリの main.rb
を探してインクルードします。
ファイル名を指定することもできますし、-e
オプションによってワンライナーを書くこともできますが、話を分かりやすくするためにこのREADMEでは main.rb
に書いていくものとします。
この main.rb
の先頭で 「using OutvokeDSL」
としておくと、内部DSLのモードになります。設定ファイルを書くような気軽さで記述できます。
main.rb
はRubyのスクリプトとして解釈されますので、複雑なプログラムを書くこともできます。
以下は main.rb
の例です。
using OutvokeDSL
hook 'every-sec', /05:00:00/ do
spawn 'play', '-q', '-t', 'wav', '-v', '0.6', 'ring.wav', 'repeat', '50'
end
午前5時になるとカレントディレクトリの ring.wav
を play
コマンドによって再生します。
(以下執筆中)
VRChatでの利用
いくつかの解説やサンプルについては、以下でみつかるかもしれません。
- [cdwact-2023-12](2023年12月活動報告) https://note.com/cleemy/n/nf9ea83c0c5e3
- [cdwact-2024-01](2024年1月活動報告) https://note.com/cleemy/n/n4ceff128e355
- [cdwact-2024-04](2024年4月活動報告) https://note.com/cleemy/n/nf7cce0493fc0
以下のサンプルもご覧ください。
- samples/vrchat_join_log2.rb (入退室履歴)
- samples/2024/vrchat_waittest1.rb (pickupとループのウェイトの変更)
- samples/2024/vrchat_waittest2.rb (pickupとループのウェイトの変更)
- samples/2024/vrchat_get_log_file_name.rb (e.status の使い方)
- samples/2024/vrchat_multiple_ds1.rb (複数のデータソースを扱う)
- samples/2024/vrchat_multiple_ds2.rb (独自のデータソースを書く)
- samples/2024/vrchat_loputs.rb (lo および loputs の基本的な使い方)
samples/2024/vrchat_multiple_ds2.rb を動作させている動画: https://x.com/metanagi/status/1802512101111689368
(以下執筆中)
ワンライナーのサンプル集
ワンライナーの場合も、基本的にRubyの機能はすべて使えます。
実行する前に、以下の準備が必要です。
カレントディレクトリに outvoke.rb を用意
カレントディレクトリに
maoudamashii-se-system47.wav
を用意
( https://maou.audio/se_system47/ から wavファイルをダウンロード)
- play コマンドによって音が鳴るかどうか確認
$ play maoudamashii-se-system47.wav
- 以下のような内容の
outvoke.conf.rb
をカレントディレクトリに用意
def ring(vol = "0.2")
spawn "play", "-v", vol.to_s, "-q", "maoudamashii-se-system47.wav", :err=>"/dev/null"
end
- 以下のワンライナーで1秒に1回音が鳴るかどうか確認
$ ./outvoke.rb -e 'hook "every-sec", /./ do ring ; end'
version 0.0.99.20240818 およびそれ以降では、以下のような書き方も可能:
$ ./outvoke.rb -e 'hook "every-sec" do ring ; end'
あるいは以下のように書くことも可能:
$ ./outvoke.rb -e 'hook("every-sec"){ring}'
これらのワンライナーにおける注意点
ここに掲載したワンライナーでは、_1
(numbered parameter) を多用しています。
$ ./outvoke.rb -e 'hookvr(/pickup object/i){puts _1.body}'
上記は、以下と同じです。
$ ./outvoke.rb -e 'hookvr(/pickup object/i){|e| puts e.body}'
2024年8月現在、hook "vrchat-001"
は hookvr
と書くのと同じですが、あえて hookvr
は使用していません。
少し複雑な目覚まし時計ワンライナー
さて、ここからワンライナーの例を多数紹介していきます。
AM 5:00 から AM 05:10 までの間、10秒に3回音を鳴らす:
$ ./outvoke.rb -e 'hook("every-sec", / 05:0[0-9]:[0-5][036]/){ring}'
AM 05:00 から AM 05:55 までの間、5分に1回動画を再生:
$ ./outvoke.rb -e 'hook("every-sec", / 05:[0-5][05]:00/) {spawn "mpv", "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "--really-quiet", :err=>"/dev/null"}'
AM 05:00 ちょうどに音を鳴らす、ただし月曜から金曜の間だけ:
$ ./outvoke.rb -e 'hook("every-sec", / 05:00:00/){ring if (1..5).include?(Time.now.wday)}'
Time.now
の代わりに、_1.status.now
も使用可能:
$ ./outvoke.rb -e 'hook("every-sec", / 05:00:00/){ring if (1..5).include?(_1.status.now.wday)}'
シンプルなVRChat関連ワンライナー
誰かがjoinしてきたら音を鳴らす:
$ ./outvoke.rb -e 'hook("vrchat-001", /onplayerjoincomplete/i){ring}'
/onplayerjoined/i は推奨できません。
何かオブジェクトをpickupした時に音を鳴らす:
$ ./outvoke.rb -e 'hook("vrchat-001", /pickup object/i){ring}'
動画関連のログをとりあえず全部表示:
$ ./outvoke.rb -e 'hook "vrchat-001", /(resolv|video)/i'
"resolv" と書いておけば、"resolve" と "resolving" の両方にマッチします。
TopazChat関連のログをとりあえず全部表示:
$ ./outvoke.rb -e 'hook "vrchat-001", /(rtsp|topaz)/i'
少し複雑なVRChat関連ワンライナー
誰かがjoinしてきたら音を鳴らす、ただし自分がjoinしてから90秒間は音を鳴らさない:
$ ./outvoke.rb -e 'hook("vrchat-001", /onplayerjoincomplete/i) {ring if _1.status.elapsed > 90}'
_1.status.elapsed
で、自分がjoinしてからの経過時間が取得できます。
これにより、人が大量にいるインスタンスに自分がjoinした直後に、不必要に音が鳴るのを防ぐことができます。
音が鳴らない時も文字列の出力は欲しいという場合:
$ ./outvoke.rb -e 'hook("vrchat-001", /onplayerjoincomplete/i) {ring if _1.status.elapsed > 90 ; _1.body}'
ワールド内で動画再生が開始されるたびに、mpvでその動画を再生:
$ ./outvoke.rb -e 'hook("vrchat-001", /video playback.*resolve url..(https[-_.a-zA-Z0-9&=?%:\/]*)/i) {spawn "mpv", _1.m[1], "--really-quiet", :err=>"/dev/null"; _1.m[1]}'
ワールド内の動画プレイヤーでエラーが起こると、リトライのせいで複数回mpvが起動する場合があります。
(まだまだサンプルを追加予定)