導入
録音ツールは世の中にたくさんありますが、怪しい海外サービスも多いです。
ですが、今はJavaScriptを使えば、録音ツールを自分で手軽に作ることができます。
そこで今回の記事では、MediaStream Recording APIというブラウザ標準のAPIを使い、無料で使える録音ツールを作る方法を紹介します。
完成したものを公開しているので、興味があれば確認してみてください。
wavやmp3、flac形式でのダウンロードにも対応しているので、録音した音声を取っておきたいと思っている方はぜひ利用してください。
スポンサードリンク
完成したもの
シンプル録音ツールという名前で公開しています。
使いたい方は上のリンクから確認してみてください。
機能としては、
- 録音機能(5分まで)
- 決まった形式でのダウンロード機能(wav、mp3、flac対応)
の2つのシンプルな録音ツールです。
MediaStream Recording APIを使っているため、録音のデータはローカル上に保存されるので、安心して利用できます。
犯罪などに利用されることを防ぐため、利用規約を定めています。
一般的な利用の場合は問題ないので、「利用規約に同意する」にチェックを入れてから利用してください。
MediaStream Recording API
MediaStream Recording API (Media Recording API, MediaRecorder APIともいう) とは、ブラウザ上で使える、録画や録音を簡単に行うためのAPIです。
IE・Android Webviewを除く2021年以降の主要なブラウザに対応しています。
具体的な対応ブラウザのバージョンは、以下の通りです。
パソコン
ブラウザ | 対応バージョン |
---|---|
Google Chrome | バージョン49以降 |
Microsoft Edge | バージョン79以降 |
Apple Safari | バージョン14.1以降 |
Mozilla Firefox | バージョン29以降 |
スマホ・タブレット
ブラウザ | 対応バージョン |
---|---|
Google Chrome | バージョン49以降 |
Apple Safari | バージョン14.5以降 |
スポンサードリンク
実装方法
続いて、MediaStream Recording APIを使った録音機能の実装方法を紹介します。
このパートでは、録音機能の実装を以下の3つに分けて紹介します。
- 録音開始処理
- 録音終了処理
- 録音の再生・ダウンロード処理
それでは順に紹介します。
録音開始処理
まずは、録音開始処理を実装していきます。
マイクの権限取得
始めに、mediaDevices.getUserMedia
を使ってマイクの権限 を取得します。
audio: true
と記述することでマイクの権限のみを要求できます。
video: true
も記述すると、録画も可能です。
今回は録音のみなので、audio: true
のみ記述します。
// マイクの権限取得const stream = await navigator.mediaDevices.getUserMedia({ audio: true,});
録音の開始
次に、録音を開始するためMediaRecorder
インスタンスを作成し、start
メソッドを実行します。
// 録音の開始const mediaRecorder = new MediaRecorder(stream);mediaRecorder.start();
録音中の処理の定義
録音中の処理として、取得した音声を配列に格納します。
以下のコードでは、配列chunks
を定義し、録音中にondataavailable
メソッドが呼び出されるたびにchunks
に追加します。
// 録音中に音声を配列に追加const chunks = [];mediaRecorder.ondataavailable = e => { chunks.push(e.data);};
録音終了時の処理の定義
最後に、stop
メソッドが呼び出され、録音が終了した際の処理をonstop
に記述します。
以下のコードでは、chunks
に保存した音声データの配列をBlobにして、1つの音声として扱えるようにし、再生時に使用するURLをwindow.URL.createObjectURL
を使って作成しています。
このURLと音声データはユーザーのメモリ上に保存されるため、ツール作成者が録音を聞くことはできません。
// 録音終了時に音声再生用のURLを発行let audioURL;mediaRecorder.onstop = () => { const audioBlob = new Blob(chunks); audioUrl = window.URL.createObjectURL(audioBlob);};
ちなみに、特定の音声ファイル形式(wavなど)で保存したい場合、Blob内で以下のように指定できます。
const audioBlob = new Blob(chunks, { type: "audio/wav" });
録音終了処理
続いて、録音終了時の処理を実装します。
録音終了時の実装はシンプルで、まずMediaRecorderのstop
メソッドを呼び出し、onstop
イベントを発生させ、先ほど記述した録音終了時の処理を実行します。
続いて、mediaDevices.getUserMedia
で取得したストリームの各trackについてstop
メソッドを呼び出し、音声ストリームを閉じます。
ここでストリームのstop
を呼び出さないと、録音終了後もブラウザのタブに赤いマイクアイコンが付いたままになるので注意してください。
mediaRecorder.stop();stream.getTracks().forEach(track => { track.stop();});
スポンサードリンク
録音の再生・ダウンロード処理
最後に、録音の再生とダ ウンロード処理を実装します。
録音の再生
録音の再生は<audio>
タグを使って、音声再生用のURL(先ほどの例では、audioURL
)を指定することで、再生ボタンを押すと再生できます。
例えば、素のJavaScriptでは以下のように実装します。
<audio id="audio" controls></audio>
const audioElement = document.getElementById("audio");audioElement.src = audioURL;
録音のダウンロード
録音のダウンロードは、JavaScriptで新しい<a>
タグを作成し、音声再生用のURL(先ほどの例では、audioURL
)とdownload属性にファイル名を指定します。
そして、その<a>
タグのclick
を実行することでダウンロード可能です。
const downloadElement = document.createElement("a");downloadElement.href = audioURL;downloadElement.download = 'recording.mp3';downloadElement.click();
また、音声再生用のURL(先ほどの例では、audioURL
)は使用されなくなったタイミングでwindow.URL.revokeObjectURL
を実行し、無効にしてください。
放置されたままだとメモリを専有し、サイトの動作が遅くなってしまいます。
window.URL.revokeObjectURL(audioURL);
Reactを使った録音ツールの実装例
ここまでは素のJavaScriptを使用した実装を紹介しましたが、冒頭で紹介したツールはReactで作成しました。
なので、冒頭のツールのコードを直接録音に関係のある部分に絞って公開します。
stream
やmediaRecorder
などの値の保持にuseRef
、audioURL
の値の保持にuseState
を使っているのが、素のJavaScriptを使った時との大きな違いです。
const Recording = () => { const supportedAudioTypes = ["wav", "mp3", "flac"]
const [recording, setRecording] = useState(false) // 録音中かどうか const [audioURL, setAudioURL] = useState("") const [audioType, setAudioType] = useState("wav") const mediaRecorderRef = useRef() const streamRef = useRef() const chunksRef = useRef()
const recordingStart = async () => { if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { try { setRecording(true) if (audioURL) { window.URL.revokeObjectURL(audioURL) }
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, })
const mediaRecorder = new MediaRecorder(stream) mediaRecorder.start()
const chunks = [] mediaRecorder.ondataavailable = e => { chunks.push(e.data) }
mediaRecorder.onstop = () => { const audioBlob = new Blob(chunks) const url = window.URL.createObjectURL(audioBlob) setAudioURL(url) }
streamRef.current = stream mediaRecorderRef.current = mediaRecorder chunksRef.current = chunks } catch (e) { // 失敗したとき console.error(e) setRecording(false) } } }
const recordingStop = () => { mediaRecorderRef?.current.stop() streamRef?.current.getTracks().forEach(track => { track.stop() }) setRecording(false) }
const clickButton = () => { if (recording) { recordingStop() } else { recordingStart() } }
const downloadRecording = () => { if ( chunksRef && chunksRef.current && supportedAudioTypes.includes(audioType) ) { const audioBlob = new Blob(chunksRef.current, { type: `audio/${audioType}`, })
const tempURL = window.URL.createObjectURL(audioBlob)
const downloadElement = document.createElement("a") downloadElement.href = tempURL downloadElement.download = `recording.${audioType}` downloadElement.click() window.URL.revokeObjectURL(tempURL) } }
return ( <> <h1>シンプル録音ツール</h1> <div className="recording-main-menu"> <div className="recording-buttons"> <button className="simple-button" onClick={clickButton} > {recording ? "録音終了" : "録音開始"} </button> </div> <audio controls src={audioURL} controlsList="nodownload"></audio> <div className="recording-download-menu"> <span> ダウンロードする形式: <select value={audioType} onChange={e => setAudioType(e.target.value)} > {supportedAudioTypes.map(type => { return ( <option key={type} value={type}> {type} </option> ) })} </select> </span> <button className="simple-button" disabled={!audioURL} onClick={downloadRecording} > 録音のダウンロード </button> </div> </div> </> )}
スポンサードリンク
まとめ
今回はJavaScriptを使って、録音ツールを作成する方法を紹介しました。
MediaStream Recording APIは一見すると複雑ですが、一つ一つ整理していくと意外と単純です。
着実に理解し、ツールを完成させましょう!