プレゼンモード
再生
← / →で移動
fでフルスクリーン
escでおわる
id:hitode909です.Kyoto.なんか #5 に飛び入りでLTするための資料です.
ブラウザでVJデビューしよう #kyotoasterisk
- Kyoto.なんか #5
- hitode909
hitode909
- はてなで働いている
- ブラウザが好き
アジェンダ
- 先日ブラウザでVJデビューした
- 始め方を伝授
- 皆様がVJデビューするのがゴール
VJとは
- Video JockeyまたはVisual Jockey
- Disc Jockeyが曲を流すので
- VJが映像を出す
- 客が盛り上がれば成功
手法
- HTML, JSを書く
- VSCode Live Server拡張を使う
- その場で編集、Live Reloadできる
- 終わったらGitHub Pagesにデプロイ
ブラウザでVJをやる強み
- インターネットにつながっている
- 無限の素材
- ブラウザのAPIを使える
- 使い慣れたinput
- なんでもブラウザでやる時代になってきている
- プレゼンもブラウザで
- 音楽聞いたり
- 映像をテレビで再生したり
ブラウザで絵を動かす
- ほっといて動くもの
- imgタグ
- アニメーションGIF
- videoタグ
- 動画
- imgタグ
- 自力で動かすもの
- 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; } }
曲の音量
- マイクの入力を取れる
- 各周波数の値を取れるので平均を計算すると音量になる
- ちゃんとしたソフトウェアなら特定の周波数だけ拾える
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; } }
何を表示するか
- 文字
- テキストエリアに入力した文字を出す
- YouTube
- GIPHY
- 検索APIがあるのでキーワードにマッチするGIFを表示できる
- https://developers.giphy.com
- 色
- 単色で塗りつぶすと盛り上がる
コツ
- 検索クエリを入力して、コンテンツを差し替えできるようにしておく
- 京都のイベントなら京都の映像を流せるように
- タイミングをバラバラに管理せず一元管理する
- タイミングが揃ってないと気持ち悪い
- 「毎フレーム動く関数」「ビートごとに動く関数」という単位で実装できるように
- ↓コンテンツを足したいときはこれを継承する
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があるか確認しておく
- バッテリーがすごい勢いでなくなる