こしあん
2019-07-16

pytube+ffmpeg-pythonでYouTubeからダウンロードした動画の音声+動画を結合する方法

Pocket
LINEで送る


YouTubeをPythonで手軽にダウンロードできるライブラリとして、PyTubeがあります。しかし、ダウンロードした動画は音声と動画が別々になっていて、動画だけ再生したら無音になっていたということがしばしばあります。他のツールは使わずに、ダウンロードから結合まですべてPythonで行うという例を紹介します。

必要なライブラリ

  • ffmpeg-python
  • pytube
  • ffmepgのバイナリ ffmpeg-pythonはあくまでラッパーなので、ffmpeg本体が必要です。実行ディレクトリに本体がない場合は「FileNotFound」と怒られます。変換元の動画や音声が存在しないのではなく、本体がないだけなのでご注意を。

コード

YouTubeのダウンロードは複数の画質・音質のオプションがあります。これはダウンロードする動画によって変わります。この例では、動画の画質を1080p、音声のビットレートを160kbpsとしてダウンロードします。どの画質・音質がダウンロードできるかはクエリを見ながら調整します。そのへんはPytubeのドキュメントを見ましょう。

from pytube import YouTube
import os
import ffmpeg

def download_youtube(url_to_download, resolution="1080p"):
    if not os.path.exists("video"):
        os.mkdir("video")
    yt = YouTube(url_to_download)
    query = yt.streams.filter(fps=30, subtype="mp4", res=resolution).all()
    query[0].download("video")

def download_youtube_audio(url_to_download, abr="160kbps"):
    if not os.path.exists("audio"):
        os.mkdir("audio")
    yt = YouTube(url_to_download)
    query = yt.streams.filter(abr=abr).all()
    query[0].download("audio")

def join_audio_video(videoname):
    videopath = "video/" + videoname
    audiopath = "audio/" + videoname.replace(".mp4", ".webm")
    instream1 = ffmpeg.input(videopath)
    instream2 = ffmpeg.input(audiopath)
    stream = ffmpeg.output(instream1, instream2, videoname, vcodec="copy", acodec="aac")
    ffmpeg.run(stream)

ffmpeg側の設定ですが、「WEBMの音声をAACに再エンコードし、動画は再エンコードせずコピーする」という設定で行っています。動画の再エンコードを挟むと画質が劣化がしますし、処理に時間がかかるのでおすすめはしません。

ffmpeg-pythonで1入力1出力の簡単な例はよく出てきましたが、2入力1出力の例は探してもほとんど出てこなかったのでいろいろ試してみたらこれで動きました。ffmpegのパラメーターをラッパー側でどう再現するのかまだわからないところが多い。

Pocket
Delicious にシェア

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です