初心者がNode.js(Express)でYouTubeの動画をダウンロードできる機能をつくる。

この記事は、【 [可茂IT塾 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/kamo-it) 】の4日目の記事です。

# 初めに
Node.jsも記事書くのも初心者なので、もしかしたらコードや説明の間違いや、記事が読みにくいかもしれませんが、お許しください・・・
また、こちらは全て自分の動画で試しております。
## つくるもの
フロント（ブラウザ）側：URLを入力
バックエンド（サーバー）側：それに応じた動画をmp4でダウンロードして送り返す

## 流れ
1. サーバーでHelloWorldがでるところまでつくる。
1. URLをおくるためのページを用意する。
1. URLを受け取って、その動画をダウンロードする



## 環境
どれも新しいversionでいいと思います。

$ npm -v
6.14.11

$ node -v 
v14.16.0

## 作業開始

任意（今回はデスクトップ）の場所に作業していくフォルダを作りましょう。

そのフォルダをVSCodeで開きます。
さて、まずは初期化設定をしましょう！
VSCordだったら、ターミナルってとこに打ちます！

```
$ npm init
```

するとなんかごちゃごちゃ聞かれますが、今回はEnter連打しちゃいましょう。
プロジェクトの設定をしてるよ～みたいな感じです・・・
次にexpressというモジュールを入れていきます。
今はなんとなく、expressっていう機能をインストールするんだ！って思ってればＯＫ！

```
$ npm install express
```

すると以下のようにnode_modulesとpackage-lock.jsonのように出てくると思います。
※package.jsonもあるとおもいます。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1544861/82960ae7-a31e-528d-d169-333c4a4a8a7f.png)


### とりあえずHelloWorld
正常にサーバーに接続できるかのテストとして、HelloWorldを表示するところまでします。
まずはapp.jsというファイルを作ります。
これからはこのファイルをいじっていきます！

```app.js
// Expressを使う
const express = require('express');
const app = express();

// Hello Worldを出力する
app.get('/', function (req, res) {
    res.send("Hello World");
});

// 3000ポートでサーバーを起動する
app.listen(3000);
console.log('3000ポートでサーバー起動したぞ！');
```
### 実行
ターミナルで、

```
$ node app.js
```
では、ブラウザで確認しましょう。
localhost:3000　で結果を見れます！

:::note info
localhost = 127.0.0.1
:::

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1544861/d20fb1b0-fe0c-f162-bfb6-578421bd8ba7.png)

できましたね！！

:::note info
サーバーを停止するには、ターミナルの上でCtrl＋Cを押します。
:::

### URLをサーバーに送るためのページを用意する

今はlocalhostでサーバーにアクセスしましたが、
ボタンを押した時にURLを送れるようにするために、ページを作りましょう！

public　というディレクトリをつくり、その下に　index.html　を作りましょう。

それぞれ編集していきます。

```index.html
<!DOCTYPE html>
<html>

<head>
    <title>Test</title>
</head>

<body>
    <form action="http://127.0.0.1:3000/download" method="get">
        <input class="URL-input" name='url' placeholder="URL">
        <button type='submit' class="button">download</button></a>
    </form>

</body>
</html>
```
これはざっくりいうと、入力したurlという値を127.0.0.1というIPアドレスの3000番のポートのdownloadに送るよ！ってフォームタグに書いてあるのです。

### URLを受け取って、その動画をダウンロードする

さて、いよいよサーバーの処理を書いていきましょう！

```app.js
// ExpressをNode.jsから使えるようにする
const express = require("express");
// expressの機能を app という変数で使えるようにする
const app = express();
// ytdl-coreの機能を ytdl という変数で使えるようにする
const ytdl = require("ytdl-core");
// pathの機能を以下略
const path = require("path");
// fs以下略
const fs = require("fs");

// サーバーを起動する
app.listen(3000);
console.log("3000ポートでサーバー起動したぞ！");

// ホストディレクトリ(/)でHello Worldを出力する
app.get("/", function (req, res) {
  res.send("Hello World");
});

// downloadに要求が来たら実行する処理
app.get("/download", (req, res) => {
  var url = req.query.url;
  audioname = "ここに好きな動画のタイトルをいれる";
  // consoleにログとして表示する
  console.log("動画のダウンロードを開始します。");
  // ytdlの引数にURLを入れれば動画が返ってくる
  ytdlStream = ytdl(url, { quality: "lowest" });
  // どこに保存するのか決めておく
  videoFilePath = path.resolve(__dirname, `./${audioname}.mp4`);
  // createWriteStreamはstreamという方式でファイルを書き込むということ
  // pipeはちょっとずつ（細かく）データを送るよーってやつ
  ytdlStream.pipe(fs.createWriteStream(videoFilePath));
  // これでエラー処理が書ける。fileSystemを使うなら書かないといけない
  ytdlStream.on("error", (err) => {
    console.err(err);
    res
      .status(400)
      .send(
        "YouTubeをダウンロードする時にエラーが発生しました。" +
          "もう一度やり直してください。\nネットワークに接続されていないか、" +
          "URLが正しいか確認してください。"
      );
    console.log(err);
  });
  // .on("end~~　で終了後の処理が書ける
  // 終了後ということは、サーバーへの動画ダウンロードが終わったということ
  ytdlStream.on("end", () => {
    console.log(`(${audioname}.mp4のダウンロードが完了しました。`);
    // このままだとサーバーのパソコンに動画を保存できただけなので、
    // 動画を送り返す処理を書く
    // res.download(パス)でレスポンスとしてファイルを送れる。
    // これはStreamではなく、一気にボーンって感じで送る書き方してる
    res.download(videoFilePath);
  });
});


```
実行するしても、モジュールがないよってエラーがでるよね！これはytdl-coreというモジュールを使ってるんだけど、それをまだインストールしてないんだ。
インストールするには、最初の方もやったけど、npm install ○○だったよね！
つまり、expressもモジュールの一つということだね！

```
$ npm install ytdl-core
$ npm install fs
$ npm install path
```

### 実行

さっきのHelloWorldの時のように、
node app.js　でサーバーを立てて、今度は、index.htmlをブラウザで開いてみよう！

あとはフォームのところにYouTubeのURLを入力し、ボタンを押したらダウンロードされ保存できます。

:::note alert
著作権は必ず守りましょう。
:::

ちなみに、動画ですし、かなり？そこそこ？ダウンロードに時間がかかるような気がします。
是非、早くダウンロードできるように改良してみてください。
また、CSSなどの装飾、動画のタイトル、MP3への変換など、調べて色々機能を付け足してみましょう！