こしあん
2019-06-27

OpenCVで作成した動画がブラウザで正常に表示できない場合の解決法

Pocket
LINEで送る


OpenCVで作成した動画をサイトで表示する場合、ローカルで再生できていても、ブラウザ上では突然プレビューがでなり、ハマることがあります。原因の特定が難しい現象ですが、動画を作成する際にH.264形式でエンコードするとうまくいきました。その方法を解説します。

MPV4は手軽だが…

OpenCVで動画を作成する例で検索すると、おそらくこっちのほうが多く出てくると思うのですが、fourccにMP4Vを指定するパターンです。

directory以下のPNGファイルを1つのMP4ファイルにまとめてみましょう。

import cv2
import glob

# よくある例
def create_mp4(directory):
    # コーデックの指定
    fourcc = cv2.VideoWriter_fourcc("m", "p", "4", "v")
    # 引数はファイル名、コーデック、FPS、解像度(横、縦)
    video = cv2.VideoWriter(directory+".mp4", fourcc, 5.0, (640, 480))

    files = sorted(glob.glob(directory + "/*.png"))
    for f in files:
        img = cv2.imread(f)
        video.write(img)

これはローカルPCではうまく行きます。そしてメディアプレーヤーで再生してもちゃんと表示されます。しかし、作成した動画をブラウザで表示しようとすると急に沼にハマります

WordPressだとエラー

「Media error: Format(s) not supported or source(s) not found」というエラーが出てしまいます。

このエラーで検索すると、いくつかそれっぽい理由が出てきました。

  • ファイルサイズが上限にかかっていて正常にアップロードできない(php.iniに問題あるケース)
  • WordPressのバグだという主張

一点目は自分のサーバーだと128MBまでアップロードでき、ファイルサイズは10MB程度だったので引っかかることはありませんでした。サーバーのファイルマネージャーから当該のアップロード済ファイルをダウンロードして、ローカルPCのメディアプレーヤーで開くと正常に表示できました。したがって、アップロード自体に失敗しているということは考えられません。アップロード自体は成功しています。

二点目は例えばこちらのフォーラムにありますが、WordPressのバグだという説が浮上しています。しかし、明確な解決法は特に示されていませんでした。

一方で、MP4のURLを直打ちするとChromeでのプレビューは以下のようになりました。

プレビューができていない??

つまり、正常にアップロードできているのに再生ができないということになります。

ローカルファイルをChromeやFirefoxで開いてもエラー

なら作成したMP4のローカルファイルをChromeで開くとどうかというと、上の図と同じ状態になりました。

ブラウザを変えてみるとどうかというと、Firefoxでは次のようになりました。

Chromeと同様に再生できません。つまり、作成した動画ファイル自体に問題があるということになります。

原因はコーデック

諸悪の根源はコーデックでした。こちらのStackOverFlowの記事が参考になりました。

この記事によると、「MP4Vはほとんどのブラウザでサポートされていないから、代わりにH264を使いなさい」とのこと。H264への切り替えは簡単で、fourccの設定を、

fourcc = cv2.VideoWriter_fourcc("H", "2", "6", "4")

とするだけ。じゃあそのままこれで実行すれば終わりかというともう一歩あります。

OpenH264が必要

H.264でエンコードするにはOpenH264というライブラリが別途必要になります。主にライセンスの関係です。試しにOpenH264なしでエンコードしようとすると、

Failed to load OpenH264 library: openh264-1.8.0-win64.dll
        Please check environment and/or download library: https://github.com/cisco/openh264/releases

「OpenH264を取ってこい」と怒られてしまいます。

本来H.264を使うにはMPEG-LAにライセンス料を支払う必要があります。しかし、OepnH264という、Ciscoがオープンソースとして公開しているビルドされたライブラリを使う限りにおいては、このライセンス料をCiscoが肩代わりしてくれるという契約があるのです。OpenCVでOpenH264を必要としているのもこれが理由です。

また、過去のニュース:2011年を読んでいるとChromeがH.264のサポートを切る予定との報道もありましたが、現在はこのOpenH264を通じてChromeもFirefoxもH.264の再生は可能になっています。

しかし、これはあくまでビルド済みのバイナリを使う上では使用料いらないよということであって、オープンソースのコードを自分でビルドする場合はこの契約から外れるそうです(つまりライセンス料払う必要がある)。詳しくはこちら

早い話がOpenH264のリリースビルドを取ってくれば良いということなのでサクッとダウンロードします。

  1. https://github.com/cisco/openh264/releasesこのページにアクセス
  2. ただし、バージョンは正確に一致する必要がある。1.8.0を要求していて(この例)、2.0.0をダウンロードすると「バージョンが違うぞ」って怒られる。
  3. Windowsの場合は、OpenCVのバージョンにもよるが「openh264-1.8.0-win64.dll.bz2」をダウンロードすればOK
  4. ダウンロードしたアーカイブを解凍(WinRARでできる)
  5. dllファイルをPythonのカレントディレクトリにコピー

dllのコピーを忘れないようにしましょう。コードを実行するとH.264のMP4が出来上がります。

試しにローカルのMP4ファイルをFirefoxやChromeで開くと無事表示することができました。

アップロードし、WordPressでもちゃんとプレビューできるようになりました。やったぜ。

まとめ

OpenCVで保存した動画をブラウザ上で表示(サイト表示を含む)したいときは、H.264形式で保存するとよい。その際OpenH264が必要になるので、必要なバージョンを正確にダウンロードしましょう。

以上です。

Related Posts

TensorFlowで値のソートをする方法 TensorFlowでNumpyのnp.sortやnp.argsortのようなソートを行うことを考えます。一般にTensorFlowで値のソートというと、自動微分もあわさって難しいように思えますが、実はちゃんとソートできます。うまくやればKerasからも使うことができます。 tf.nn.top_...
ColabのTPUでNASNet Largeを訓練しようとして失敗した話... ColabのTPUはとてもメモリ容量が大きく、計算が速いのでモデルのパラメーターを多くしてもそこまでメモリオーバーor遅くなりません。ただし、あまりにモデルが深すぎると訓練の初期設定で失敗することがあります。NASNet Largeを訓練しようとして発生しました。これを見ていきます。 CIFAR...
PCA Color Augmentationを拡張してTensorFlow/Keras向けに実装した... PCA Color AugmentationはAlexNetの論文に示された画像向けのData Augmentationですが、画像用だけではなく、テンソルの固有値分解をすることで構造化データに対しても使えるようにしてみました。これの解説と効果を書きます。 リポジトリ こちら https://...
Pillowでグレースケール化するときに3チャンネルで出力するテクニック... カラー画像をグレースケール化すると1チャンネルの出力になりますが、カラー画像と同時に扱うと整合性からグレースケールでも3チャンネルで欲しいことがあります。Numpyのブロードキャストを使わずに簡単に3チャンネルで出力する方法を書きます。 グレースケール化してカラー化すればOK これでOK i...
Numpyだけでサクッと画像を拡大する方法... Numpyだけで画像をサクッと拡大する方法を紹介します。OpenCVやPillowを使うまでもないな、というようなときに便利な方法です。ニューラルネットワークでインプットのサイズを調整するときも使えます。 ただのNearest Neighbor法 拡大前の1ピクセルを1つの四角形と見立てて、拡...
Pocket
LINEで送る
Delicious にシェア

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です