コマンドラインで動く動画ダウンロードツールyoutube-dlの紹介とそのzsh補完関数を書いたので紹介

コマンドラインで動く、Youtube等動画サイトから動画をダウンロードするツール[youtube-dl](https://github.com/rg3/youtube-dl/)を紹介します。また、このオプションが多くて覚えることができないので、zshの補完関数を書いたので、紹介します。

# youtube-dl

## 使い方

端末から

```
youtube-dl "URL"
```

と実行すれば、対応しているサイトならこれだけでダウンロードすることができます。


## インストール
インストール方法は

Pythonのパッケージ管理モジュールpipを使えば

```
sudo pip install youtube-dl
```

でインストールできます。ただし、Pythonのモジュール名としては仕様で`youtube_dl`とアンダーバーになっていることに注意。

MacではHomebrewを使ってインストールすると楽そう。

```
brew install youtube-dl
```

ソースからビルドしたい方などは、やっぱり本家をみてください。

- [youtube-dl #installation](https://github.com/rg3/youtube-dl/#installation)

## 対応サイト

対応しているサイトは、

```
youtube-dl --extractor-description
```

実行すれば見ることができますが、現在621サイトに対応しているようです。Youtubeはもちろん、ニコニコ動画、twitch他有名どころは大体カバーしているように思います。以下にそれぞれへのサイトへのリンクを追加したものを置いておきます。…いかがわしいサイトも多くあるので、見るときは気をつけてください。

- [対応サイト一覧](https://gist.github.com/b832d944ea08ff4967d0)

## オプションの指定

また、ヘルプを見てもらえれば分かりますが、様々なオプションを与えて実行することができます。一番シンプルな使い方としては、はじめにあげたように単純にオプション無しで

```
youtube-dl "URL"
```

としてurlを直接貼り付ける方法です。YoutubeではURLの`watch=`以下のIDでも指定することができます。また、プレイリストを指定するだけで、その中に登録されている動画すべてをダウンロードすることができます。

## ダウンロードするフォーマットの指定

動画のフォーマットを指定してダウンロードすることもできて、`-F`で対応しているダウンロードのフォーマットを表示することができ、`-f`でこれらの中からフォーマットを指定して実行することができます。

## 保存ファイル名をテンプレートで指定

それから、`-o` で保存するファイル名を指定できるのですが、ここでテンプレートを書くことで、動画のタイトル、プレイリストのタイトル、プレイリストの中の番号、どのサイトからダウンロードしてきたか、アップローダーなどを動画のファイル名に含めることができるようになります。詳しくは(ry

- [youtube-dl #output-template](https://github.com/rg3/youtube-dl/#output-template)

## 指定した複数の動画をダウンロードする

あと、覚えていて便利かもしれないのは、一つのテキストファイルの中にダウンロードしたいファイルを全部放り込んでおいて、後で

```
youtube-dl -a dl_list
```

とすれば、このファイル内の動画をすべてダウンロードしてくれます。

## 時間のかかるダウンロードはignore-errorsオプションを付ける

再生リストからダウンロードするときなど、たくさんの動画をダウンロードするときには、`-i`オプションをつけると、途中で発生したエラーは無視して、次の動画の処理を続けてくれるので便利です。

また、ネットワークの不調など、何らかの理由で途中で処理が止まってしまった動画ファイルは、`.part`という拡張子付きで保存されており、同じファイル名で保存するように再びyoutube-dlコマンドを実行すると、ダウンロードを途中から再開してくれます。ただし、自分から`Ctrl-c`などで処理を中断した場合、再度やり直しになったりするので注意してください。

## ダウンロードせずにストリーミング再生を行う

ダウンロードするのではなく、ストリーミングで再生したい場合には、`-o`オプションで標準出力に出してパイプでmplayerに渡し、

```
youtube-dl URL -o - | mplayer -
```

という形にすれば、mplayer、vlcなど、URLから動画再生できるメディアプレーヤーを使えば、そのまま再生することができます。[mpv](https://github.com/mpv-player/mpv)では、youtube-dlのホックが用意されているので、動画のURLをそのまま貼り付けるだけで再生ができます。(上のやり方では逆に再生できないことがあります)


# zsh補完関数

## 自動生成

youtube-dlの中に準備されているスクリプトの中に、zsh補完関数を自動で生成するスクリプトが用意されています。

- [youtube-dl/zsh-completion.in at master · rg3/youtube-dl](https://github.com/rg3/youtube-dl/blob/master/devscripts/zsh-completion.in)
- [youtube-dl/zsh-completion.py at master · rg3/youtube-dl](https://github.com/rg3/youtube-dl/blob/master/devscripts/zsh-completion.py)

この二つをダウンロードしてきて、同じディレクトリ内で`zsh-completion.py`の12行目を

```
ZSH_COMPLETION_TEMPLATE = "zsh-completion.in"
```

に変更して

```
python zsh-completion.py
```

として実行すると、同じディレクトリ内に`youtube-dl.zsh`というファイルが作成されます。これをzshの補完関数を置いておくディレクトリに置いておけば、youtube-dlを実行するときに、すべてのロングオプションの候補を表示してくれ、いくつかのオプションに関しては、ファイル名やディレクトリの補完もされます。

## ちょっと手を加える

ただ、このままだとよく使うオプションについて、何だったか覚えておかないといけない気もするので、自分で手を加えたものが以下に置いてあります。適当にダウンロードして使ってください。追加したりもっといい書き方あるよって場合は、何かしらの方法で僕にも教えていただくとありがたいです。

- [zsh-completion function for youtube-dl](https://gist.github.com/ssh0/436e906765dfe8d1b3d6)

```zsh
#-------- youtube-dl completion
# put this script in your .zshrc
# generated by:
# https://github.com/rg3/youtube-dl/blob/master/devscripts/zsh-completion.in
# https://github.com/rg3/youtube-dl/blob/master/devscripts/zsh-completion.py
# and modified manually by Shotaro Fujimoto (https://github.com/ssh0)

__youtube_dl() {
  local curcontext="$curcontext" fileopts diropts cur prev
  typeset -A opt_args
  fileopts="--download-archive|-a|--batch-file|--load-info|--cookies|--ffmpeg-location"
  diropts="--cache-dir"
  local ddir="/media/shotaro/STOCK/Videos"
  cur=$words[CURRENT]
  case $cur in
    :)
      _arguments '*: :(::ytfavorites ::ytrecommended ::ytsubscriptions ::ytwatchlater ::ythistory)'
    ;;
    *)
      prev=$words[CURRENT-1]
      if [[ ${prev} =~ ${fileopts} ]]; then
        _path_files
      elif [[ ${prev} =~ ${diropts} ]]; then
        _path_files -/
      elif [[ ${prev} == "--recode-video" ]]; then
        _arguments '*: :(mp4 flv ogg webm mkv)'
      elif [[ ${prev} == "--audio-format" ]]; then
        _arguments '*: :(best aac vorbis mp3 m4a opus wav)'
      elif [[ ${prev} == "--convert-subtitle" ]]; then
        _arguments '*: :(srt ass vtt)'
      elif [[ ${prev} =~ "-o|--output" ]]; then
        _arguments "*: :(\
          '${ddir}/%(title)s.%(ext)s' \
          '${ddir}/%(autonumber)s - %(title)s.%(ext)s' \
          '${ddir}/%(extractor)s/%(title)s.%(ext)s' \
          '-' \
          )"
      elif [[ ${prev} == "--proxy" ]]; then
        _arguments "*: :( `echo ${http_proxy}` )"
      else
        _arguments -S\
          '-h[Print help]: :' \
          '-U[Update the program (run with root)]: :' \
          '-i[Continue on download errors]' \
          '(-6)-4[Make all connections via IPv4]' \
          '(-4)-6[Make all connections via IPv6]' \
          '-r[Maximum download rate in bytes per second (e.g. 50K or 4.2M)]' \
          '-R[Number of retries (default is 10), or "infinite"]' \
          '-a[File containg URLs to download ('-' for stdin)]' \
          '-o[Output filename template. (See manpage)]' \
          '-q[Activate quiet mode]' \
          '-s[Do not download the video and do not write anything to disk]' \
          '-g[Simulate, quiet but print URL]' \
          '-e[Simulate, quiet but print title]' \
          '-j[Simulate, quiet but print JSON information]' \
          '-J[Simulate, quiet but print JSON information for each command-line argument]' \
          '-f[Video format code, see the "FORMAT SELECTION" for all the info]' \
          '-F[List all available formats]' \
          '-u[Login with this account ID]' \
          '-p[Account pass word. If this option is left out, youtube-dl will ask interactively]' \
          '-2[Two-factor auth code]' \
          '-n[Use .netrc authentication data]' \
          '-x[Convert video files to audio-only files]' \
          '-k[Keep the video file on disk after the post-processing; the video is erased by default]' \
          '*: :(--help --version --update --ignore-errors --abort-on-error --dump-user-agent --list-extractors --extractor-descriptions --default-search --ignore-config --flat-playlist --no-color --proxy --socket-timeout --source-address --force-ipv3 --force-ipv6 --cn-verification-proxy --playlist-start --playlist-end --playlist-items --match-title --reject-title --max-downloads --min-filesize --max-filesize --date --datebefore --dateafter --min-views --max-views --match-filter --no-playlist --yes-playlist --age-limit --download-archive --include-ads --rate-limit --retries --buffer-size --no-resize-buffer --test --playlist-reverse --xattr-set-filesize --hls-prefer-native --external-downloader --external-downloader-args --batch-file --id --output --autonumber-size --restrict-filenames --no-overwrites --continue --no-continue --no-part --no-mtime --write-description --write-info-json --write-annotations --load-info --cookies --cache-dir --no-cache-dir --rm-cache-dir --write-thumbnail --write-all-thumbnails --list-thumbnails --quiet --no-warnings --simulate --skip-download --get-url --get-title --get-id --get-thumbnail --get-description --get-duration --get-filename --get-format --dump-json --dump-single-json --print-json --newline --no-progress --console-title --verbose --dump-pages --write-pages --youtube-print-sig-code --print-traffic --call-home --no-call-home --no-check-certificate --prefer-insecure --user-agent --referer --add-header --bidi-workaround --sleep-interval --format --all-formats --prefer-free-formats --list-formats --youtube-include-dash-manifest --youtube-skip-dash-manifest --merge-output-format --write-sub --write-auto-sub --all-subs --list-subs --sub-format --sub-lang --username --password --twofactor --netrc --video-password --extract-audio --audio-format --audio-quality --recode-video --keep-video --no-post-overwrites --embed-subs --embed-thumbnail --add-metadata --metadata-from-title --xattrs --fixup --prefer-avconv --prefer-ffmpeg --ffmpeg-location --exec --convert-subtitles)'
      fi
    ;;
  esac
}

compdef __youtube_dl youtube-dl
```

これを`.zshrc`の中において、

```
local ddir=""
```

の部分を、自分が動画をダウンロードしたいディレクトリの場所に変更してもらえれば、zshで補完を行うことができます。zshの設定を再度読みこむと`youtube-dl`と打ってTABキーを押すと、1文字オプションについてはその説明も表示されますし、いくつかのオプションについては追加されて欲しい情報が追加されるようになっています。(例えばアウトプットのテンプレートとか、proxyのアドレスとか)

# まとめ

youtube-dl超便利。ブラウザのアドオンなんかでも似たようなものあるけど、あれはフラッシュじゃないといけなかったり、ニコニコ動画だとエコノミーモードだとダウンロードする動画もエコノミーになってしまったり、ちょっと問題があった。その点これはそのサイトのURLだけ分かってればいいわけだし、わざわざブラウザを立ち上げる必要もないわけだから、便利。ただし、一気にアクセスすると、サイトにとっては迷惑になるので、そこら辺は良識ある行動を。あと、権利者にダウンロードが認められているサイトかどうかも、確認するようにしましょう。

zshの補完関数の書き方は、メタ文字などがたくさんあって難しいような気もするけど、これを覚えるとターミナル内での作業が格段に捗るようになるので、積極的に自分が使うやつは補完関数書いていきたい。