【VJソフト】SynapseRackのBeat Syncの実装とUI/UX


はじめに

この記事は【ジェネ系VJ Advent Calendar 2023】7日目の記事です。

SynapseRack

私が開発しているプリレンダVJ向けソフトウェアです。
わかりやすく言うとResolumeVDMXの個人開発版という雰囲気になります。
ジェネ系VJ Advent Calendarですが、自作VJツール全般がOKということなので今回はプリレンダVJソフトウェア開発について書きます。
別の日にジェネについても書きたい気持ちです。

Beat Sync

最近SynapseRackのbeta0.2.2を公開しました。
主なアップデートとしてはBeat Syncとクロスフェードループです。
今回はBeat Syncの機能、実装、UI/UX(思想?)について話します。

機能

映像の再生速度をBPMと同期させる機能です。
以下の動画で理解して頂けると思います。
少し解説のテンポが速いので一時停止を推奨します。

実装

方法①映像にBPMの情報を持たせる

映像をBPMに合わせたい場合、一番簡単なのは映像のBPMを取得することです。例えば100BPMの映像があった場合、単純に2倍速にすれば200BPMに対応できます。
しかし、VJ向けの映像が必ずしもBPMの情報を持っているとは限りませんし、映像を見てなんとなくBPMを計算するのは人間がぱっとやるには難しすぎます。
総合的にこの方法は現実的ではないと判断しました。

方法②映像に拍の情報を持たせる

BPMとはbeat per minuteつまり1分間に何拍なのかという情報です。
つまり映像に拍の情報があれば、その映像が1分間のうちにどこまで再生出来れば良いのかというのが計算できます。

条件
合わせたいのは120BPM
使用する映像は4秒
その映像は4拍でループする(1から4までカウントする映像をイメージしてください)
とします。

こんな映像

最終的に知りたいのはこの映像を何秒以内に再生しきる必要があり、そのために再生速度はいくらにする必要があるのかです。

簡単に計算してみましょう。
まずはBPMから1拍の秒数を計算します。
120BPMの場合1分間に120拍が必要なので
1分/120をすることで1拍に必要な時間がわかります。
60/120 = 0.5
今回1拍に必要な時間は0.5秒です。

次に映像が何秒で1ループすればBPMと一致するかを計算します。
今回は1拍0.5秒必要なので、4拍分再生する場合は2秒必要です。
つまり映像が2秒でループすれば良いという事です。

次に映像を何倍にすれば2秒で収まるかを計算します。
今回映像の時間は4秒です。単純に4(映像の本来の時間)/2(今回映像をループさせたい時間)で2倍になります。

つまり今回は、映像を2倍速することでBeat Syncされます。

コード(C#)

実際の実装を元に記事用に少し調整しています。
コードの方がわかりやすい方に向けてそれっぽい感じで書きました。コピペでは動かないと思います。(メソッドも適当です)

public void BeatSync(VideoPlayer videoPlayer,float bpm,int beat)
{    
    //BPMから1拍の秒数を計算する→120の場合は0.5秒(60/BPM)
    var beatTime = 60f / bpm;
    
    //beatTime×beatでループ時間を計算する→例えば0.5*4で2秒
    var loopTime = beatTime * beat;
    
    //例えば映像が10秒なら、それを2秒で再生する必要がある→10/2で5倍速
    var videoDuration = videoPlayer.streamDuration;
    var speed = videoDuration / loopTime;
    
    //videoPlayerに再生速度を適用させる
    videoPlayer.speed = Mathf.Clamp((float)speed, 0, 5f); 
}

UI/UX

デザイン

Beat Syncに関するUIはレイヤーウィンドウの右下に集約されてます。
右下かどうかにあまり意味は無いです。
プロジェクトファイルの互換性の問題からレイヤーウィンドウのサイズを変更することが出来ず、機能追加を想定して念のため空けておいたスペースを使っているだけです。

拍を選んだ理由とUI/UX

まずはベースの体験部分について話します。
上記でも説明しましたが、映像をBPMに同期させる場合何かしら映像に情報を付け加える必要があります。基本的にはBPMか拍です。(VDMXの場合は逆の考え方で4拍で何ループするかという情報を追加するようです。)
VJには仕込みフェーズとプレイフェーズがあります。
仕込みフェーズはインポートする映像素材選定やエフェクトの準備、MIDIマッピングなどのプロジェクト作成です。
プレイフェーズは単純にイベントでプレイしている状態です。VJソフトの各機能は仕込みフェーズとプレイフェーズどちらかのために存在していると考えています。
例えばエフェクトを組む機能は仕込みフェーズですが、エフェクトをMIDIでコントロールする機能はプレイフェーズのためのものです。

Beat Syncという機能は性質上、映像と拍のデータを紐づけるという仕込みが必要になります。しかし、VJのための映像素材は何百、何千とありそれぞれに紐づけている時間はありません。これではBeat Syncという機能は使われないと思いました。

もし拍という情報であれば、少し時間をかけることでVJプレイ中に計算することが出来ます。実際に下の映像で体験してみてください。
シークバーがループするまでに映像が何回動いてるかを脳内で数えることが出来ます。

1ループで4拍の映像

VJプレイ中は周りに音楽が流れているため、そちらに意識を持っていかれてしまいますが、一瞬音の事を忘れて少し集中して数えるだけで拍の情報を得て設定することが出来ます。
そしてその拍を設定するボタンはレイヤーウィンドウに紐づけられているため数クリックで済みます。
また、このデータは映像に紐づけられて自動で保存されます。つまりVJプレイ中に自然と仕込みが行われる設計になっており、VJをすればするほどライブラリが育っていきます。
こうすることでイベント前日に何百、何千もある映像素材に拍の情報を入れる必要を無くしました。

ボタン配置


拍の設定を2倍、1/2倍に変更している

これはBeat Syncを有効にした状態で、拍の設定を変更しています。
短い動画のためわかりにくいですが、
を2倍に増やしたときは映像の再生速度が遅くなり
を1/2倍に減らしたときは映像の再生速度は速くなります
つまり、「(拍を)増やしたのに(再生速度が)減る」という不思議な体験になってしまいました。
ここは単純にボタンの配置を反転させて、感覚的にわかりやすいUIにしようか検討しましたが結局この形になりました。
理由としては、VJや音楽に慣れてくると「拍が増えると再生速度が遅くなるのは当たり前」と認識出来ると思ったからです。ここはあえて第一印象としては違和感を残しておき、慣れてもらうことでより(VJや音楽的な)拡張性、将来性を優先しました。

シンク解除のUI

Beat Syncの解除には二つの方法があります。
・Beat Syncトグルをクリック(or MIDIで操作)して切り替える方法
・再生速度をマウス(or MIDI)で上書きして解除する方法

Beat Syncをクリックする方法
再生速度を上書きする方法

この二つになった理由は単純で、VJはめちゃくちゃ忙しいからです。
もちろんVJスタイルにも寄りますが、
「BPM Syncしてたけど、普通に手動で調整したいな」というときに
解除→再生速度を調整
は単純に手間が増えますし、VJ中の人間にはコストが高すぎると判断しました。
また上書きする場合はSyncされている状態からシームレスに速度を変更することが出来るというメリットもあり、総合的に良いと判断しました。

再生速度をロックが出来ないというデメリットもありますが、単純に触らなければ良いだけなので大きな問題ではないと考えています。
※問題が多そうならロック機能の追加も考えています。

どこまでシリアライズするか

最後に設定した拍のデータなどをどのレベルまで保存、読み込みするかについてです。

Global Tempo
SynapseRack全体のBPMを管理する機能

案①
・拍の情報と追加でBPM Syncしていたという情報も保存する
つまり一度Syncした映像は、再度読み込んだ時にSyncした状態で再生されるという設計です。
この場合明らかにSyncを目的とした映像の場合メリットが多く、VJプレイ中の無駄が減ります。逆に、Syncを目的としてない映像をSyncした状態で放置していた場合、次回もSyncされていて困るというデメリットがあります。
また、Syncさせるためには現在のDJがかけているBPMの情報が必要です。
SynapseRackの場合Global Tempo(上の画像参照)でタップテンポすることでBPMを算出出来ますが、VJ中に毎回これを正しく行っているとは限りません。BPMを無視して筋肉VJしたい時もあります。
結果こちらのパターンはSyncしてほしくないときに勝手にSyncしていて解除する手間が増えると判断しました。

案②
・拍の情報だけ保存する
この場合、Syncさせたい場合は毎回映像読み込み後にSyncトグルを押す必要が出てきますが、そもそも映像選択中に「これをSyncしたいかどうか」を考えてることが多いと思います。つまり読み込んでSyncを押すという動作はあまり負担にならないと考えました。
また似たような話にはなりますが、そもそもSyncさせるにはタップテンポでBPMを算出している必要があります。つまりSyncする前にタップテンポを行っているはずで、「タップテンポ→映像を読み込む→Syncボタンを押す」という流れはルーティンになり負担は少ないという結論になりました。

結果案②の拍の情報だけ保存する実装になっています。

終わりに

最後まで読んでいただきありがとうございます。
せっかくのAdvent Calendarなので、勢いで書きました。誤字脱字、内容等に問題があれば気づき次第修正します。

SynapseRackは無料体験版からVJデビューが出来ますのでぜひ使ってみてください!(ロゴの透かしが出ないためイベントで利用出来ます。)

自己紹介

Sainaと言います。普段はプリレンダVJ、ジェネVJ、ソフトウェア開発、シェーダーお絵描きなどをやります。
Twitter
https://twitter.com/SainaKey
ポートフォリオ
https://www.sainakey.com/


この記事が気に入ったらサポートをしてみませんか?