pytube+ffmpeg-pythonでYouTubeからダウンロードした動画の音声+動画を結合する方法
Posted On 2019-07-15
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のパラメーターをラッパー側でどう再現するのかまだわからないところが多い。
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー