画面録画をするページ

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>画面+音声 録画テスト</title>
</head>
<body>

<button id="start">録画開始</button>
<button id="stop" disabled>停止</button>
<pre id="log"></pre>

<script>
let recorder;
let chunks = [];
const log = (s) => document.getElementById("log").textContent += s + "\n";

document.getElementById("start").onclick = async () => {
  try {
    log("画面取得開始...");

    const displayStream = await navigator.mediaDevices.getDisplayMedia({
      video: true,
      audio: true
    });

    log("AudioContext 準備...");

    const audioCtx = new AudioContext();
    const destination = audioCtx.createMediaStreamDestination();

    // 画面音声
    if (displayStream.getAudioTracks().length > 0) {
      audioCtx.createMediaStreamSource(displayStream).connect(destination);
      log("タブ音声接続 OK");
    } else {
      log("タブ音声なし");
    }

    // マイク(失敗しても続行)
    try {
      log("マイク取得開始...");
      const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
      audioCtx.createMediaStreamSource(micStream).connect(destination);
      log("マイク接続 OK");
    } catch (e) {
      log("マイク取得失敗(無視して続行): " + e.message);
    }

    const mixedStream = new MediaStream([
      ...displayStream.getVideoTracks(),
      ...destination.stream.getAudioTracks()
    ]);

    log("MediaRecorder 作成...");

    recorder = new MediaRecorder(mixedStream);

    recorder.onstart = () => log("● 録画開始!");
    recorder.ondataavailable = e => {
      if (e.data.size > 0) chunks.push(e.data);
    };
    recorder.onstop = () => {
      log("■ 録画停止");
      const blob = new Blob(chunks, { type: "video/webm" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "record.webm";
      a.click();
      chunks = [];
    };

    recorder.start();
    log("recorder.start() 実行");

    document.getElementById("start").disabled = true;
    document.getElementById("stop").disabled = false;

  } catch (e) {
    log("致命的エラー: " + e.message);
    console.error(e);
  }
};

document.getElementById("stop").onclick = () => {
  recorder.stop();
  document.getElementById("start").disabled = false;
  document.getElementById("stop").disabled = true;
};
</script>

</body>
</html>