Node For Maxを使って、YouTubeの動画をJitterで再生する。

#はじめに
今回は、Max8の新機能である"Node For Max"(以下"n4m")にチャレンジしたいと思います。

この記事は「深く理解する!」というよりも、「とりあえずやってみる！」を目標にしています。

ちなみに、僕自身が"Node.js"初心者なので不備が多々あるかと思います。
どうぞ、ご指摘ください...！

環境: macbook pro(OS High Sierra), Max(ver8.0.8)

#今回やること
今回は僕のような「node.js初心者、Maxはなんとなくわかるよ」って感じの方向けの記事です。
よって、node.jsの環境を整えるところの紹介からスタートします。
そして、Maxパッチの準備、jsファイルの作成を経て、最終的には、任意のYutubeの動画をjitterで再生します。

上にも書きましたが、とりあえず動かすことを目標にしています！
詳しい解説は、リクエスト等頂ければ追記したいと思います。(頑張って調べます。笑)




#参考資料
いろんな方のサイトを見て、参考にさせて頂いています!

特に日本語でn4mの記事を書かれているのは余湖さん(@Yuichi_Yogo )くらいのようで、コード含め特に反復して読ませて頂いています。n4mに限らず、本当に尊敬してます。
具体的にはMax Artist Patches内で紹介されている[機械学習パッチ](https://rittor-music.jp/sound/magazine/max/1909)や、Qiitaでの記事([天気APIの記事](https://qiita.com/Yuichi_Yogo/items/a439964034be4e200026)と[Electronの記事](https://qiita.com/Yuichi_Yogo/items/7d34560d55f201256de1))を見てみると良いかと思います。

また、[Maxの公式サイト](https://docs.cycling74.com/max8?contentp=Node%20For%20Max&contentg=vignettes)や"[Znibble~](https://www.znibbl.es)"さんのサイトは英語にはなりますが、とても勉強になりました。
今回はその"Znibble~"さんのサイト内にある"[WATCH YOUTUBE VIDEOS](https://www.znibbl.es/video/10-node-in-max-or-01-watch-youtube-videos)"を元に、補足等しながらn4mにチャレンジしたいと思います。
動画内の実験コードや動画再生に関係なさそうなところは、割愛させて頂きます!

どうぞ、よろしくお願いします。

##その前に(参考として)
###Node For Maxとは?
n4mは、Max8からの新機能で、MaxとNode.jsの通信を可能にしてくれるのものです。以前からあった"jsオブジェクト"とは別物であることにご注意ください。

node.jsを使うメリットは多々ありますが、"npmによるパッケージ管理"、"APIを簡単に利用できる"などが挙げられます。また、余湖さんが紹介しているように"ElectronによるUI設計"ができることも大きな利点と言えるでしょう。

それぞれにどんなメリットがあるのか、より詳細に知りたい方はnode.js自体について調べてみましょう!

#やってみよう
それでは、実際にやってみましょう。

##事前準備
事前準備としてnode.jsをPCにインストールします。
Max内にNodeが入っているらしいのでインストールする必要はありませんが、node.jsファイル単体の開発などの時に役立つと思います。

さっそく他の方の記事を参照しますが、僕は[この方の記事](https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09)を参考にしました。
最終的にターミナルで

```
$ node -v
```

と入力して、
vO.O.O
とかでたら、インストール完了です。
また、同様に

```
$ npm -v
```
と入力して
O.O.O
と出てきたら、npmも無事にインストール出来ています!
###npmとは
npmとは"Node Package Manager"の略で、上にも書きましたがnode.jsのパッケージを管理するためのシステムです。
これを使うとエクスターナルのオブジェクトやプラグインなどを、一括でインストールしてくれます。
すごい！

##npmによる準備
それでは、さっそくこのnpmを使って準備をしましょう。
ターミナルで任意のディレクトリに入り、フォルダを生成します。(僕はDesktopに作りました。)

```
$ mkdir youtube
```

今回は"youtube"というフォルダを作成しました。
再びcdでyoutubeフォルダの中に入り、以下のコマンドを実行します。(詳細は下の方で紹介しています。)

```
$ npm init
```

すると、いろいろと表示されて

```
package name: (youtube)[]
```

と聞かれると思います。
このときデフォルトでは、現在の階層のフォルダ名になっていると思います。
Maxで実行するjsファイルのファイル名を何にするか聞かれているので、今回は"watch-youtube"とします。(任意のファイル名で大丈夫です。)

その後は2回程enterを押して、

```
entry point: (index.js)[]
```

と聞かれたら、さっきと同じ名前を入力します。
僕の場合は"watch-youtube"です。

(デフォルトでは、index.jsというファイル名ですが、そこに.jsのファイルがすでにある場合は、そのファイル名が表示されていると思います。
その場合も無視して、先ほど入力したものを入力してください。)

その後も何度かenterを押して、最後に

```
Is this OK?(yes)
```

と聞かれるので、再びenterを押します。
これで、このフォルダ内にパッケージをインストールする準備ができました。
自動的に、フォルダ内に"package.json"というファイルが生成されていると思います。
このファイル内には、今ターミナルで入力した内容が反映されています。

npm initについては、[こちらの記事](https://techacademy.jp/magazine/16151)を参考にしてみてください。
"init"とはinitializeの略で、文字通り初期化処理を行っています。

さあ、それではnpmを使ってパッケージをインストールしてみたいと思います。

今回は["ytdl-core"というパッケージ](https://www.npmjs.com/package/ytdl-core)をインストールします。
そのままのディレクトリで

```
$ npm install --save ytdl-core
```

と入力するだけです。

簡単すぎて、ちょっと怖いですね。

あとは、

```
$ touch watch-youtube.js
```

と入力すると同じディレクトリに"watch-youtube.js"というjsファイルが生成されます。
この"watch-youtube.js"ファイルに処理を記述していくことになります。

ここで、jsファイルの編集の前にMaxパッチをやっていきましょう!

##Max Patch
Maxのほうは、以下の画像を参考にしてパッチして頂ければと思います。([下](#コードサンプル)にダウンロードリンクを貼っておきます。)
正解例を丸写しさせる感じで申し訳ないです。
ちなみに、先にこのMaxパッチを上で作成したディレクトリに保存しなければ、node.scriptオブジェクトでjsファイルを指定してもエラーになると思います。
正しい場所に保存してから、maxパッチを立ち上げなおすと正常に読み込まれます。

![スクリーンショット 2019-09-13 0.57.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474709/774f90a7-b3db-1b35-2afd-9e41ca52f3d3.png)




パッチはこんな感じです。
Znibble~さんの動画内ではjit.movieに対してqmetroを入力していたのですが、なくても動くため今回は使っていません。

一番上のメッセージのopen後に好きなyoutubeの動画のurlを貼ってください。

この段階では、jsファイルに何も書いていないため、一番上のメッセージをクリックしても、なにも起きません。
それでは、いよいよjsファイルに処理を書き込みます。

##JavaScript
こちらも正解例の提示になってしまいますが、こんな感じです。
動画内のURLをほぼ丸々コピーしています。

```js:watch-youtube.js
const maxApi = require('max-api');
const ytdl = require('ytdl-core');

maxApi.addHandler('open', (url) => {
    ytdl.getInfo(url)
        .then(info => {
            let format = ytdl.chooseFormat(info.formats, {});
            maxApi.outlet("download_url", format.url);
        })
        .catch(() => {
            maxApi.post('Error fetching url: ${url}');
        })
});
```

*--(追記)--*
上2行の"const OO = require('XXX');" は、XXXというモジュールを呼び出しOOという名前の変数に代入する、という意味です。
Maxでn4mを使うときは、ほぼ必ずこの"max-api"というモジュールを呼び出します。

"maxApi.addHandler('OO', (XXX) =>{}" では、Maxパッチでnode.scriptに入力したメッセージリストの最初の文字列が"OO"だった場合、その次の文字列を引数として受け取り"XXX"という変数に代入して、{}内の処理を行います。
今回の場合を例に説明すると、Maxパッチ内にてnode.scriptに入力しているメッセージが"open https\://www~"というリストになっています。このメッセージが入力された時に処理を実行するには、まずwatch-youtube.jsにて"maxApi.addHandler('open', (XXX) => {...}"とする必要があります。
また、入力したリストのopen以下の部分("https\://www~"の部分)を引数として利用したいため、"maxApi.addHandler('OO', (url) => {...}"とすることでこの文字列を"url"という変数に代入しています。
もちろんMaxパッチから引数をスペース区切りで増やして送り、"maxApi.addHandler('OO', (XXX, VVV) =>{}"などのように()内でコンマ区切りにして引数を増やすことも可能です。

真ん中あたりの"max.Api.outlet();"の()内の内容が、Maxパッチ内のnode.scriptから出力されます。
内容は",(コンマ)"で区切ることで、リストとしてまとめて出力することができます。

また、"max.Api.post();"の()内の内容は、Max consoleの方に出力されます。
*--------*

これを保存すると、いよいよ準備完了です!

#いざ、再生
あとは、一番上のメッセージをクリックするだけです！

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">test &quot;Node For Max&quot;<br>Playing YouTube video!<a href="https://twitter.com/hashtag/Max?src=hash&amp;ref_src=twsrc%5Etfw">#Max</a> <a href="https://twitter.com/hashtag/n4m?src=hash&amp;ref_src=twsrc%5Etfw">#n4m</a> <a href="https://twitter.com/hashtag/Jitter?src=hash&amp;ref_src=twsrc%5Etfw">#Jitter</a><a href="https://t.co/ThBl9ofYXR">https://t.co/ThBl9ofYXR</a> <a href="https://t.co/uDWl2Wzmao">pic.twitter.com/uDWl2Wzmao</a></p>&mdash; LUDO TAKEBE (@for_LUDO) <a href="https://twitter.com/for_LUDO/status/1172183116644925441?ref_src=twsrc%5Etfw">September 12, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


無事に再生されると、感動ですね...!

###サンプルコード
[こちら](https://github.com/LUDO-TAKEBE/n4m-watch_youtube_video)に僕が今回作成したファイル一式をアップロードしています。
ご活用ください。
また、今回はせっかくなのでnpmでインストールできるものは、そちらで準備していただこうと思います。
youtube.maxpatというファイルを開いたら、まずは"script npm install"というメッセージをクリックしてください。(もちろん、ターミナルで"npm install"でも構いません。)
そうすると必要なパッケージをインストールしてくれます。
あとは任意のyoutubeの動画のリンクに書き換えて、そのopenメッセージをクリックすると再生されます。

####サンプルコードでエラーが出た場合
このサンプルコードをダウンロードしてエラーが出た方は、この記事内の操作を全て一からやると確実です。
が、少し面倒だと思いますので、以下の方法をお試しください。

* ダウンロードしたファイルの中に“node_modules”というフォルダと”package-lock.json”と”package.json”という2つファイルがあれば、削除する
* ターミナルでダウンロードしたフォルダの階層内に移動
* この記事内の”npmによる準備”の部分の”npm init”から”npm install --save ytdl-core"までを実行する
* maxを開いて、”script start”をクリック→urlのメッセージをクリック

これで実行できると思います。
ちなみに、これはストリーミングではないのでyoutubeのライブ配信などの動画は使用できませんのでご注意ください。(ライブ配信終了後のアーカイブは可能です。)


#最後に
今回はMax内でyoutubeの動画を再生させてみましたが、いかがだったでしょうか?
この動画再生だけでは、そこまで意味がないかもしれません。
しかし、youtubeの動画にjitterでエフェクトをかけたり、同時再生させたり、またはn4mを使った全く違った様々な応用も考えられます。
今後はn4mを使ったさらに面白いもの、便利なものが必ず出てくるはずです。

今回の記事が、その一助になれば幸いです。

冒頭にも書きましたが、ご指摘やさらなるリファレンスのご教授などお待ちしております。
どんどんお寄せください。