作ったもの
Voice Memo — https://sen.ltd/portfolio/voice-memo/
- MediaRecorder API で音声録音
- IndexedDB に blob 保存(localStorage だと容量不足)
- 録音中の波形を Canvas + AnalyserNode でライブ描画
- 再生シークバー
- Web Speech API で文字起こし(ベストエフォート)
- ラベル / タグ / 削除
- エクスポート
vanilla JS、ゼロ依存、ビルド不要。node --test で 55 ケース。
MediaRecorder とフォーマット選択
Chrome は WebM/Opus、Safari は MP4/AAC を好む。MediaRecorder.isTypeSupported でフォールバック:
['audio/webm;codecs=opus', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/mp4']
.filter(MediaRecorder.isTypeSupported)
ライブ波形は AnalyserNode
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
source.connect(analyser);
const buffer = new Uint8Array(analyser.fftSize);
function draw() {
analyser.getByteTimeDomainData(buffer);
drawWaveform(canvas, buffer);
requestAnimationFrame(draw);
}
buffer は 0-255 の PCM サンプル(128 が無音)。Canvas に折れ線で描画するだけでリアルタイム波形ができる。
localStorage ではなく IndexedDB
音声 blob は数百 KB〜数 MB。localStorage は 5-10 MB の制限 + 文字列のみなので base64 エンコードで 33% 肥大化。IndexedDB は blob ネイティブ対応でクォータも大きい。
Web Speech API での文字起こしの工夫
Web Speech API はマイク入力のみを認識対象とする。保存した blob を直接転写できない。仕方ないのでスピーカーから再生しつつ同時にマイクで拾う方式(ベストエフォート)。正攻法は Whisper などのサーバサイド。
シリーズ
100+ 公開ポートフォリオ シリーズの #71 です。
- 📦 リポジトリ: https://github.com/sen-ltd/voice-memo
- 🌐 デモ: https://sen.ltd/portfolio/voice-memo/
- 🏢 会社: https://sen.ltd/
