Pythonとyt-dlpを活用した動画・音声のダウンロード方法

ちょっと前まで、とある原稿を書いていたのですが、その時の没ネタを少しメモしておきます。

Pythonを使用した便利な処理ということでのネタ探しでしたが、紙面の関係と、微妙に権利関係の懸念もあって没としていました。 内容としてはYouTubeの動画および、音声のダウンロードとなります。

調べたきっかけ

たまに自分の作成した動画(機器のデモなど)はチャチャっと作ってすぐ見せるということがほとんどのため、 元ファイルを削除してしまったり、無くすことがかなりあります。多くの場合には何回も使用することがないため、それで問題は発生しません。 稀に、同じ作品の動画を使いたいとなったときには元ファイルがないので、困ってしまいます。 そこで、YouTubeにはアップロードしていることもあるので何とかそれを素材として使用したいという要望のため、やってみたということになります。

そういうサービスは別でWebサービスとしてもありますが、今回はPythonを使用したプログラミングで行います。動作環境はUbuntu24.04 LTSとなります。

(注意) 本記事で紹介する方法は、技術的な紹介を目的としています。YouTubeの動画をダウンロードする行為は、利用規約著作権法に抵触する場合があります。この内容を使用して行う行為についての全ての責任は、使用したユーザー自身にあります。違法なダウンロードや著作権侵害等、法律に違反する行為は厳禁です。何らかのトラブルや損害が発生した場合、筆者は一切の責任を負いかねますので、十分にご注意ください。

使用したライブラリ

今回使用したライブラリはyt-dlpになります。

リポジトリのreadme.mdには以下のように記載がされています。

yt-dlp is a youtube-dl fork based on the now inactive youtube-dlc. The main focus of this project is adding new features and patches while also keeping up to date with the original project

以前あったyoutube-dlというライブラリのforkのようです。

以下が公式サイトになります。

github.com

ちなみにこのライブラリはエントリーポイントを持っているのでインストール後は単独のプログラムとして実行することも可能です。

ライブラリインストール

ライブラリのインストールは以下のようになります。必要であればvenvなどを使用して行ってください。

$ pip install yt-dlp

使用方法

動画をダウンロード

動画をダウンロードするには以下のようにコードを記載します。

基本的な流れとしては処理のオプション(フォーマットなど)を指定して、URLを指定してダウンロードを行うことになります。 URLはフルパスを指定します。

download_from_youtube.py

import yt_dlp

def download_video_as_mp4(video_url):
    options = {
        'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]',
        'outtmpl': 'downloaded_videos/%(title)s.%(ext)s', # 出力ファイル名のテンプレート
    }

    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([video_url])

# 動画のURLを指定してダウンロード
download_video_as_mp4('https://www.youtube.com/watch?v=YOUR_VIDEO_ID')

動画の音声のみをダウンロード

動画の中でも音声だけが保存したいこともあるので、その場合には以下のように記述します。音声の抽出に関してはFFmpegを使用するので事前にインストールを行っておいてください。

$ sudo apt update
$ sudo apt install ffmpeg

download_audio_from_youtube.py

import yt_dlp

def download_audio_as_mp3(video_url):
    options = {
        'format': 'bestaudio/best',
        'extractaudio': True,  # 引数が `True` である場合、音声のみをダウンロードします
        'audioformat': 'mp3',  # 出力形式を mp3 に設定します
        'outtmpl': 'downloaded_audios/%(title)s.%(ext)s',  # 出力ファイル名のテンプレート
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',  # 音声を抽出するために FFmpeg を使用します
            'preferredcodec': 'mp3',  # 出力形式を mp3 に設定します
        }],
    }

    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([video_url])

# 動画のURLを指定してダウンロード
download_audio_as_mp3('https://www.youtube.com/watch?v=YOUR_VIDEO_ID')

タイムコードを指定して、特定の部分のみをダウンロード

あまり、必要ではないかもしれませんが、タイムコードを指定してその部分のみをクリップして保存することもできます。 YouTubeの動画をStart(開始点)とEnd(終了店)のタイムコードを指定したクリップでダウンロード

download_from_youtube_clip.py

import yt_dlp
from moviepy.video.io.VideoFileClip import VideoFileClip
import argparse
import os

def download_video(url, path):
    ydl_opts = {
        'outtmpl': f'{path}/%(title)s.%(ext)s',
        'format': 'bestvideo+bestaudio/best',
    }
    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        info_dict = ydl.extract_info(url, download=True)
        return f"{path}/{info_dict['title']}.mp4"  # downloaded file path

def clip_video(video_path, start_time, end_time, output_path):
    with VideoFileClip(video_path) as video:
        new_clip = video.subclip(start_time, end_time)
        new_clip.write_videofile(output_path, codec='libx264')

def main():
    parser = argparse.ArgumentParser(description='Download and clip YouTube video.')
    parser.add_argument('url', type=str, help='URL of the YouTube video (enclose in double quotes).')
    parser.add_argument('start_time', type=int, help='Start time in seconds.')
    parser.add_argument('end_time', type=int, help='End time in seconds.')
    parser.add_argument('output_path', type=str, help='Output file name with path.')

    args = parser.parse_args()

    temp_directory = 'temp_video_directory'
    os.makedirs(temp_directory, exist_ok=True)

    downloaded_video_path = download_video(args.url, temp_directory)
    clip_video(downloaded_video_path, args.start_time, args.end_time, args.output_path)
    
    # Optionally, remove the temporary directory and downloaded video
    # os.rmdir(temp_directory)

if __name__ == '__main__':
    main()

上記を実行するには以下のように動作させます。10秒目から20秒目までの動画のクリップをoutput_clip.mp4として出力する。

$ python script.py "https://www.youtube.com/watch?v=YOUR_VIDEO_ID" 10 20 output_clip.mp4

おわりに

没ネタではありましたが、そのまま捨てるにはもったいないのでこちらででメモをしておきます。

再度とはなりますが以下に注意してください。

(注意・再掲) 本記事で紹介する方法は、技術的な紹介を目的としています。YouTubeの動画をダウンロードする行為は、利用規約著作権法に抵触する場合があります。この内容を使用して行う行為についての全ての責任は、使用したユーザー自身にあります。違法なダウンロードや著作権侵害等、法律に違反する行為は厳禁です。何らかのトラブルや損害が発生した場合、筆者は一切の責任を負いかねますので、十分にご注意ください。

/* -----codeの行番号----- */