僕の世界観を変えてみる

文系男子が趣味でプログラミングを勉強していくブログです。他にも日常で起きたどうでもいいことや愚痴を書いていきたいです。座右の銘は和を以て貴しとなすです。仲良くやろうよ。

【続pytube】mp4をmp3に変換する

f:id:htmllifehack:20180615131701j:plain

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が使えなくなったのがまじでだるい。

一応解決策みたいなのは見つけたのでそれで直ればまた記事に残そうかと思います。

では。