本サイトはプロモーションが含まれています

JavaScriptを使ってWebブラウザ上で録音する無料のツールを作る方法(wav、mp3、flac対応)

導入

録音ツールは世の中にたくさんありますが、怪しい海外サービスも多いです。
ですが、今は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です


MediaStream Recording 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で作成しました。
なので、冒頭のツールのコードを直接録音に関係のある部分に絞って公開します。


streammediaRecorderなどの値の保持にuseRefaudioURLの値の保持に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は一見すると複雑ですが、一つ一つ整理していくと意外と単純です。
着実に理解し、ツールを完成させましょう!