JavaScript/HTML5おぼえがき

JavaScriptJavaScript/HTMLサイトマップホーム

音の再生

mp3/oggファイルの再生   戻る

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-language" content="ja">
<meta charset="UTF-8">
<title>音楽の再生</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body onload ="init()">
<audio controls>
<source src="../sound/Yesterday.mp3">
<source src="../sound/Yesterday.ogg"> </audio><br>
<br>
<br>
<button onclick="ply();">先頭から再生</button>
<button onclick="pus();">一時停止</button>
<button onclick="rst();">再生</button>
<button onclick="stp();">停止</button>
<SCRIPT>
//<!-- 
function init() {
  ad = new Audio("");
  if(ad.canPlayType){
    var canPlayOgg = ("" != ad.canPlayType("audio/ogg"));
    var canPlayMp3 = ("" != ad.canPlayType("audio/mpeg"));
    if(canPlayOgg && canPlayMp3){
      window.alert("ogg/mp3をサポートしています。") ;
      ad.src = "../sound/Yesterday.ogg" ; 
    }else if(canPlayOgg){
      window.alert("oggをサポートしています。") ;
      ad.src = "../sound/Yesterday.ogg" ;
    }else if(canPlayMp3){
      window.alert("mp3をサポートしています。") ;
      ad.src = "../sound/Yesterday.mp3" ;
    }else{
      window.alert("oggもmp3もサポートしていません") ;
    }
  }else{
    window.alert("canPlayTypeメソッドが存在しません") ;
  }
}
function rst(){ ad.play(); }  // 再生(一時停止中は一時停止箇所から再生) 
function ply(){               //  先頭から再生 
  ad.load();  // ロードを実行して初期状態に戻す
  ad.play();
}  
function pus(){ad.pause();}   // 一時停止 
function stp(){               // 停止 
  if(!ad.ended){        // ended属性で終了判定する
    ad.pause();
    ad.currentTime = 0;  // 再生位置を0秒にする
  }
}
//-->
</script></body>
</html>

テキストの読上げ   戻る

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-language" content="ja">
<meta charset="UTF-8">
<TITLE>テキスト読上げ</TITLE>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body> 
<form name="form">
<input type="button" onclick="speak(form.jp.value,'ja-JP')" value="日本語">
<input type="text" name="jp" value ="おはようございます"><br>
<input type="button" onclick="speak(form.en.value,'en-US')" value="English">
<input type="text" name="en" value ="Good Morning">
</form>
<SCRIPT>
function speak(text,lang) {
  var synthes = new SpeechSynthesisUtterance();
  synthes.volume = 1;  //音量
  synthes.rate = 1;    //スピード
  synthes.pitch = 0;   //ピッチ
  synthes.text = text;
  synthes.lang = lang ;  //言語
  speechSynthesis.speak(synthes);
}
</script>
</body>
</html>

音声認識   戻る

音声認識開始ボタンで開始します。プラウザはGoogle Chromeで動作致します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>音声認識</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<button onclick="recognition.start();">音声認識開始</button>
<button onclick="recognition.stop();">停止</button>
<div id="resultdiv"></div>
<script>
  SpeechRecognition = webkitSpeechRecognition || SpeechRecognition ;
  recognition = new SpeechRecognition() ;
  recognition.lang = 'ja-JP' ;
  recognition.interimResults = true ;
  recognition.continuous = true ;

  finalTranscript = '' ; // 確定した認識結果
  recognition.onresult = function (e) {
    interimTranscript = '' ; // 暫定の認識結果
    for (i = e.resultIndex; i < e.results.length ; i++) {
      transcript = e.results[i][0].transcript ;
      if (e.results[i].isFinal) {
        finalTranscript += transcript + '<br>' ;
      } else {
        interimTranscript = transcript ;
      }
    }
    resultdiv.innerHTML = finalTranscript + '<i style="color:#f00;">' + interimTranscript + '</i>' ;
  }
</script>
</body>
</html>

音声の録音(wav)   戻る

wavファイルは、主にWindows環境で標準的に使用される非圧縮の音声ファイル形式で、多くのソフトウェアで扱うことができます。
音声データを圧縮せずにそのまま保存するためにファイルサイズが大きくなり、音質劣化が少ないのが特徴です。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Recording(wav)</title>
<script src="https://cdn.webrtc-experiment.com/RecordRTC.js"></script>
</head>
<body>
<h1>Recording(wav)</h1>
<button id="startBtn">録音開始</button> <button id="stopBtn" disabled>録音停止</button><br>
<audio id="audio" controls></audio><br>
<button id="dloadBtn">ダウンロード</button>
<script>
let recorder; // RecordRTCのインスタンス
let audioStream; // マイクストリーム

async function srt() {  // マイク入力を取得  
  audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
}
srt() ;
async function startRecording() {  // マイク入力を取得  
  recorder = new RecordRTC(audioStream, {  // RecordRTCのインスタンスを作成 (mp3フォーマットを指定)
    type: "audio",
    mimeType: "audio/wav", // MP3 ではなく WAV を指定 (後で MP3 に変換可能)
    recorderType: StereoAudioRecorder,
    desiredSampRate: 16000, // サンプリングレート (16kHz)
  });
  recorder.startRecording();
  console.log("録音開始");
  document.getElementById("startBtn").disabled = true;
  document.getElementById("stopBtn").disabled = false;
  document.getElementById("dloadBtn").disabled = true;
}
function stopRecording() {
  recorder.stopRecording(() => {
    const blob = recorder.getBlob(); // 録音データ (WAV形式)
    audioUrl = URL.createObjectURL(blob);// ダウンロードリンクを生成
    document.getElementById("audio").src = window.URL.createObjectURL(blob);
  });
//  audioStream.getTracks().forEach((track) => track.stop());  // ストリームを停止
    document.getElementById("startBtn").disabled = false;
    document.getElementById("stopBtn").disabled = true;
    document.getElementById("dloadBtn").disabled = false;
}
document.getElementById("dloadBtn").disabled = true;
dloadBtn.onclick = function() {
    const a = document.createElement("a");
    a.href = audioUrl;
    a.download = "recording.wav"; // WAVファイルをダウンロード

    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    console.log("録音停止・ファイルをダウンロードしました");
    document.getElementById("dloadBtn").disabled = true;

}
// ボタンイベントの設定
document.getElementById("startBtn").addEventListener("click", startRecording);
document.getElementById("stopBtn").addEventListener("click", stopRecording);
const fileInput = document.getElementById('fileInput');
const audioPlayer = document.getElementById('audioPlayer');
</script>
</body>
</html>

音声の録音(weba)   戻る

webaファイルは、主にウェブ上で動画を配信する際に利用される「webmファイル」から、音声部分だけを抽出したものです。
音声圧縮形式でエンコードされており、比較的高音質でありながらファイルサイズを小さく保つことができます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Audio Recording(waba)</title>
</head>
<body>
<h1>Audio Recording(waba)</h1>
<button id="startBtn">録音開始</button> <button id="stopBtn">録音停止</button><br>
<audio id="audio" controls></audio><br>
<button id="dloadBtn">ダウンロード</button>
<script>
var mediaRecorder;
var localStream;
  let onSuccess = function (stream) {
    localStream = stream;
    mediaRecorder = new MediaRecorder(stream);
  }
  let onError = function (err) { console.log("The following error occured: " + err); };
  navigator.mediaDevices.getUserMedia({ audio: true }).then(onSuccess, onError);
startBtn.onclick = function () {
//mediaRecorder = new MediaRecorder(stream);
  mediaRecorder.start();
  console.log("Status: " + mediaRecorder.state);
  startBtn.disabled = true;
  stopBtn.disabled = false;
  dloadBtn.disabled = true;
}
stopBtn.onclick = function () {
    mediaRecorder.stop();
    console.log("Status: " + mediaRecorder.state);
    mediaRecorder.ondataavailable = function (event) {
    document.getElementById("audio").src = window.URL.createObjectURL(event.data);
    audioUrl = URL.createObjectURL(event.data);
    }
    localStream.getTracks().forEach(track => track.stop());
    startBtn.disabled = false;
    stopBtn.disabled = true;
    dloadBtn.disabled = false;
}
dloadBtn.onclick = function() {
    const a = document.createElement("a");
    a.href = audioUrl;
    a.download = "recording.waba"; // WAVファイルをダウンロード
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    console.log("録音停止・ファイルをダウンロードしました");
    dloadBtn.disabled = true;
}
</script>
</body>
</html>

音声ファイル変換(wavからmp3)   戻る

mp3ファイルは音声データを圧縮してファイルサイズを小さくするため、多くの楽曲を保存・共有するのに適しています。
圧縮の際に人間の聴覚では感知しにくい部分のデータを削除するため、元の音源に比べて音質が劣化しますが、 一般的なリスニング環境ではほとんど気にならない程度です。
多くのデバイスやソフトウェアでサポートされており、最も一般的な音声ファイル形式の一つです。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WAV to MP3 Converter</title>
</head>
<body>
<h2>WAV to MP3 Converter</h2>
<input type="file" id="fileInput" accept="audio/wav">
<script src="https://cdn.jsdelivr.net/npm/lamejs@latest/lame.all.js"></script>
<script>
document.getElementById('fileInput').addEventListener('change', async function (event) {
  const file = event.target.files[0];
  if (!file) return;

  const wavBuffer = await file.arrayBuffer();
  const mp3Blob = convertWavToMp3(wavBuffer);

  const mp3Url = URL.createObjectURL(mp3Blob);
  const downloadLink = document.createElement('a');
  downloadLink.href = mp3Url;
  downloadLink.download = 'converted.mp3';
  document.body.appendChild(downloadLink);
  downloadLink.click();
  document.body.removeChild(downloadLink);
});
function convertWavToMp3(wavBuffer) {
  const wavView = new DataView(wavBuffer);
  const wavHeader = lamejs.WavHeader.readHeader(wavView);
  const samples = new Int16Array(wavBuffer, wavHeader.dataOffset, wavHeader.dataLen / 2);

  // チャネル数を取得
  const channels = wavHeader.channels;
  // ステレオの場合、左右のチャンネルを分離
  let leftChannel, rightChannel;
  if (channels === 2) {
    leftChannel = new Int16Array(samples.length / 2);
    rightChannel = new Int16Array(samples.length / 2);
    for (let i = 0, j = 0; i < samples.length; i += 2, j++) {
      leftChannel[j] = samples[i];
      rightChannel[j] = samples[i + 1];
    }
  } else { leftChannel = samples; } // モノラルの場合、そのまま使用
  const mp3Encoder = new lamejs.Mp3Encoder(channels, wavHeader.sampleRate, 128);
  const mp3Data = [];
  const chunkSize = 1152;
  for (let i = 0; i < leftChannel.length; i += chunkSize) {
    const leftChunk = leftChannel.subarray(i, i + chunkSize);
    let mp3buf;     
    if (channels === 2) {
      const rightChunk = rightChannel.subarray(i, i + chunkSize);
      mp3buf = mp3Encoder.encodeBuffer(leftChunk, rightChunk);
    } else { mp3buf = mp3Encoder.encodeBuffer(leftChunk); }
    if (mp3buf.length > 0) mp3Data.push(mp3buf);
  }
  const finalMp3 = mp3Encoder.flush();
  if (finalMp3.length > 0) mp3Data.push(finalMp3);
  return new Blob(mp3Data, { type: 'audio/mp3' });
}
</script>
</body>
</html>

音声ファイル変換(webaからmp3)   戻る

WebAデコード
 ・AudioContext を使って WebA を PCM(WAV)にデコード。
 ・decodeAudioData() を使用。
PCMをMP3にエンコード
 ・lamejs を使って MP3に変換。
 ・ステレオ(2ch)とモノラル(1ch)両対応。
PCMを16bit整数に変換
 ・lamejs は 16bit PCMデータ を必要とするため、floatTo16BitPCM() を使用して変換。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebA to MP3 Converter</title>
</head>
<body>
    <h2>WebA to MP3 Converter</h2>
    <input type="file" id="fileInput" accept="audio/webm, audio/weba">
    <script src="https://cdn.jsdelivr.net/npm/lamejs@latest/lame.all.js"></script>
    <script>
/*
WebAデコード
 ・AudioContext を使って WebA を PCM(WAV)にデコード。
 ・decodeAudioData() を使用。
PCMをMP3にエンコード
 ・lamejs を使って MP3に変換。
 ・ステレオ(2ch)とモノラル(1ch)両対応。
PCMを16bit整数に変換
 ・lamejs は 16bit PCMデータ を必要とするため、floatTo16BitPCM() を使用して変換。
*/
document.getElementById('fileInput').addEventListener('change', async function (event) {
  const file = event.target.files[0];
  if (!file) return;
  try {
    const audioBuffer = await decodeWebA(file);
    const mp3Blob = convertToMp3(audioBuffer);

    const mp3Url = URL.createObjectURL(mp3Blob);
    const downloadLink = document.createElement('a');
    downloadLink.href = mp3Url;
    downloadLink.download = 'converted.mp3';
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  } catch (error) {
      console.error('変換エラー:', error);
      alert('変換に失敗しました。');
  }
});
async function decodeWebA(file) {
  const arrayBuffer = await file.arrayBuffer();
  const audioContext = new AudioContext();
  return await audioContext.decodeAudioData(arrayBuffer);
}
  function convertToMp3(audioBuffer) {
    const numChannels = audioBuffer.numberOfChannels;
    const sampleRate = audioBuffer.sampleRate;
    const samples = [];
    for (let i = 0; i < numChannels; i++) { samples.push(audioBuffer.getChannelData(i)); }
    const mp3Encoder = new lamejs.Mp3Encoder(numChannels, sampleRate, 128);
    const mp3Data = [];
    const chunkSize = 1152;
    let left = samples[0];
    let right = numChannels > 1 ? samples[1] : samples[0];
    for (let i = 0; i < left.length; i += chunkSize) {
      const leftChunk = left.subarray(i, i + chunkSize);
      const rightChunk = numChannels > 1 ? right.subarray(i, i + chunkSize) : leftChunk;
      const mp3buf = mp3Encoder.encodeBuffer(floatTo16BitPCM(leftChunk), floatTo16BitPCM(rightChunk));
      if (mp3buf.length > 0) mp3Data.push(mp3buf);
    }
    const finalMp3 = mp3Encoder.flush();
    if (finalMp3.length > 0) mp3Data.push(finalMp3);
    return new Blob(mp3Data, { type: 'audio/mp3' });
}
function floatTo16BitPCM(input) {
  const output = new Int16Array(input.length);
  for (let i = 0; i < input.length; i++) {
    output[i] = Math.max(-32768, Math.min(32767, input[i] * 32768));
  }
  return output;
}
</script>
</body>
</html>

JavaScriptJavaScript/HTMLサイトマップホーム