見出し画像

VDMX5とYouTubeでVJ環境構築(力技)

ワンオペVDJ(DVJ)においてローカル外の映像をその場で出したい!
以下の記事で検討を行った『YouTubeの再生位置をMIDIコンで操作する』を実装出来たので備忘録として記事にします。


0. 概要

今回のゴールを大雑把に説明すると「Javascript制御でMIDIコンからyoutubeの再生位置を操作する」です。

イメージは以下です。

1. Tampermonkeyの導入

今回の動作環境は以下になります。
OS:macOS Monterey
ブラウザ:Google Chrome バージョン 126.0.6478.183

まず初めにJSの動作環境として「Tampermonkey」を導入します。
こちらはChromeのアドオンで色々便利にスクリプトを実装、動作するみたいです。

導入についての詳細は各々調べてください。(Chromeにアドオン追加するだけです)

2. MIDIコンの入力値調査

Tampermonkeyの導入が済ませたら次に操作したいMIDIコンの入力信号を調査します。
今回使用しているMIDIコンは「DJ2GO2 Touch」です。

PCにMIDIコンを接続します。
このとき接続するMIDIコンは1台のみにします。(複数台接続するとコード的に不都合があるようなので)

ChromeでMIDI信号を取り扱う際の下準備が必要な場合があります。
Chromeが最新版ではない場合、chrome://flags/のMIDIに関するフラグを有効化する必要があります。(最新版ではこの項目が廃止され、予め有効になっているらしいです)

Chromeのアドレスバーに「chrome://flags/」を入力し、エンターキーを押下します。
Use Windows Runtime MIDI API」の項目を探し、Enableにします。

これで下準備完了です。

Tampermonkeyに以下のスクリプトを追加します。

// ==UserScript==
// @name         midiKeyTest
// @namespace    http://tampermonkey.net/
// @version      2024-07-28
// @description  try to take over the world!
// @author       You
// @match        https://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

function onMIDISuccess(midiAccess) {
    const input = midiAccess.inputs.values().next(); // デバイスが 1台だけつながっている前提
    input.value.onmidimessage = onMIDIMessage;
}
function onMIDIFailure(msg) {
  console.log("Failed to get MIDI access - " + msg);
}

function onMIDIMessage(message) {
    const data = message.data;
    console.log(data);
}

(
    function() {
        navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
    }
)()
;

ソースは以下のサイトを参考にしました。


確認するためのサイトはどこでも大丈夫なので、試しにGoogleのトップページで行います。

先ほど追加したスクリプトを起動すると許可を求められるので許可します。

ブラウザの開発者メニューよりコンソールを開いてMIDIコンの入力値を確認します。

コンソールログにMIDI信号の値が出力されています。
ここから必要な操作に対するMIDIの値を控えます。

解析結果より以下の情報が判明しました。
[左Deck]
▼ターンテーブル左回し:176, 6, 127
▼ターンテーブル右回し:176, 6, 1
▼CUEボタン:144, 1, 127
▼PLAY/POSE:144, 0, 127
[右Deck]
▼ターンテーブル左回し:177, 6, 127
▼ターンテーブル右回し:177, 6, 1
▼CUEボタン:145, 1, 127
▼PLAY/POSE:145, 0, 127

この情報を元に本チャンのコーディングをやっていきます。

3. コーディング

※プログラム初心者のコーディングです!
細かい例外処理やお作法等は考えていないので必要であれば各々追加してください!

早速ですがコードは以下になります。

// ==UserScript==
// @name         leftDECK_for_DJ2GO2TOUCH
// @namespace    youtubeskip_for_DJ2GO2TOUCH
// @version      0.1
// @description DJ2GO2 TOUCHによるyoutube再生時間操作
// @author you
// @match https://www.youtube.com/*
// @grant none
// ==/UserScript==

function onMIDISuccess(midiAccess) {
    const input = midiAccess.inputs.values().next(); // デバイスが 1台だけつながっている前提
    input.value.onmidimessage = onMIDIMessage;
}
function onMIDIFailure(msg) {
  console.log("Failed to get MIDI access - " + msg);
}

function onMIDIMessage(message) {
    const data = message.data;
    const keyData = data[0] + ":" + data[1] + ":" + data[2];
//    console.log(keyData);

    // 巻き戻し
    if (keyData === "176:6:127") {
        var ytPlayer = document.getElementById("movie_player");//前準備
         currentTime = ytPlayer.getCurrentTime();//現在の再生時間を取得
        ytPlayer.seekTo(currentTime - 0.03);// 0.03秒戻る
    }
    // 早送り
    if (keyData === "176:6:1") {
        ytPlayer = document.getElementById("movie_player");//前準備
        currentTime = ytPlayer.getCurrentTime();//現在の再生時間を取得
        ytPlayer.seekTo(currentTime + 0.03);// 0.03秒進む
    }
    // 再生(CUEボタン)
    if (keyData === "144:1:127") {
        ytPlayer = document.getElementById("movie_player");//前準備
        currentTime = ytPlayer.playVideo();//再生
    }
    // 停止(PLAY/POSE)
    if (keyData === "144:0:127") {
        ytPlayer = document.getElementById("movie_player");//前準備
        currentTime = ytPlayer.pauseVideo();//停止
    }

}

(
    function() {
        navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
    }
)()

;
// ==UserScript==
// @name         rightDECK_for_DJ2GO2TOUCH
// @namespace    youtubeskip_for_DJ2GO2TOUCH
// @version      0.1
// @description DJ2GO2 TOUCHによるyoutube再生時間操作
// @author you
// @match https://www.youtube.com/*
// @grant none
// ==/UserScript==

function onMIDISuccess(midiAccess) {
    const input = midiAccess.inputs.values().next(); // デバイスが 1台だけつながっている前提
    input.value.onmidimessage = onMIDIMessage;
}
function onMIDIFailure(msg) {
  console.log("Failed to get MIDI access - " + msg);
}

function onMIDIMessage(message) {
    const data = message.data;
    const keyData = data[0] + ":" + data[1] + ":" + data[2];
//    console.log(keyData);

    // 巻き戻し
    if (keyData === "177:6:127" ) {
        var ytPlayer = document.getElementById("movie_player");//前準備
         currentTime = ytPlayer.getCurrentTime();//現在の再生時間を取得
        ytPlayer.seekTo(currentTime - 0.03);// 0.03秒戻る
    }
    // 早送り
    if (keyData === "177:6:1" ) {
        ytPlayer = document.getElementById("movie_player");//前準備
        currentTime = ytPlayer.getCurrentTime();//現在の再生時間を取得
        ytPlayer.seekTo(currentTime + 0.03);// 0.03秒進む
    }
    // 再生(CUEボタン)
    if (keyData === "145:1:127") {
        ytPlayer = document.getElementById("movie_player");//前準備
        currentTime = ytPlayer.playVideo();//再生
    }
    // 停止(PLAY/POSE)
    if (keyData === "145:0:127") {
        ytPlayer = document.getElementById("movie_player");//前準備
        currentTime = ytPlayer.pauseVideo();//停止
    }
}

(
    function() {
        navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
    }
)()

;

ソースを書くにあたって以下のサイトを参考にしました。


内容はほぼ一緒ですが2ソースあります。
今回の実装・動作方針として以下としています。
・ブラウザ2つを左右Deckと見立てて操作する
・左ブラウザを左Deck、右ブラウザを右Deckで操作する
・各ブラウザを別スクリプトで制御する

めっちゃ力技です。全然スマートじゃないけど知識が足りないのでこれが限界でした。

このソースで実装している動作は以下になります。
・ターンテーブルで再生位置を操作
・CUEボタンで動画再生
・PLAY/POSEボタンで動画一時停止

4. 動作テスト

動作テストを行います。
Chromeを2つ起動し右ブラウザに「rightDECK_for_DJ2GO2TOUCH」、左ブラウザに「leftDECK_for_DJ2GO2TOUCH」を適用します。

同一サイトで別々のスクリプトを適用するのが通常の動作でない?(後から適用した方に引っ張られる事がある)ので上手いことリロードしたりして、右ブラウザには右用、左ブラウザには左用のスクリプトが適用されるようにします。
ここでも力技です。

JSの適用が完了したらMIDIコンを操作して想定通りの動きをするかチェックします。
通信環境やマシンスペックによってはターンテーブルの操作に対して映像のスキップが追いつかないこともありますが、その点は御愛嬌で。
リップシンク程度の細かい区間でのスキップくらいでしたら問題なく使えると思います。

チェックが完了したらVDMXにyoutubeの映像を取り込みます。

5. VDMXへ導入

VDMXにyoutubeの映像を取り込む便利な方法は沢山ありますが(ピクチャーインピクチャーなど)、今回の方法では少しネックな部分です。

VJ映像をyoutube映像→youtube映像へ繋ぐことを想定して2ブラウザ体制にしています。
ですがピクチャーインピクチャーは2つ立ち上げることが不可能です。
ですがここでも力技です。

1つのブラウザはピクチャーインピクチャーで取り込み、1つのブラウザは範囲指定で映像を取り込みます。

各取り込みの手段は検索すれば参考サイトが沢山出てくるのでここでは省略します。

諸々設定し終わった状態が以下になります。


以上、長文になりましたがこれでMIDIコンでyoutubeの再生位置を操作することが出来ました。
その場ノリプレイでのVJ映像問題をどうにかしたい」を解決しようと色々とやってみました。

技術的には実現しましたが、果たして実践導入してスムーズにVDJ出来るのかは不明です。
まずはこのシステムに身体を慣らしていければと思いました()。

ex. おまけ

おまけで上記システムをもっと楽に使えるように、youtubeの検索を楽に出来るようにする追加ソースをそのうち記事にする予定です。






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