Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8902

YouTube動画をダウンロードするWebアプリを作る

$
0
0

始めに

YouTube動画をダウンロードするにあたって、無料のWebサービスはありますが、怪しい広告が表示されたりして危なかったり、煩わしかったりします。
ライブラリを使えば自作も簡単にできますので、実装内容についてまとめました。
ここでは以下のものを使って実装しています。

  • Node.js
  • TypeScript
  • ytdl-core
  • Express
  • Heroku

ローカルでYouTube動画をダウンロードする

まず始めにローカルでYouTube動画をダウンロードできるようにします。

以下の記事を参考にして、スクリプトを書きました。ただしこちらではTypeScriptを使って実装しています(と言っても型定義全くないですけど。。)。

Node.jsでYoutube動画をDLして保存するytdl-coreを使ったみたメモ

download.ts
importytdlfrom'ytdl-core';importpathfrom'path';importfsfrom'fs';constBASE_URL='https://www.youtube.com/watch?v=';constYOUTUBE_ID='bnc1NjaXXXX';consturl=`${BASE_URL}${YOUTUBE_ID}`;constvideo=ytdl(url);video.pipe(fs.createWriteStream(path.resolve(__dirname,`./tmp/${YOUTUBE_ID}.mp4`)));video.on('end',()=>{console.log('file downloaded.');});

これでmp4ファイルがダウンロードされました。mp3はffmpegで変換する必要があるようなのでchild_processで変換します。

mp3に変換
importpathfrom'path';import{exec}from'child_process';video.on('end',()=>{constinputFilePath=path.resolve(__dirname,`./tmp/${YOUTUBE_ID}.mp4`);constoutputFilePath=path.resolve(__dirname,`./tmp/${YOUTUBE_ID}.mp3`);// ffmpegでmp3に変換する。yオプションで上書きができる(これがないと、出力先にファイルが存在している場合は止まってしまう)exec(`ffmpeg -y -i ${inputFilePath}${outputFilePath}`,(error,stdout,stderr)=>{if(error){console.error(error);return;}console.log(stdout);console.log(stderr);});});

ExpressでYouTube動画をダウンロードするAPIを作る

ローカルでダウンロードできるようになったので、次はExpressでサーバーを立てて、API経由でダウンロードして動画または音声を返すAPIを作ります。
/api/youtube/bnc1NjaXXXX?fileType=mp4みたいに送ったら対象のYouTubeIdをmp4またはmp3でダウンロードするようにします。

server.ts
// Youtubeのダウンロードapp.get('/api/youtube/:youtubeId',(req,res)=>{const{youtubeId}=req.params;constfileType=(req.query.fileType||'mp4')as'mp4'|'mp3';constdestFilePath=path.resolve(__dirname,`./tmp/${youtubeId}.mp4`);consturl=`https://www.youtube.com/watch?v=${youtubeId}`;conststream=ytdl(url,{quality:'highest'});stream.pipe(fs.createWriteStream(destFilePath));stream.on('error',(err)=>{console.error(err);res.status(400).send('download error!');});stream.on('end',()=>{console.log(`youtube file (${youtubeId}.mp4) downloaded.`);// mp4の場合はそのまま返すif(fileType==='mp4'){res.download(destFilePath);return;}// mp3の場合は変換してから返すconsole.log('transform mp4 -> mp3.');constmp3FilePath=path.resolve(__dirname,`./tmp/${youtubeId}.mp3`);exec(`ffmpeg -y -i ${destFilePath}${mp3FilePath}`,(err,stdout,stderr)=>{if(err){console.error(err);res.status(500).send('movie translation error!');return;}console.log(stdout);console.log(stderr);res.download(mp3FilePath);});});});

フロント側のリクエストは以下のようにしました。ファイルのダウンロードは直接URL遷移してもできますが、エラーの場合だとエラーページが出てしまうので、一度blobで受け取るようにしました。(どうでも良いですが、fetch APIのエラーハンドリングは一々response.okをチェックしないといけないのは面倒ですね。。)

console.log('downloading...');// ファイルダウンロードfetch(`/api/youtube/${youtubeId}?fileType=${fileType}`).then((response)=>{if(!response.ok){thrownewError('Network error');}returnresponse.blob();}).then((blob)=>{consturl=URL.createObjectURL(blob);consta=document.createElement('a');a.href=url;a.download=`${youtubeId}.${fileType}`;document.body.appendChild(a);a.click();a.remove();}).finally(()=>{console.log('finished.');});});

Herokuにデプロイする

最後にHerokuにデプロイします。ExpressをHerokuにデプロイするやり方とほぼ同じですが、今回はffmpegを入れる必要があります。こちらに書かれていたbuildpackを使用しましたが、heroku-cliを使うのが面倒だったのでGUIで入れました。

Herokuでffmpegを使えるようにする

Herokuのアプリ画面に入り、SettingsのBuildpacksというセクションでbuildpackを2つ入れます。今までは自動でheroku/nodejsが使われていたと思いますが、2つ入れる必要があるので明記する必要があります。

スクリーンショット 2021-04-04 15.17.51.png

これで無事デプロイされて動作すれば完了です。

終わりに

以上がYouTube動画をダウンロードするWebアプリを作る流れでした。今回Node.jsでYouTube動画をダウンロードしましたが、音声付きだと画質は360pしか選べなくて少し残念でした。昔PythonでダウンロードしたときはフルHDでも普通にダウンロードできた気がしたんですけどね。。

今回作成したソースとHerokuアプリは以下に上がっております。興味がある方は見てください😄


Viewing all articles
Browse latest Browse all 8902

Trending Articles