hitode909の日記

以前はプログラミング日記でしたが、今は子育て日記です

ブラウザでVJデビューしよう #kyotoasterisk

プレゼンモード
再生
← / →で移動
fでフルスクリーン
escでおわる

id:hitode909です.Kyoto.なんか #5 に飛び入りでLTするための資料です.

ブラウザでVJデビューしよう #kyotoasterisk

  • Kyoto.なんか #5
  • hitode909

hitode909

  • はてなで働いている
  • ブラウザが好き

アジェンダ

  • 先日ブラウザでVJデビューした
  • 始め方を伝授
  • 皆様がVJデビューするのがゴール

VJとは

  • Video JockeyまたはVisual Jockey
  • Disc Jockeyが曲を流すので
  • VJが映像を出す
  • 客が盛り上がれば成功

VJデビュー

妻がDJデビューすることになったのでその流れでVJデビューすることになった
smtppp.club

f:id:hitode909:20190803232936j:plain

f:id:hitode909:20190803232939j:plain

f:id:hitode909:20190803233001j:plain

手法

  • HTML, JSを書く
  • VSCode Live Server拡張を使う
    • その場で編集、Live Reloadできる
  • 終わったらGitHub Pagesにデプロイ

ブラウザでVJをやる強み

  • インターネットにつながっている
    • 無限の素材
  • ブラウザのAPIを使える
  • 使い慣れたinput
  • なんでもブラウザでやる時代になってきている
    • プレゼンもブラウザで
    • 音楽聞いたり
    • 映像をテレビで再生したり

ブラウザで絵を動かす

  • ほっといて動くもの
    • imgタグ
      • アニメーションGIF
    • videoタグ
      • 動画
  • 自力で動かすもの
    • requestAnimationFrame
    • CSS transition

曲と合わせる

  • 曲のビートに合わせて動く
  • 曲の音量に反応して動く

ビートに合わせる

  • 曲に合わせてTAPボタンを4回押す
  • 時間の差分から求める
  • タップした瞬間にもビートが変わったことにすると、ずれた状態からリカバリしやすい
    calculate() {
        this.tappedAt.push(new Date().getTime());
        if (this.tappedAt.length > 4)
            this.tappedAt.shift();
        if (this.tappedAt.length < 2)
            return;
        let durations = 0;
        for (let i = 0; i < this.tappedAt.length - 1; i++) {
            durations += this.tappedAt[i + 1] - this.tappedAt[i];
        }
        durations /= this.tappedAt.length - 1;
        this.input.value = durations;
    }
}

曲の音量

  • マイクの入力を取れる
  • 各周波数の値を取れるので平均を計算すると音量になる
    • ちゃんとしたソフトウェアなら特定の周波数だけ拾える

blog.sushi.money

class VolumeAverage {
    constructor() {
        navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then((stream) => {
            const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            const analyser = audioCtx.createAnalyser();
            const source = audioCtx.createMediaStreamSource(stream);
            source.connect(analyser);
            this.analyser = analyser;
            this.data = new Uint8Array(analyser.frequencyBinCount);
        });
    }
    getVolume() {
        if (!this.data)
            return 0;
        this.analyser.getByteFrequencyData(this.data);
        let sum = 0;
        const length = this.data.length;
        for (var i = 0; i < length; i++) {
            sum += this.data[i];
        }
        return sum / length;
    }
}

完成

  • 曲のビートに合わせて動く
  • 曲の音量に反応して動く
  • インターネットのリソースを表示すれば完成

https://hitode909.github.io/sketch20190802vj/
f:id:hitode909:20190824114451p:plain

何を表示するか

コツ

  • 検索クエリを入力して、コンテンツを差し替えできるようにしておく
    • 京都のイベントなら京都の映像を流せるように
  • タイミングをバラバラに管理せず一元管理する
    • タイミングが揃ってないと気持ち悪い
    • 「毎フレーム動く関数」「ビートごとに動く関数」という単位で実装できるように
    • ↓コンテンツを足したいときはこれを継承する
class Animator {
    constructor(screenName) {
        this.screenName = screenName;
        this.screen = document.querySelector(`.screen.${screenName}`);
        this.isActive = false;
    }

    onFrame() { }
    onBeat() { }
    onBeatTogggleDisplay(parameters, i) {
        const screenKey = `display-${this.screenName}-${i % 4}`;
        this.isActive = parameters[screenKey];
        this.screen.classList.toggle('hidden', ! this.isActive);
    }
    onParametersChange(parameters) { }
}

注意

  • 会場にWi-Fiがあるか確認しておく
  • バッテリーがすごい勢いでなくなる

まとめ

  • ブラウザでVJするのは簡単
  • マイク入力を取れる、動画を簡単に読み込めるなど、テクノロジーが時代に追いついてきている
    • 10年前なら難しい
  • みなさまやりましょう

github.com