Help us understand the problem. What is going on with this article?

Youtubeをmp3化して超安全にダウンロードする方法【Python】

今回はYouTubeにあげられている動画をmp3としてダウンロードする方法をまとめてみます。

参考サイトやgithubも載せます。

ミスや疑問点がありましたらコメントしていただけると幸いです。

*注意点*

あくまで個人的にYouTubeにアップロードした動画をダウンロード、そしてmp3化することを主としております。

そのため、自分以外の誰かが投稿した動画から手に入れた音源を使って問題が起きても一切の責任を負いません。

私的利用は大丈夫だという声も多いですが、自己判断で行うようにしてください。そのつもりで以下ごらんください!

完成品

あくまで例です。
https://www.youtube.com/watch?v=E8bUKuF9v10 をmp3化するとします。

開いたところ

2020-09-10_22h16_22.png

2020-09-10_22h16_57.png

ファイル生成

2020-09-10_22h17_19.png

2020-09-10_22h18_17.png

日付もすべて揃えることができる。

つまり、ダウンロードした順に並ぶ。
2020-09-10_22h18_36.png

ちなみに、最初の段階でQuitを押すとウィンドウが閉じ、何も入力していないときにTo Mp3,DeleteURL,Pasteを入力してもご作動は起きないように作ってあります。

環境

ディレクトリ

...\ffmpeg~static\bin\
この中にffmpegの主要ファイルがあるので、そこにpathを通します。bin内に、youtue-dlのexeファイルも入れます。そうすることで、コマンドプロンプトのどこでもexeが起動できます。

    -bin
      - ffmpeg.exe
      - ffplay.exe
      - ffprobe.exe
      - youtube-dl.exe

作った背景と作りたかった構造

youtube動画ダウンローダーたるものはネット上に数え切れないほどありますが、どうしても得体のしれないサイトからデータを返してもらうことが嫌でした。

そのため自分のPCで完結させようと思いました。

最初は、専用のソフトウェアなど全く知りませんでしたが、ググるうちにいいものを見つけたので、これは実現できるのではないか、と感じました。

実装させる機能は至ってシンプルなもので良かったので、GUIで操作できるようにしました。

また、Pythonファイルであれば、すぐにexe化できるので、友人に配布することも可能であります。

GUIとしてはTkinterが有名でしたが、試しに使ったところ吐き気がするくらい嫌になったので、pysimpleguiを用いました。

そのおかげでGUIは短時間で完成したと思います。

コード

github:

https://github.com/cota-eng/youtube-dl-in-windows

コード解説

区切って解説していきます。

モジュール・ライブラリのimport

import subprocess
import PySimpleGUI as sg
import sys
import re
import os
import pyperclip
from win32_setctime import setctime
from datetime import datetime

関数内の最初

すべてpysimpleguiのプログラムです。
配色テーマを決め、レイアウトを作り、ウィンドウを開く流れです。

それぞれのボタン、テキストフィールドの意味は英単語のそれの通りです。

sg.theme("SystemDefault")
    layout = [
        [sg.Text("Please Input Youtube URL!")],
        [sg.Button(
            'Quit', size=(34, 2))],
        [sg.Button('To Mp3', size=(34, 2))],
        [sg.InputText('', size=(39, 3))],
        [sg.Button('DeleteURL', size=(16, 2)),
         sg.Button('Paste', size=(16, 2))]
    ]
    window = sg.Window('From Youtube To mp3', layout)

while True

while True:
        event, values = window.read()
        url = values[0]

event=="Quit"

単純に、このボタンがおされるとwhileループを抜けるということです。

if event == 'Quit':
            break

whileループの一番下にbreakがあるのではなく、if,elifなどで適切な場面においてbreakさせます。

mp3化する

event==" "というのは、ボタンがクリックされたときに発生するイベントということです。そのうち、ボタンの名前に一致させることで一意にプログラムを指定できます。
そのイベント中でinputされたurlの長さで簡単にバグ防止させてみます。youtubeのリンクのうち、必須の長さは40ほどなので、安全に32を基準としました。

len > 32 が True

elif event == 'To Mp3':
    if len(url) > 32:
        cmd = r'youtube-dl {} -x --audio-format mp3 -o "C:\Users\INPUTUSERNAME\Music\youtube-dl\%(title)s.%(ext)s"'.format(
            url)
        subprocess.call(
            cmd, cwd=r"C:\Program Files\ffmpeg-20200831-4a11a6f-win64-static\bin")

        res = subprocess.check_output(f'youtube-dl -e {url}'.split())
        res = res.decode('shift_jis').replace('\n', '')
        res += '.mp3'
        root = "C:\\Users\\INPUTUSERNAME\\Music\\youtube-dl\\"
        filename = root + res
        print(filename)
        date = datetime.now()
        year, month, day, hour, minute, second = date.year, date.month, date.day, date.hour, date.minute, date.second
        now = datetime(date.year, date.month, date.day,
                       date.hour, date.minute, date.second).timestamp()
        os.chdir(root)
        setctime(filename, now)
        os.utime(filename, (now, now))

さらに分けて解説します。


r"文字列"とすることで、紛らわしい記号もすべて文字として扱えます。raw文字列のrawです。
cmdというコマンドはyoutube-dlのreadmeより作成しました。
youtube-dl\%(title)s.%(ext)sというのは、ファイル名です。youtube-dl上の話なので、詳しくは自分で読むといいです。僕は試行錯誤して得ました。

subprocessのcall関数で呼び出します。cwdでディレクトリも指定します。

cmd = r'youtube-dl {} -x --audio-format mp3 -o "C:\Users\INPUTUSERNAME\Music\youtube-dl\%(title)s.%(ext)s"'.format(
            url)
        subprocess.call(
            cmd, cwd=r"C:\Program Files\ffmpeg-20200831-4a11a6f-win64-static\bin")

resにファイル名を収めます。これも試行錯誤した結果なので、見て理解してください。
結局、以下のようにしたらfilenameにpathをすべて格納できるんです。

res = subprocess.check_output(f'youtube-dl -e {url}'.split())
                res = res.decode('shift_jis').replace('\n', '')
                res += '.mp3'
                root = "C:\\Users\\INPUTUSERNAME\\Music\\youtube-dl\\"
                filename = root + res
                print(filename)

datetimeライブラリより、作成時刻などを設定させます。厳密には、更新日時以外は、作成したときに自動的に設定されるのですが、なぜか更新日時が更新されませんでした。

そのため、以下のサイトを参考にし、自分なりにdatetimeを埋め込むことで実現できました。

参考URL:
https://srbrnote.work/archives/4054

ちなみにpowershell 使うなら、

Set-ItemProperty hogehoge.txt -name CreationTime -value $(Get-Date)

Set-ItemProperty hogehoge.txt -name LastWriteTime -value $(Get-Date)

として簡単にできるのですが、pythonではpowershellが使えないとのことなので、osモジュールを使用した次第です。

date = datetime.now()
year, month, day, hour, minute, second = date.year, date.month, date.day, date.hour, date.minute, date.second
now = datetime(date.year, date.month, date.day,
                date.hour, date.minute, date.second).timestamp()
os.chdir(root)
setctime(filename, now)
os.utime(filename, (now, now))

len <= 32 のとき

単純に、一度ウィンドウを閉じ、最初に開いたときと同じ入力して実行したとき、弾かれます。

else:
    window.close()
    layout = [
        [sg.Text("Please Input youtube URL!")],
        [sg.Button('Quit', size=(34, 2))],
        [sg.Button('To Mp3', size=(34, 2))],
        [sg.InputText('', size=(39, 3))],
        [sg.Button('DeleteURL', size=(16, 2)),
                     sg.Button('Paste', size=(16, 2))]
        ]
        window = sg.Window('From youtube To mp3', layout)

pasteイベント

pasteはそのとおり、コピーしたリンクを貼り付けます。ボタン操作の方が楽なので実装させました。

pyperclipだけでguiに入力はできないので、ウィンドウを閉じ、pyperclipの内容を変数に代入し、その変数を初期値とするウィンドウを開かせることで解決できました。

elif event == 'Paste':
    window.close()
    paste_url = pyperclip.paste()
    layout = [
        [sg.Text("Please Input youtube URL!")],
        [sg.Button('Quit', size=(34, 2))],
        [sg.Button('To Mp3', size=(34, 2))],
        [sg.InputText(paste_url, size=(39, 3))],
        [sg.Button('DeleteURL', size=(16, 2)),
         sg.Button("Paste", size=(16, 2))]
    ]
    window = sg.Window('From youtube To mp3 ', layout)

deleteイベント

これは先程と同じ考えです。削除させるのではなく、ウィンドウを閉じ、入力がされていないウィンドウを呼び出しました。

elif event == 'DeleteURL':
            window.close()
            layout = [
                [sg.Text("Please Input youtube URL!")],
                [sg.Button('Quit', size=(34, 2))],
                [sg.Button('To Mp3', size=(34, 2))],
                [sg.InputText('', size=(39, 3))],
                [sg.Button('DeleteURL', size=(16, 2)),
                 sg.Button('Paste', size=(16, 2))]
            ]
            window = sg.Window('From youtube To mp3', layout)

以上

コードが汚くて申し訳ないですが、参考になれば幸いです。

この一連の流れを紹介・解説しているサイトを見つけられなかったので、Qiitaに上げました。

ありがとうございました。

cota_hu
2020年5月~プログラミングをはじめました。 よろしくお願いいたします。
https://cota-blog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした