【続pytube】mp4をmp3に変換する
pytubeを使ってyoutubeからコンテンツをダウンロードする方法を記事にしましたが、それの続きです。
▼前回の記事
www.htmllifehack.xyz
mp4のダウンロードはできましたがそれだとmp3しか対応していないデバイスだと聞けません。
PCでならそのまま聞けますけどカーナビでは聞くことができませんでした。
そこで今回はffmpegを使ってmp4をmp3にコンバートしていきます。
ffmpegとは
こちらのブログを参考にさせていただきました。
▼参考
ffmpegで画像の山から動画を作る or 動画から静止画を取り出す ~ Youtuber向け? - 生活を良くします-怠惰なプログラミング
もっと細かく使いたい方はffmpeg オプションなどで検索してください。
使い方は簡単でiオプションのあとに元のファイル名.mp4、スペース開けてファイル名.mp3とするだけです。
c:\users\owner\music> ffmpeg -i test_audio.mp4 test_audio.mp3 実行するとサイズと時間が表示される size= 2989kB time=00:03:11.21 bitrate= 128.0kbits/s speed=7.71x
ちなみにffmpegを使ってコンバートするとなぜか音源が5秒長くなります。
勝手にクロスフェードしてくれてるんですかね?
pythonからexeを呼び出して実行する
ffmpeg-pythonてのがあるのでpythonでも使えるらしいのですが、今pip3が使えなくてインストールできないんでexeを起動させるコードを書きました。
pythonにはsubprocessモジュールがあるのでこれを使ってffmpeg.exeを呼び出し、さらにはコマンド入力も行います。
subprocess
▼参考サイト
Pythonでsubprocessを使ってコマンドを実行する方法
import subprocess import os os.chdir(r'C:\Users\Owner\Music\\ffmpeg-20180617-bd47cca-win64-static\\bin\\') cmd = 'ffmpeg.exe -i test_audio.mp4 test_audio.mp3' subprocess.call(cmd)
使い方はこれだけ
subprocessとディレクトリを移動するためにosをインポートします。
osl.chdirでffmpeg.exeがあるディレクトリまで移動します。
変数cmdにコマンドを入れます。
callでcmdを呼び出すことでffmpeg.exeを実行できます。
しかし、今はffmpegのあるディレクトリにいるのでmp4のファイルがあるパスを指定しなければならない。
c:\users\owner\music\test_audio.mp4みたいに。
逆にディレクトリをmusicフォルダにしてffmpegはパスを書いておくのもあり。
import subprocess import os os.chdir(r'C:\Users\Owner\Music') cmd = 'C:\Users\Owner\Music\\ffmpeg-20180617-bd47cca-win64-static\\bin\\ffmpeg.exe -i test_audio.mp4 test_audio.mp3' subprocess.call(cmd)
こんな感じ。
しかし結局毎回ファイル名(test_audioのところ)を書き換えないといけない。
それはめんどくさいのでglobを使ってmp4のファイル名取得することにしよう。
glob
▼参考サイト
Pythonでファイル名の前後に文字列や連番を加えて一括変更 | note.nkmk.me
osのlistdirと同様現在のディレクトリにあるファイルをリストで表示してくれるモジュール。
違いはlistdirはファイル名だけに対して、globはファイル名とパスを取得してくれる。
import glob dir = glob.glob(r'c:\users\owner\music\*.mp4') print(dir) >>結果 >>['c:\\users\\owner\\music\\test_audio.mp4']
そしてlistdirは*.mp4のような正規表現が使えないようなのでglobのほうが上手。
バックスラッシュが入る場合の対処法
windowsの場合パスに¥が入る。
これはpythonでいうエスケープになる。
¥nで改行とか¥bでバックスペースとか。
という風に普通に入力するとエラーになるのでパスの先頭にrを付けることで回避することができる。
ただし今回はfとbだけ回避できなかったので\\を使って2重で回避することにした。
\\bin\\ffmpeg.exe ← これとかそういう意味。
rつけてダメならバックスラッシュを2つ入れることで回避する。
ファイル名にスペースが入っている場合の対処法
ファイル名にスペースが入っている場合、コマンドラインに入力するとエラーがでる。
例えばman with a mission.mp4というファイル名を入力した場合。
最初のスペースの位置であるmanで切られてしまうためman : No such file or directoryとエラーになる。
こういう時はファイル名をダブルクォーテーションで囲むことで回避することができる。
pythonに組み込んで自動化する
以上を踏まえてpythonに組み込んでみる。
import subprocess # ffmpeg.exeを実行するためのモジュール import os # ディレクトリを移動するために使う import glob # パス付でファイル名を取得するために使う dir = glob.glob(r'c:\users\owner\music\*.mp4') # 正規表現でmp4ファイルだけを取得 name = [n.split('.')[0] for n in dir] # splitを使ってファイル名と拡張子に分けてファイル名だけをnameに入れる print(name) # 念のため取得したファイル名を確認 os.chdir(r'C:\Users\Owner\Music\\ffmpeg-20180617-bd47cca-win64-static\\bin\\') # ディレクトリを移動する cmd = 'ffmpeg.exe -i \"{0}\".mp4 \"{0}\".mp3'.format(name[0]) # \"はエスケープシーケンス subprocess.call(cmd)
これを先日のpytubeのコードに書き足せば完成:)。
# coding:utf-8 from pytube import YouTube import subprocess import os import glob url = input('>> Prease enter URL : ') yt = YouTube(url) yt.streams.get_by_itag(140).download(r'c:\users\owner\music') dir = glob.glob(r'c:\users\owner\music\*.mp4') name = [n.split('.')[0] for n in dir] print(name) os.chdir(r'C:\Users\Owner\Music\\ffmpeg-20180617-bd47cca-win64-static\\bin\\') cmd = 'ffmpeg.exe -i \"{0}\".mp4 \"{0}\".mp3'.format(name[0]) subprocess.call(cmd)
まとめ
普通にmp4からmp3に名前を変えるだけだとpcではmp3になっていますがカーナビだと聞けません。
一応名前を変えるのに試したコードを載せておきます。
import os import glob dir = glob.glob(r'c:\users\owner\music\*.mp4') # mp4ファイルを取得 for name in dir: bname, ext = os.path.splitext(name) # splitextでファイル名と拡張子に分けてそれぞれ変数に入れる print(bname + '---' + ext) # 一応わけられたか確認 os.rename(name, bname + '.mp3') # os.renameを使ってファイ名+mp3に書き換える
これでいろいろダウンロードできるようになりましたけど、曲はちゃんと買いましょうね。
いやそれにしてもpip3が使えなくなったのがまじでだるい。
一応解決策みたいなのは見つけたのでそれで直ればまた記事に残そうかと思います。
では。