LoginSignup
0
0

More than 1 year has passed since last update.

心拍に合わせて画像を脈動させるOBSプラグインを作る!【プラグイン編】

Last updated at Posted at 2021-12-25

この記事は、Kyoto University Advent Calendar 2021の25日目の記事です。まだ25日だからセーフです1。こんなに忙しくなるとは思ってなかったんだ……。後日もっと丁寧なのに差し替えます……。

概要

画像を一定周期で拡大縮小させるOBSプラグインを作成しました。

目的

去年作ったアプリを友人に見せたらもっといろいろできるはずと言われたのでOBSのフィルタという形で実装すれば楽しいのではと思い作ることにしました。
とりあえず簡単な気がしたので心拍に合わせてサイズが変わるフィルタの実装を目指します。通信部が間に合わなかったので今回は固定周波数で実装しました。

方法

OBSの開発環境を用意する。

OBSのサイトBuild from sourceを見ながら環境を整えていきます。ハマりどころがいくつかありますがこのブログがわかりやすかったです。

プラグインのプロジェクトを作る

プラグインに関する公式ドキュメントを参考にCmakeListを書いてプロジェクトを作ります。僕はそんな余裕がなかったのでサンプルプロジェクトを上書きしました。

コードを書く

プラグインに関する公式ドキュメントのみを参考に書くのはかなり厳しいので類似するプラグインを探しました。
するとOBS Scale To Soundという音で画像サイズを変化させるプラグインが見つかったのでこれを見て書く事にしました。詳細な中身については割愛して(後で追加しますごめんなさい)、参考プログラムからの大きな変更点のみをまとめます。

このプラグインは元画像のサイズを音量に比例したサイズになるように変更しており、それはobs_source_info構造体のvideo_renderに渡す関数の中で行われています。フィルタエフェクトを触る時は直前にobs_enter_graphicsobs_source_process_filter_beginを呼び出し、終了時にobs_source_process_filter_endobs_leave_graphics'を呼びます。実はフィルタから出力される画像のサイズはobs_source_process_filter_end`に渡す引数で決まります。なので引数にいい感じにスケーリングしたサイズ情報を渡せば画像を拡大縮小させることができます。ただそのまま拡大縮小させると、画像の左上を基準にスケールされてしまうのでスケールすると同時に画像を斜め方向に移動させて中心をそろえる必要があります。拡大縮小と移動を同時に行うコードはすでに参考プログラムが書いてくれているのでこれを一定周波数の正弦波によってスケーリングされるように書き換えれば目的は達成です。

僕が書いたvideo_renderに渡す関数は以下の通りです。

static void hrv_filter_render(void *data, gs_effect_t *effect)
{
    int16_t pchRequest[BUFSIZE];
    DWORD cbRead;

    struct hrv_filter_data *filter = data;
    int32_t w = filter->src_w;
    uint32_t h = filter->src_h;

    DWORD now = GetTickCount();
    float duration = (now - filter->last_time) / 1000.0f;
    float s = filter->hear_rate * duration / 60;
    float _sin = sinf(2 * M_PI * s);
    if (s > 1) {
        filter->last_time =
            now - (DWORD)(duration - 60 / filter->hear_rate);
    }

    filter->current_scale = fmax(_sin * filter->scale + 1, 0);

    obs_enter_graphics();
    if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
                         OBS_ALLOW_DIRECT_RENDERING))
        return;

    gs_effect_t *move_effect = filter->effect;
    gs_eparam_t *move_val =
        gs_effect_get_param_by_name(move_effect, "inputPos");
    gs_eparam_t *show = gs_effect_get_param_by_name(move_effect, "show");

    gs_effect_set_float(show, 1.0f);
    /*if (audio_w <= 0 || audio_h <= 0) {
        gs_effect_set_float(show, 0.0f);
        audio_w = 1;
        audio_h = 1;
    }*/

    //Change the position everytime so it looks like it's scaling from the center
    struct vec4 move_vec;
    vec4_set(&move_vec, (w - w * filter->current_scale) / 2, (h - h * filter->current_scale) / 2,
         0.0f, 0.0f);

    gs_effect_set_vec4(move_val, &move_vec);

    obs_source_process_filter_end(filter->context, move_effect,
                      w * filter->current_scale,
                      h * filter->current_scale);
    obs_leave_graphics();

    blog(LOG_DEBUG, "w%ld, h%ld, scale%f", w * filter->current_scale,
         h * filter->current_scale,
         filter->current_scale);

    UNUSED_PARAMETER(effect);
}

結果

こんな感じ。周期は60Hz固定です。Scaleを変えると振幅が変わります。
Desktop 2021.12.25 - 23.48.01.03_8.gif

今後の展望

今回は心拍センサとの連携が全く持って間に合わずとりあえずフィルタだけ書いた形となりました。早急に心拍センサと連携したい所存です。去年作ったアプリが心拍数をブロードキャストしてプラグインが受信する形にしたいなと考えています。


  1. 投稿ボタンを押す瞬間までは25日でしたが、タグが指定されていないというエラーで差し戻されて26日になりました。 

0
0
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
0
0