まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:media

みんな大好き WordPress 。自分もローカルコンテナやクラウド、ホスティングなど色々な形態で活用しています。最近は k8s などのパブリックなコンテナ環境下で使われることも珍しくなくなってきました。

実際に環境構築した経験のある人はわかると思いますが、この WordPress はシングルサーバーのシングルテナント構成(サーバーもインスタンスも1台で、1つの WordPress サイトを作る構成)であれば構築手順は簡単なのですが、負荷分散を考慮して複数サーバーインスタンス化した構成を考慮に入れるととたんにややこしくなります。理由もシンプルではないのですが、最大の問題はメディアストレージと呼ばれる画像などのファイルアップロード空間がファイルシステムを前提としている点にあります。簡単に説明すると、コンテンツ内で使う画像をアップロードすると、その画像はサーバーのファイルシステム上に保存されます。表示される際も当然サーバーのファイルシステム上の画像を参照することになります。サーバーが1台であればこれで問題ないのですが、サーバーが複数台(例えばAとBの2台)あった場合、サーバーAのファイルシステムに画像を保存して、サーバーAから画像を参照すると画像が見えますが、サーバーBのファイルシステムには画像は存在していないので、参照しても見つからない、という結果になってしまいます。負荷分散の仕組みが存在している以上、サーバーAを使うかサーバーBを使うかは毎回変わる可能性があるので、アクセスするたびに画像が見えたり見えなかったりすることになります。サーバーが3台、4台と増えていくと、画像が見える確率はどんどん下がっていきます。これでは使い物になりません。

そのため、WordPress では一般的にメディアストレージには全サーバーから参照可能な共有ストレージをマウントして指定します。こうすることで全サーバーが同じストレージにメディアファイルをアップロードすることになり、全てのサーバーから参照可能になる、というわけです。WordPress 環境構築時によく使う典型的な作業でもあり、この機能に関連した多くのプラグインも提供されています。

で、この WordPress の共有メディアストレージに IBM Cloud の Object Storage を指定する方法を調べたので、自分用メモの意味も込めてまとめました。IBM Cloud の Object Storage はいわゆる「S3互換」のオブジェクトストレージで、一定の条件下で無料利用(しかもクレジットカード不要!)できます。詳しくは後述の説明を参照いただきたいのですが、無料枠でも容量としては 25GB まで使えるので、WordPress の規模としてはそこそこ大きなものでもまかなえる共有ストレージだと思っています。


【WordPress 環境の準備】
まずは WordPress 環境を用意します。具体的には MySQL データベースサーバーと、WordPress が展開された HTTP サーバー。複数サーバーでなければ localhost で構築してもいいですし、ローカルの docker/docker Compose で用意してもいいし、有料/無料のクラウド/ホスティングサーバーを使っても構いません。管理者権限でログイン可能な WordPress 環境を1つ用意してください。この時点ではメディアストレージに特別な設定は不要で、デフォルトのファイルシステムをそのまま使う設定であると仮定します。


【IBM Cloud Object Storage(IBM COS) の準備】
次に上述環境のメディアストレージとなる IBM COS を用意します。IBM Cloud アカウントを所有していない場合はこちらから作成してください(作成後にクレジットカードを登録することでより多くのサービスを利用できるようになりますが、今回紹介している内容をそのまま実行するだけであれば登録しないアカウントでも可能です):
https://cloud.ibm.com/registration


IBM Cloud アカウントでログイン後、ダッシュボード画面から「リソースの作成」ボタンをクリックします:
2021092101


検索ボックスに "object storage" と入力し、見つかった "Object Storage" を選択します:
2021092102


次の画面で料金プランを選択します。料金体系が "Free" と表示されたライトプランが選択されていることを確認してください(ライトプランは無料ですが、Standard プランは有料です)。そして画面右下の「作成」ボタンをクリックします:
2021092103



なお、このライトプランの制約事項は以下のようなものです。ストレージ容量としては 25GB ですが、リクエストの回数やパブリックアウトバウンド容量などに一か月単位の上限が設定されています。また30日間非アクティブな状態が続くと削除されます(このプランのままこの制約を超えて使うことはできませんが、有料プランにアップグレードすることで制約を超えて使うことは可能です)。ご注意ください:
2021092104


Cloud Object Storage サービスが作成され、以下のような画面が表示されます:
2021092105


ではこの Object Storage にデータ(今回は画像)を格納するバケットを作成します。左メニューから「バケット」を選び、「バケットの作成」ボタンをクリックします:
2021092101


バケットの属性を選択したり、カスタマイズできたりするのですが、今回は定義済みのバケットを使うことにします。「すぐに始める」と書かれたカードの→印部分をクリック:
2021092102


ここでは3ステップでバケットを定義しますが、実質的に最初のここだけがカスタマイズ部分となります。これから作成するバケットの名称を適当に入力します。以下の例では WordPress のメディアストレージ向けということで、自分の名前も使って "kkimura-wordpress-media" と入力しています。ここは皆さんがわかりやすい名前を入力してください。そして「次へ」:
2021092103


次の画面ではそのまま「次へ」:
2021092104


最後の画面も特に変更する必要はありません。そのまま「バケット構成の表示」ボタンをクリックします:
2021092105


すると入力した名称でバケットが作成されます。この時に「ロケーション」欄に表示されている内容は後で使うのでメモしておきます(下図の例だと "jp-tok"):
2021092106


バケットが作成できたら、次はこのバケットを外部から(今回の例だと WordPress から)利用できるようにするための情報を取得します。画面左のメニューで「サービス資格情報」を選択し、「新規資格情報」ボタンをクリックします:
2021092107


資格情報の作成ダイアログが表示されたら「詳細オプション」を開き、役割が「ライター」になっていることを確認した上で、「HMAC 資格情報を含める」をオンにしてから「追加」ボタンをクリックします:
2021092108


いま追加した資格情報が一覧に表示されるので、名称部分をクリックして展開します:
2021092109


以下のように追加したサービス資格情報が表示されます:
2021092110


サービス資格情報は以下のようなフォーマットになっているので、"cos_hmac_keys" の中の "access_key_id" の値と、"secret_access_key" の値をメモしておいてください:
{
  "apikey": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "cos_hmac_keys": {
    "access_key_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "secret_access_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "endpoints": "https://control.cloud-object-storage.cloud.ibm.com/v2/endpoints"
    :
    :
}

※ サービス資格情報に cos_hmac_keys というキーそのものが存在していない場合は、資格情報を作成する際に「HMAC 資格情報を含める」オプションをオンにしていない可能性があります。上述の手順を再度確認してもう一度実行してみてください。


最後にエンドポイントを確認します。画面左メニューから「エンドポイント」を選択し、バケットを作成した時に確認したロケーション情報( Regional の jp-tok)に合わせて「回復力」と「ロケーション」を設定し、そこで表示されるパブリック URL の内容をメモしておきます:
2021092111


これで IBM COS 側の設定と準備も完了です。改めて、この時点で  IBM COS に関する以下の情報が入手できていることを確認してください。これらがすべてわかっていれば WordPress のメディアストレージとしてマウントできるようになります(手順は後述します):
取得・確認方法
バケット名バケット作成時に指定した名前
access_key_idサービス資格情報内
secret_access_keyサービス資格情報内
エンドポイント作成したバケットのロケーション情報に合わせて取得したパブリック URL


【Media Cloud プラグインのインストールと設定】
ここまでの手順が正しく実施できて、上述の4つの情報が取得できていれば WordPress に IBM COS のバケットをメディアストレージとしてマウントできる準備が整ったことになります。以下では実際にマウントする手順を紹介します。

まず WordPress の管理機能にアクセスできるアカウントでログインし、管理画面に移動します。まずObject Storage をメディアストレージとしてマウントするための Media Cloud プラグインをインストールします。画面左のメニューから「プラグイン」を選び、「新規追加」ボタンをクリックします:
2021092201


キーワード検索ボックスに "Media Cloud" と入力します:
2021092202


候補がいくつか見つかりますが、その中に以下のような "Media Cloud for Amazon S3, ..." というプラグインが見つかります。ここの「今すぐインストール」をクリックしてインストールします:
2021092203


インストールに成功すると「有効化」というボタンに変わります。このボタンもクリックしてプラグインを有効にします:
2021092204


更新通知機能をオプトインするかどうかを聞かれます。オプトインする場合は「許可して続ける」、したくない場合は「スキップ」のいずれかを選んで先へ進みます:
2021092205


Media Cloud のセットアップウィザードが起動します。まずは Next をクリック:
2021092206


最初に Object Storage のプロバイダーを選択します。IBM COS の場合は "S3 Compatible" を選択します:
2021092207


S3 互換ストレージの設定が開始されます。"Next" をクリック:
2021092201


次の画面で先程準備した IBM COS の情報を入力します。入力内容は以下のようにします:
項目名入力する値
ACCESS KEYaccess_key_id の値
SECRETsecret_access_key の値
BUCKET作成したバケット名
REGION(Automatic のまま)
CUSTOM ENDPOINTエンドポイント URL

最後に "Next" をクリック:
2021092202


入力した値が正しく利用できるかどうかを確認するいくつかのテストを行います。"START TESTS" をクリック:
2021092203


実際にバケットに対してファイルをアップロードして、アップロードできていることを確認して、削除して・・・といったテストが行われます。すべて成功すると下図のように5つのグリーンでチェックマークが表示され、正しく利用できる状態であることが確認されました。"Next" をクリック:
2021092204


これで Media Cloud を利用できる状態になりました。"FINISH & EXIT WIZARD" をクリックして設定ウィザードを終了します:
2021092205


WordPress の管理画面に戻り、"Media Cloud" メニュー内の "Enable Cloud Storage" がオンに設定されていることを確認します:
2021092206


ちなみに、ここで設定した値は MySQL データベースの wp_options テーブル内に格納されているようです。なので、この状態で(データベースへの接続情報が含まれた状態で)サーバーの内容をコンテナイメージ化すれば、コンテナ環境でも動く状態が作れる、と思います:
2021092201



最後にメディアストレージが Object Storage に切り替わっていることを WordPress 内からも確認しておきましょう。管理画面の「メディア」を選択し、メディアライブラリの「新規追加」で適当な画像ファイルを選択して追加します:
2021092207


試しにこんな感じで1つ画像をアップロードしてみました(この画像は WordPress のコンテンツとして利用することができず状態になっています):
2021092208


改めて IBM Cloud のダッシュボードに戻り、IBM Cloud Object Storage のバケット内を表示してみると、画像ファイルが追加されているはずです(2つ追加されているのは、1つのアップロードに対して元画像とサムネイル用の2つの画像が追加されているからのようです):
2021092209


画像を1つ選択すると右にウィンドウが表示され、ここからダウンロードすることができます:
2021092201


実際にダウンロードして表示し、WordPress 画面からアップロードした画像が Object Storage に格納されていることを確認します:
2021092202


WordPress のメディアストレージとして IBM Cloud の Object Storage を利用できることが確認できました。IBM Cloud の Cloud Object Storage を使うことである程度の規模まで無料でこの環境での運用ができるので、バケットを複数用意して使うケースも含めて、実運用前の構築段階ではとても便利に使うことができそうです。

JavaScript(HTML5) の機能だけで、PC に付属したマイクから音声を入力(つまり PC の前で喋った音声データを取り込む)してみました。なお、この機能を使うには UserMedia に対応したブラウザが必要です。以下のコードは Windows 版の FireFox で動作確認をしています。

サンプルのコードはこんな感じになります:
<html>
<head>
<title>HTML5 Audio</title>
<script type="text/javascript"> 
//. ブラウザによる差異を吸収
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
 
//. バッファサイズ等
var audioContext = new AudioContext();
var bufferSize = 4096;
var cnt = 0;
 
//. 音声処理
function onAudioProcess( e ){
  //. 取得した音声データ
  var input = e.inputBuffer.getChannelData(0);

//. ↑この input に音声データが入っているので、これをストリーミングなどで処理すればよい。
//. 以下は実際にデータが入っていることを確認するためのサンプル処理
//. 音声データの最大・最小値を求める var mx = 0, mn = 0; for( var i = 0; i < bufferSize; i ++ ){ if( mx < input[i] ){ mx = input[i]; } if( mn > input[i] ){ mn = input[i]; } } //. 一度に取得した音声データの最大・最小値を求める(特に意味は無いが、データが取得できている確認) cnt ++; console.log( "[" + cnt + "] min = " + mn + ", max = " + mx ); } //. 音声処理開始 function initialize(){ navigator.getUserMedia( { audio: true }, function( stream ){ //. 音声処理 var javascriptnode = audioContext.createScriptProcessor( bufferSize, 1, 1 ); var mediastreamsource = audioContext.createMediaStreamSource( stream ); window.dotnsf_hack_for_mozzila = mediastreamsource; //. https://support.mozilla.org/en-US/questions/984179 mediastreamsource.connect( javascriptnode ); javascriptnode.onaudioprocess = onAudioProcess; javascriptnode.connect( audioContext.destination ); },function( e ){ console.log( e ); } ); } </script> </head> <body onload="initialize()"> </body> </html>

余談ですが、上記コードの赤字部分は今回一番迷った所。どうも FireFox のバグらしく、取得したメディアストリームがいつの間にか消えて(音声入力処理が止まって)しまう、という現象に遭遇しました。そのバグを回避するため、無理やり取得した値をグローバル変数化して消えないようにしています。バグの詳細についてはこちら:
https://support.mozilla.org/en-US/questions/984179


この HTML をマイク入力を ON にした状態で対象ブラウザで開くと、「PC のマイクをこのアプリと共有しますか?」という確認メッセージが表示されます。ここで「共有」を選択してください:
2016030301

共有すると画面に FireFox がマイクを利用中であること(知らないうちに音声を取得しているわけではないこと)を知らせるマークが表示されます。このマークが出ている間は PC のマイクで拾った音声をこのウェブページで共有していることを表しています:
2016030302


ここで F12 キーを押すとデバッグ画面が表示され、コンソールタブを見ると取得した音声データ1まとまり(4Kbyte)単位での最大値と最小値(簡単にいうと音の大きさ)を表示し続ける、というアプリになっています。
2016030303


実際には取得した音声データを保存(録音)して再生できるようにするとか、ストリーミングで処理してテキスト化するとか、・・・ という使い方になると思いますが、その入力を HTML で行う方法の紹介でした。

このページのトップヘ