こんにちは、つくたろうです。
僕はClipBox(ClipBox+)というスマホアプリを使ってiPhoneで動画をダウンロードして、お気に入りの動画をオフラインでも見れるようにしています。
そうしてダウンロードしている動画がiPhone上に増えてきたので、バックアップと整理がてらPCに移そうと思ってなんとなく移行作業をしていたのですが、たまに落ちてくる「.hls」という拡張子の動画がPCにおいてはそのままでは再生できないことに気づきました。ニコニコ動画なんかから落とした動画は大体この拡張子になっています。
これはどうにも気持ちが悪いので.hlsの動画は.mp4に変換しようと思ったんですが、なんと「.hls」という拡張子について取り扱っている変換ソフトや変換コードの類が全く見つからない。
無いなら作るしかねえ、、、ということでpythonを使って「.hlsを.mp4に変換するプログラム」を書きました。(しかも基本的に無損失。すばらC)
ちなみに、KINGBOXの後継の「トルミル」では.hlsの動画を再生できませんが、この手法を使って.mp4に変換することで再生できるようになります。トルミルユーザーの方にも参考にしていただけると嬉しいです。
- そもそも「.hls」という拡張子はClipBoxの独自規格っぽい
- 実装
- コードについて
- このプログラムの使い方
- 実際にhlsファイルを変換
- KingBoxでも変換可能
- 参考書籍
- Github
- おわりに
そもそも「.hls」という拡張子はClipBoxの独自規格っぽい
HLSというのはHTTP Live Streamingの頭文字を取った略称で、動画のストリーミング用の通信プロトコルです。
動画のストリーミング配信では1本の動画をそのまま送っていては速度的な問題が発生するため、このプロトコルでは1つの動画を数秒程度の細切れにしたもの(.tsファイル)を次から次へと送って連続で再生することによって、あたかも1本の動画を通信しながら再生しているように見せかけているというわけです。
そしてこのとき、送られてくる数秒の動画についてのプレイリストの役割をしているのが.m3u8という拡張子のファイルというわけです。つなげる順番をあらかじめプレイリストのような形で明記しておかないと、正しい順序で.tsファイルを再生できない恐れがあるんですね(細切れのファイルが必ず順番通りに届くとは限らないため)。
詳しくは調べればいくらでも出ると思うので簡単な説明にとどめますが、HLSでは.m3u8ファイルと.tsファイルのセットで動画を再生しているんです。つまり、使われている拡張子は「.m3u8」と「.ts」なんです。「.hls」なんて拡張子はどこにも使われていない。
つまりどういうことかというと、「.hls」ファイルはClipBoxがダウンロードした「.m3u8と.tsのセット」について便宜的に使っているだけのオリジナル拡張子である可能性が非常に高いというわけです。高いというか、絶対そう。
ClipBox上で.hlsという拡張子の動画ファイルが再生できるのは、ClipBoxが.hlsというファイルの中に格納した.m3u8を読んで、そこに書かれている通りの順番で同じく.hlsに格納している.tsファイルを再生しているからというわけです。
そりゃ変換ソフトの類が簡単に転がっているわけないですね。規格が限定的すぎます。
ということで、無いなら作る。DIYですね。
実装
とりあえず、.hlsファイルの正体が「拡張子が便宜的につけられているだけの、.m3u8と.tsを格納しているだけの容器」と分かったので、これを取り出して.m3u8に書かれた順番通りに.tsファイルをくっつけて.mp4として保存すれば終わりです。
.m3u8を読んで.tsを合体させる部分についてはffmpegに任せちゃいます。もちろんffmpegを使わずとも自分でも簡単に書けると思いますが、今回は車輪の再発明はしないことにします。
ということでできたコードがこちら。
import os import glob import shutil import subprocess def hls2mp4(filePath): #ファイルのあるディレクトリに移動 os.chdir(os.path.dirname(__file__)) #ファイル名の処理 src = filePath fileName = os.path.basename(filePath) savePath = os.path.splitext(os.path.dirname(filePath)+f"/{fileName}")[0]+".mp4" tempDir = os.path.dirname(filePath)+"/temp" dst,ext = os.path.splitext(os.path.join(tempDir+"/"+fileName)) #入力が.hlsファイルのときのみ処理を実行 if not ext==".hls": print("Error: This is not \".hls\" file.") return else: if not os.path.exists(tempDir): os.mkdir(tempDir) try: #.m3u8ファイルと.tsファイル群を展開 dst = dst+".zip" shutil.copy(src,dst) shutil.unpack_archive(dst,tempDir) #変換を実行 index_m3u8 = glob.glob(f"{tempDir}/*.m3u8")[0] cmd = f"./ffmpeg/ffmpeg.exe -allowed_extensions ALL -y -i \"{index_m3u8}\" -loglevel fatal -c copy \"{savePath}\"" subprocess.run(cmd) #一時ファイルの削除 shutil.rmtree(tempDir) finally: messageFine = f""" {src} | V {savePath} 変換は正常に完了しました。 """ print(messageFine) if __name__=="__main__": #変換したい.hlsファイルのパス hlsPath = "ここにパスを記述" #実行 hls2mp4(hlsPath)
コードについて
コードの説明はコメントに割と詳しく書いたのでそちらを見てもらえれば分かると思います。
基本的には先ほど述べた通り「.hlsから.m3u8と.tsを取り出して合体」ということをしているだけです。
.hlsから取り出すところについては、.hlsを一度.zipに変換してからshutil.unpack_archive()
を使って展開しています。変換をかまさずにもっとスマートにできるような気もしますが、まあ確実にできるしこれでいいかなという感じです。うごけばええねん
このプログラムの使い方
このプログラムは、コードのメイン部分のパスを自分の変換したい.hlsファイルのものに変えて実行するだけで使えます。
ただし、実行前にffmpeg.exeを入れておく必要があります。ffmpegについては後述。
ffmpegについて
このプログラムを実行するためには、ffmpegというフリーソフトが必要となります。
こちらからffmpeg-(バージョン)-full_build.zip
をダウンロード・解凍し、bin
内のffmpeg.exe
をコピーしてhls2mp4/ffmpeg/ffmpeg.exe
となるように配置してください。
.mp4動画の上書き保存について
変換元の.hlsのあるディレクトリに既に同じ名前で拡張子違いの.mp4動画がある場合、その動画ファイルが上書きされる形で変換後の.mp4ファイルが保存されます。
上書きしたくない場合はあらかじめ名前を変えるなどして対処してください。
実際にhlsファイルを変換
せっかく.hlsを.mp4に変換するプログラムを作ったので、実際に使って変換してみましょう。
今回はClipBoxを使ってニコニコ動画からダウンロードした「神のまにまに」のMVがちょうど.hls拡張子だったので、こちらを.mp4に変換してみます。
以下のようにパスを設定して、実行するだけです。
if __name__=="__main__": #変換したい.hlsファイルのパス hlsPath = "D://Music//niconico//【ミクリンGUMI】神のまにまに【オリジナル】 - ニコニコ動画.hls" #実行 hls2mp4(hlsPath)
無事にできました!変換成功です!
再生もできました。
KingBoxでも変換可能
ClipBox+の後釜の「KingBox」というアプリでダウンロードした結果「.hls」となった動画ファイルについても、このプログラムで.mp4に変換可能です。
KingBoxでダウンロードした動画ファイルをPCでも見たい方はぜひ使ってみてください。
参考書籍
今回のような動画の通信技術・伝送技術について体系的に学ぶなら、以下の書籍をオススメしておきます:
また、Pythonを書いていくにあたって以下の書籍はとても使いやすく、他の書籍には載っていない点も網羅的に学べるため非常に重宝しています。皆さんにもオススメしておきます:
Github
今回のプログラムのリポジトリはこちらです:
おわりに
さて、今回はpythonを使って.hlsファイルを.mp4ファイルに変換するという記事でした。
正直かなり忙しいのでなかなかブログを書く暇もないのですが、隙間時間を見つけて書いていけたらと思います。
これからも読んでもらえると嬉しいです!ここまで読んでくれて、ありがとうございました!
2022/05/17 つくたろう
カテゴリ: