🔰

MediaRecorderであっさりボイスチェンジャー

2021/11/16に公開

MediaRecorderとは!?

MediaRecorderは、メディアを簡単に記録するためのAPIです。

MediaRecorder

Howler.jsは、簡単にオーディオデータを再生する大人気ライブラリです。

Howler.js

今回はこのAPIとライブラリを使い、ボイスチェンジャーを作ってみます。

プロジェクトを用意する

次の様にプロジェクトを作ります。

MyProject01/
 ├ index.html (プログラムを起動するファイルです)
 ├ main.js (メインのプログラムを記述するファイルです)

HTMLファイルを用意する

では、作っていきましょう。
HTMLファイルを用意して、下記コードを記述します。

index.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8"/>
	<script src="https://cdn.jsdelivr.net/npm/howler@2.2.3/dist/howler.js" defer></script>
	<script src="./main.js" defer></script>
</head>
<body>
	<button id="btnStart">開始</button>
	<button id="btnStop">停止</button>
</body>
</html>

Howler.jsのライブラリのロードには、CDN(Contents Deliverly Network)を使っています。
(URLから直接ダウンロードする事で、プロジェクトがコンパクトになりますね)

JavaScriptファイルを用意する

いよいよ、メインの処理です。

全体の処理の流れは次の様になります。

  1. MediaDevicesの確認と準備する
  2. MediaRecorderの準備する
  3. スタート、ストップボタンを準備する
  4. データをBlob形式に変換し、更にBase64形式に変換する
  5. Howler.jsで再生する

1,MediaDevicesの確認と準備

"navigator.mediaDevices"を調べる事で、マイクにアクセスできるかを確認します。
そして、"navigator.mediaDevices.getUserMedia"関数を実行し、マイクへアクセスします。

main.js
// 省略
// 1-1, MediaDevicesが使えるかどうかを判定します
if(!navigator.mediaDevices){
	console.log("Media Devices not supported!!");
	return;
}

// 1-2, MediaDevicesを起動します
navigator.mediaDevices.getUserMedia({audio: true}).then((stream)=>{
	readyMediaRecorder(stream);// Ready
}).catch((err)=>{
	console.log("Error:" + err);// Error
});
// 省略

2,MediaRecorderの準備する

次は、MediaRecorderの準備です。

main.js
// 2-1, MediaRecorderを準備します
let mediaRecorder = new MediaRecorder(stream);

"mediaRecorder"オブジェクトには次のイベントを登録しておきます。
(onstopのタイミングで音声データを取得します)

イベント 実行されるタイミング
mediaRecorder.onstart 開始時に実行されます
mediaRecorder.onstop 停止時に実行されます
mediaRecorder.ondataavailable データが取得されるタイミングで実行されます
mediaRecorder.onerror エラー時に実行されます

3,スタート、ストップボタンを準備する

HTMLに配置してあるボタン2つにクリックイベントを設定しておきます。
スタートボタン、ストップボタンで次の2つの命令をそれぞれ実行します。

ボタン 命令 意味
スタートボタン mediaRecorder.start(); mediaRecorderを開始します
ストップボタン mediaRecorder.stop(); mediaRecorderを停止します
main.js
// 3-1, スタートボタン
document.getElementById("btnStart").onclick = ()=>{
	if(mediaRecorder.state == "recording") return;
	mediaRecorder.start();
	console.log("MediaRecorder:" + mediaRecorder.state);
}

// 3-2, ストップボタン
document.getElementById("btnStop").onclick = ()=>{
	if(mediaRecorder.state == "inactive") return;
	mediaRecorder.stop();
	console.log("MediaRecorder:" + mediaRecorder.state);
}

4,データをBlob形式に変換し、更にBase64形式に変換する

"chunks"配列には、"mediaRecorder.ondataavailable"で集めた音声データが格納されています。
ここでは、データ自体を"Blob"形式に変換し、更に"Base64"形式へ2段階で変換しています。

main.js
// 省略
// 4-1, Blob形式に変換する
const blob = new Blob(chunks, {"type":"audio/ogg; codecs=opus"});
const url = URL.createObjectURL(blob);
chunks = [];// 配列を初期化
// 4-2, Base64形式に変換する
let reader = new FileReader();// Reader
reader.readAsDataURL(blob);
reader.onload = ()=>{playHowl(reader.result);};
// 省略

5,Howler.jsで再生する

ここまで来れば、最後は簡単です。
"Base64"形式の文字列データに変換されたデータを、"Howler.js"を使って再生するだけです。

Howlには、次の様なオプションがあるので、参考にしてみてください。
特に"rate"を変更する事でボイスチェンジャーの効果を試す事ができます。

オプション 意味
loop 繰り返しを設定します
volume 音量を設定します
rate 再生レートを設定します

"Howler.js"については、以前の記事でも解説をしておりますので、よろしければご参照下さい。

main.js
// 5, Howlerを使って再生する
let snd = new Howl({
	src: base64,
	loop: false,// 繰り返し 
	volume: 1.0,// 音量
	rate: 1.4,  // 再生速度
	onplay: ()=>{
		console.log("サウンド再生!!");
	},
	onstop: ()=>{
		console.log("サウンド停止!!");
	},
	onpause: ()=>{
		console.log("サウンド一時停止!!");
	},
	onend: ()=>{
		console.log("サウンド終了!!");
	}
});
snd.play();

これだけでボイスチェンジャーが出来てしまいます。(やりました!!)

全体のコード

最後に、全体のコードを載せておきますね。

main.js
let chunks = [];// データを格納する配列

window.onload = ()=>{

	// 1-1, MediaDevicesが使えるかどうかを判定します
	if(!navigator.mediaDevices){
		console.log("Media Devices not supported!!");
		return;
	}

	// 1-2, MediaDevicesを起動します
	navigator.mediaDevices.getUserMedia({audio: true}).then((stream)=>{
		readyMediaRecorder(stream);// Ready
	}).catch((err)=>{
		console.log("Error:" + err);// Error
	});
}

function readyMediaRecorder(stream){

	// 2-1, MediaRecorderを準備します
	let mediaRecorder = new MediaRecorder(stream);

	// 2-2, MediaRecorderの開始
	mediaRecorder.onstart = (e)=>{
		console.log("onstart!!");
	}

	// 2-3, MediaRecorderの停止
	mediaRecorder.onstop = (e)=>{
		console.log("onstop!!");
		// 4-1, Blob形式に変換する
		const blob = new Blob(chunks, {"type":"audio/ogg; codecs=opus"});
		const url = URL.createObjectURL(blob);
		chunks = [];// 配列を初期化
		// 4-2, Base64形式に変換する
		let reader = new FileReader();// Reader
		reader.readAsDataURL(blob);
		reader.onload = ()=>{playHowl(reader.result);};
	}

	// 2-4, MediaRecorderにデータを追加
	mediaRecorder.ondataavailable = (e)=>{
		console.log("ondataavailable!!");
		chunks.push(e.data);
    }

    // 2-5, MediaRecorderのエラー
    mediaRecorder.onerror = (e)=>{
		console.log("onerror:" + e);
	}

	// 3-1, スタートボタン
	document.getElementById("btnStart").onclick = ()=>{
		if(mediaRecorder.state == "recording") return;
		mediaRecorder.start();
		console.log("MediaRecorder:" + mediaRecorder.state);
	}

	// 3-2, ストップボタン
	document.getElementById("btnStop").onclick = ()=>{
		if(mediaRecorder.state == "inactive") return;
		mediaRecorder.stop();
		console.log("MediaRecorder:" + mediaRecorder.state);
	}
}

function playHowl(base64){
	console.log("playHowl:" + base64);
	// 5, Howlerを使って再生する
	let snd = new Howl({
		src: base64,
		loop: false,// 繰り返し 
		volume: 1.0,// 音量
		rate: 1.4,  // 再生速度
		onplay: ()=>{
			console.log("サウンド再生!!");
		},
		onstop: ()=>{
			console.log("サウンド停止!!");
		},
		onpause: ()=>{
			console.log("サウンド一時停止!!");
		},
		onend: ()=>{
			console.log("サウンド終了!!");
		}
	});
	snd.play();
}

最後に

今回は、MediaDevicesとHowler.jsを使ってボイスチェンジャーを作ってみましたが、いかがでしたでしょうか!?
全体のコードとしてはとても短いものなので、是非挑戦してみてください。
ここまで読んでいただき有難うございました。

Discussion