WEBサイトに録音機能を追加したくてリサーチ開始。Flashで簡単に出来そうだと軽い気持ちで。しかしFlashでマイクを認識するまではいいが、録音データをクライアントに溜められないのでストリーミングサーバーを用意する必要があった。
ストリーミングサーバーは高価なFlashMediaServerかフリーのRed5。Red5を使う場合、開発はサーバー側がJavaでクライアント側はAS3。「ただ録音するだけなのに・・・」という感じ。(´・ω・`)
しかしFlashプラグイン10.1からクライアントに録音データを溜められるようになりストリーミングが必要なくなった事を知る。さらに手軽に録音できる「WAMI recorder」ライブラリを発見→録音機能あっという間に実装完了!そんなわけで「WAMI recorder」を紹介したいと思います。
出来上がりサンプル
デザインまで入れた状態のサンプルです。Flashの動作を許可すれば実際に録音できます。WAMIはJavascriptとSWFで動いています。デザインはbootstrapとJustGageを使いました。bootstrapのデザインについては解説する必要はないと思うので、説明はWAMIとJustGageのみに削ぎ落したソースを使います。
下準備
まずはWAMIとJustGageから必要なファイルをダウンロード。
WAMIには標準のGUI(gui.js)がついていますが、GUIは0から組むので必要なファイルは Wami.swf と recorder.js の2つです。
justGageで必要なファイルは justgage.1.0.1.min.js と raphael.2.1.0.min.js の2つ。
こちらで作成するのは index.html と wami.js と save.php の3ファイル、合計7ファイルを用意します。save.php は WAMI公式サイトのサンプルままです。WAMIはFLASHなのでファイルを直接ブラウザで表示しても動作しません。ローカルでもHTTPアクセスで。
HTML
まずHTMLですが、最低限の操作ボタンとWAMIとJustGageの為のdivを作っておきます。#wamiにはWami.setupでswfが入ってきます。
swfobject.js は WAMI に、raphael.js は JustGage に必要です。
- index.html
<html> <head> <meta charset="UTF-8" /> </head> <body> <div id="recorder" style="width: 340px; text-align: center;"> <button id="record" onclick="clickRecord()">録音</button> <button id="stop" onclick="clickStop()">停止</button> <button id="play" onclick="clickPlay()">再生</button> <div id="wami"></div> <div id="meter" style="width: 340px; height: 200px;"></div> <!--justgageはサイズ指定必須--> </div> <script src="https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script> <script src="recorder.js"></script> <script src="raphael.2.1.0.min.js"></script> <script src="justgage.1.0.1.min.js"></script> <script src="wami.js"></script> </body> </html>
JavaScript
各設定をグローバル変数で定義し、Wami.setupでWamiの初期化。操作ボタンのクリックに応じてWAMIの関数を実行しています。
ポイントは
- recordStart 内の setTimeout で最大録音時間を設定する
- setInterval で JustGage を動かす(戻り値は0-100)
- キャッシュが再生されるのを回避する
という感じです。動作には変数hostを定義する必要があります。
- wami.js
var mode; var timeLimit=10; // 録音制限 秒 var host = 'save.phpがあるURL'; // http://localhost/wami/ 等 var recording = 'temp.wav'; // ファイル名 var recordInterval, playInterval; var gage = new JustGage({ id: 'meter', value: 0, min: 0, // wamiのlevel戻り値は0-100 max: 100, showMinMax: false, title: 'Ready' }); Wami.setup({id:'wami'}); function clickRecord(){ mode = 'record'; var recordingUrl = host+'save.php?name='+recording; Wami.startRecording(recordingUrl,Wami.nameCallback(recordStart),Wami.nameCallback(recordFinish),Wami.nameCallback(wamiError)); } function stopRecording(){ Wami.stopRecording(); recordFinish(); } function recordStart(){ setTimeout('stopRecording()',timeLimit * 1000); // 録音時間制限 recordInterval = setInterval(function(){ var level = Wami.getRecordingLevel(); updateMeter(level); },100); } function recordFinish(){ clearInterval(recordInterval); updateMeter(0); } function clickPlay(){ mode = 'play'; var playUrl = host+recording+'?_='+(new Date)/1; // キャッシュ回避 Wami.startPlaying(playUrl,Wami.nameCallback(playStart),Wami.nameCallback(playFinish),Wami.nameCallback(wamiError)); } function stopPlaying(){ Wami.stopPlaying(); playFinish(); } function playStart(){ playInterval = setInterval(function(){ var level = Wami.getPlayingLevel(); updateMeter(level); },100); } function playFinish(){ clearInterval(playInterval); updateMeter(0); } function clickStop(){ if ( mode == 'record' ){ stopRecording(); } else if ( mode == 'play' ){ stopPlaying(); } } function wamiError( e ){ alert(e); } function updateMeter( level ){ gage.refresh(level); }
PHP
POST送信される音声データをファイル化するPHPです。公式サイトのものですが必要最低限ですので、運用する場合は容量制限などが必要です。
- save.php
<?php parse_str($_SERVER['QUERY_STRING'], $params); $name = isset($params['name']) ? $params['name'] : 'output.wav'; $content = file_get_contents('php://input'); $fh = fopen($name, 'w') or die("can't open file"); fwrite($fh, $content); ?>
出力されるファイル形式はwav。フォーマットは
- サンプリングレート 22.05kHz
- 量子化ビット 16ビット
- モノラル
です。現行バージョンのWAMIはフォーマットの変更が出来ないようです。
wavファイルのサイズ計算は、22050*16 を バイト化 / 8 で 44100 Byte/sec ですので、容量制限を行う場合は、
if ( $sec * 44100 < strlen($content) ){
exit;
}
[/code]
上のソースを file_get_contents の後に追加すれば、指定秒数を超えたデータは保存されません。
課題
WAMIはクライアントサイドで大きなファイルを扱う都合上、待ちが発生してモッサリ動作です。これはRed5などのストリーミングで解決するしかありません。
サーバー容量の問題もあります。サーバー側で定期的にmp3等の圧縮音源にエンコすれば解決しそうですが、再生は他のプレイヤーを使う必要がでてきます。でも、これだけ手軽に録音機能を構築できるWAMIは凄いです。(・∀・)
プログラミングで悩んだ時は
93%の回答率が売りのエンジニアのための無料Q&Aサイト「teratail」。長く悩んでも答えが出ない時の為に、登録しておけば助かるかもしれません。