From 529b2fbb21c90087f1c47358b6150e5133f1d36d Mon Sep 17 00:00:00 2001
From: voluntas <nakai@shiguredo.jp>
Date: Sat, 11 Jan 2025 18:01:03 +0900
Subject: [PATCH] lineWidth 100

---
 biome.jsonc                |   1 +
 check_stereo/main.ts       | 127 ++++++++++----------------------
 check_stereo_multi/main.ts | 147 +++++++++++++------------------------
 messaging/main.ts          |  44 ++++-------
 package.json               |   2 +-
 recvonly/main.ts           |  12 +--
 replace_track/main.ts      |  41 +++--------
 sendonly/main.ts           |  15 +---
 sendrecv/main.ts           |  15 +---
 simulcast/main.ts          |  83 ++++++---------------
 spotlight_sendrecv/main.ts |  20 ++---
 src/misc.ts                |   5 +-
 tests/sendrecv.test.ts     |  44 +++--------
 13 files changed, 167 insertions(+), 389 deletions(-)

diff --git a/biome.jsonc b/biome.jsonc
index 701180b..3551721 100644
--- a/biome.jsonc
+++ b/biome.jsonc
@@ -28,6 +28,7 @@
   "javascript": {
     "formatter": {
       "enabled": true,
+      "lineWidth": 100,
       "indentStyle": "space"
     }
   }
diff --git a/check_stereo/main.ts b/check_stereo/main.ts
index b771e35..d26807a 100644
--- a/check_stereo/main.ts
+++ b/check_stereo/main.ts
@@ -28,50 +28,38 @@ document.addEventListener("DOMContentLoaded", async () => {
   // デバイスの変更を監視
   navigator.mediaDevices.addEventListener("devicechange", updateDeviceLists);
 
-  document
-    .querySelector("#sendonly-connect")
-    ?.addEventListener("click", async () => {
-      const audioInputSelect = document.querySelector<HTMLSelectElement>(
-        "#sendonly-audio-input",
-      );
-      const selectedAudioDeviceId = audioInputSelect?.value;
-      const stream = await navigator.mediaDevices.getUserMedia({
-        video: false,
-        audio: {
-          deviceId: selectedAudioDeviceId
-            ? { exact: selectedAudioDeviceId }
-            : undefined,
-          echoCancellation: false,
-          noiseSuppression: false,
-          autoGainControl: false,
-          channelCount: 2,
-          sampleRate: 48000,
-          sampleSize: 16,
-        },
-      });
-      await sendonly.connect(stream);
+  document.querySelector("#sendonly-connect")?.addEventListener("click", async () => {
+    const audioInputSelect = document.querySelector<HTMLSelectElement>("#sendonly-audio-input");
+    const selectedAudioDeviceId = audioInputSelect?.value;
+    const stream = await navigator.mediaDevices.getUserMedia({
+      video: false,
+      audio: {
+        deviceId: selectedAudioDeviceId ? { exact: selectedAudioDeviceId } : undefined,
+        echoCancellation: false,
+        noiseSuppression: false,
+        autoGainControl: false,
+        channelCount: 2,
+        sampleRate: 48000,
+        sampleSize: 16,
+      },
     });
+    await sendonly.connect(stream);
+  });
 
-  document
-    .querySelector("#recvonly-connect")
-    ?.addEventListener("click", async () => {
-      await recvonly.connect();
-    });
+  document.querySelector("#recvonly-connect")?.addEventListener("click", async () => {
+    await recvonly.connect();
+  });
 });
 
 // デバイスリストを更新する関数
 async function updateDeviceLists() {
   const devices = await navigator.mediaDevices.enumerateDevices();
 
-  const audioInputSelect = document.querySelector<HTMLSelectElement>(
-    "#sendonly-audio-input",
-  );
+  const audioInputSelect = document.querySelector<HTMLSelectElement>("#sendonly-audio-input");
 
   if (audioInputSelect) {
     audioInputSelect.innerHTML = "";
-    const audioInputDevices = devices.filter(
-      (device) => device.kind === "audioinput",
-    );
+    const audioInputDevices = devices.filter((device) => device.kind === "audioinput");
     for (const device of audioInputDevices) {
       const option = document.createElement("option");
       option.value = device.deviceId;
@@ -138,9 +126,7 @@ class SendonlyClient {
     if (!this.connection.pc) {
       return undefined;
     }
-    const sender = this.connection.pc
-      .getSenders()
-      .find((sender) => sender.track?.kind === "audio");
+    const sender = this.connection.pc.getSenders().find((sender) => sender.track?.kind === "audio");
     if (!sender) {
       return undefined;
     }
@@ -148,8 +134,7 @@ class SendonlyClient {
   }
 
   private initializeCanvas() {
-    this.canvas =
-      document.querySelector<HTMLCanvasElement>("#sendonly-waveform");
+    this.canvas = document.querySelector<HTMLCanvasElement>("#sendonly-waveform");
     if (this.canvas) {
       this.canvasCtx = this.canvas.getContext("2d");
     }
@@ -199,8 +184,7 @@ class SendonlyClient {
       }
 
       // sendonly-stereo 要素に結果を反映
-      const sendonlyStereoElement =
-        document.querySelector<HTMLDivElement>("#sendonly-stereo");
+      const sendonlyStereoElement = document.querySelector<HTMLDivElement>("#sendonly-stereo");
       if (sendonlyStereoElement) {
         sendonlyStereoElement.textContent = result;
       }
@@ -224,11 +208,7 @@ class SendonlyClient {
 
     this.canvasCtx.fillStyle = "rgb(240, 240, 240)";
     this.canvasCtx.fillRect(0, 0, width, height);
-    const drawChannel = (
-      dataArray: Float32Array,
-      color: string,
-      offset: number,
-    ) => {
+    const drawChannel = (dataArray: Float32Array, color: string, offset: number) => {
       if (!this.canvasCtx) return;
 
       this.canvasCtx.lineWidth = 3;
@@ -270,10 +250,7 @@ class SendonlyClient {
     this.canvasCtx.fillText(isMonaural ? "Monaural" : "Stereo", 10, 30);
   }
 
-  private isMonaural(
-    dataArrayL: Float32Array,
-    dataArrayR: Float32Array,
-  ): boolean {
+  private isMonaural(dataArrayL: Float32Array, dataArrayR: Float32Array): boolean {
     const threshold = 0.001;
     for (let i = 0; i < dataArrayL.length; i++) {
       if (Math.abs(dataArrayL[i] - dataArrayR[i]) > threshold) {
@@ -289,9 +266,7 @@ class SendonlyClient {
       event.event_type === "connection.created" &&
       this.connection.connectionId === event.connection_id
     ) {
-      const connectionIdElement = document.querySelector<HTMLDivElement>(
-        "#sendonly-connection-id",
-      );
+      const connectionIdElement = document.querySelector<HTMLDivElement>("#sendonly-connection-id");
       if (connectionIdElement) {
         connectionIdElement.textContent = event.connection_id;
       }
@@ -301,13 +276,10 @@ class SendonlyClient {
   private startChannelCheck() {
     this.channelCheckInterval = window.setInterval(async () => {
       const channels = await this.getChannels();
-      const channelElement =
-        document.querySelector<HTMLDivElement>("#sendonly-channels");
+      const channelElement = document.querySelector<HTMLDivElement>("#sendonly-channels");
       if (channelElement) {
         channelElement.textContent =
-          channels !== undefined
-            ? `getParameters codecs channels: ${channels}`
-            : "undefined";
+          channels !== undefined ? `getParameters codecs channels: ${channels}` : "undefined";
       }
     }, 1000); // 1秒ごとにチェック
   }
@@ -335,11 +307,7 @@ class RecvonlyClient {
     this.secretKey = secretKey;
 
     this.sora = Sora.connection(signalingUrl, this.debug);
-    this.connection = this.sora.recvonly(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.recvonly(this.channelId, undefined, this.options);
     this.connection.on("notify", this.onnotify.bind(this));
     this.connection.on("track", this.ontrack.bind(this));
 
@@ -350,19 +318,15 @@ class RecvonlyClient {
     const jwt = await generateJwt(this.channelId, this.secretKey);
     this.connection.metadata = { access_token: jwt };
 
-    const forceStereoOutputElement =
-      document.querySelector<HTMLInputElement>("#forceStereoOutput");
-    const forceStereoOutput = forceStereoOutputElement
-      ? forceStereoOutputElement.checked
-      : false;
+    const forceStereoOutputElement = document.querySelector<HTMLInputElement>("#forceStereoOutput");
+    const forceStereoOutput = forceStereoOutputElement ? forceStereoOutputElement.checked : false;
     this.connection.options.forceStereoOutput = forceStereoOutput;
 
     await this.connection.connect();
   }
 
   private initializeCanvas() {
-    this.canvas =
-      document.querySelector<HTMLCanvasElement>("#recvonly-waveform");
+    this.canvas = document.querySelector<HTMLCanvasElement>("#recvonly-waveform");
     if (this.canvas) {
       this.canvasCtx = this.canvas.getContext("2d");
     }
@@ -412,8 +376,7 @@ class RecvonlyClient {
       }
 
       // 既存のコード
-      const recvonlyStereoElement =
-        document.querySelector<HTMLDivElement>("#recvonly-stereo");
+      const recvonlyStereoElement = document.querySelector<HTMLDivElement>("#recvonly-stereo");
       if (recvonlyStereoElement) {
         recvonlyStereoElement.textContent = result;
       }
@@ -437,11 +400,7 @@ class RecvonlyClient {
 
     this.canvasCtx.fillStyle = "rgb(240, 240, 240)";
     this.canvasCtx.fillRect(0, 0, width, height);
-    const drawChannel = (
-      dataArray: Float32Array,
-      color: string,
-      offset: number,
-    ) => {
+    const drawChannel = (dataArray: Float32Array, color: string, offset: number) => {
       if (!this.canvasCtx) return;
 
       this.canvasCtx.lineWidth = 3;
@@ -478,10 +437,7 @@ class RecvonlyClient {
     this.canvasCtx.fillText(isMonaural ? "Monaural" : "Stereo", 10, 30);
   }
 
-  private isMonaural(
-    dataArrayL: Float32Array,
-    dataArrayR: Float32Array,
-  ): boolean {
+  private isMonaural(dataArrayL: Float32Array, dataArrayR: Float32Array): boolean {
     const threshold = 0.001;
     for (let i = 0; i < dataArrayL.length; i++) {
       if (Math.abs(dataArrayL[i] - dataArrayR[i]) > threshold) {
@@ -497,9 +453,7 @@ class RecvonlyClient {
       event.event_type === "connection.created" &&
       this.connection.connectionId === event.connection_id
     ) {
-      const connectionIdElement = document.querySelector<HTMLDivElement>(
-        "#recvonly-connection-id",
-      );
+      const connectionIdElement = document.querySelector<HTMLDivElement>("#recvonly-connection-id");
       if (connectionIdElement) {
         connectionIdElement.textContent = event.connection_id;
       }
@@ -513,13 +467,10 @@ class RecvonlyClient {
       this.analyzeAudioStream(new MediaStream([event.track]));
 
       // <audio> 要素に音声ストリームを設定
-      const audioElement =
-        document.querySelector<HTMLAudioElement>("#recvonly-audio");
+      const audioElement = document.querySelector<HTMLAudioElement>("#recvonly-audio");
       if (audioElement) {
         audioElement.srcObject = stream;
-        audioElement
-          .play()
-          .catch((error) => console.error("音声の再生に失敗しました:", error));
+        audioElement.play().catch((error) => console.error("音声の再生に失敗しました:", error));
       }
     }
   }
diff --git a/check_stereo_multi/main.ts b/check_stereo_multi/main.ts
index bf80154..64ff1b9 100644
--- a/check_stereo_multi/main.ts
+++ b/check_stereo_multi/main.ts
@@ -34,59 +34,45 @@ document.addEventListener("DOMContentLoaded", async () => {
   // デバイスの変更を監視
   navigator.mediaDevices.addEventListener("devicechange", updateDeviceLists);
 
-  document
-    .querySelector("#sendonly-connect-1")
-    ?.addEventListener("click", async () => {
-      const audioInputSelect = document.querySelector<HTMLSelectElement>(
-        "#sendonly-audio-input-1",
-      );
-      const selectedAudioDeviceId = audioInputSelect?.value;
-      const stream = await navigator.mediaDevices.getUserMedia({
-        video: false,
-        audio: {
-          deviceId: selectedAudioDeviceId
-            ? { exact: selectedAudioDeviceId }
-            : undefined,
-          echoCancellation: false,
-          noiseSuppression: false,
-          autoGainControl: false,
-          channelCount: 2,
-          sampleRate: 48000,
-          sampleSize: 16,
-        },
-      });
-      await sendonly1.connect(stream);
+  document.querySelector("#sendonly-connect-1")?.addEventListener("click", async () => {
+    const audioInputSelect = document.querySelector<HTMLSelectElement>("#sendonly-audio-input-1");
+    const selectedAudioDeviceId = audioInputSelect?.value;
+    const stream = await navigator.mediaDevices.getUserMedia({
+      video: false,
+      audio: {
+        deviceId: selectedAudioDeviceId ? { exact: selectedAudioDeviceId } : undefined,
+        echoCancellation: false,
+        noiseSuppression: false,
+        autoGainControl: false,
+        channelCount: 2,
+        sampleRate: 48000,
+        sampleSize: 16,
+      },
     });
+    await sendonly1.connect(stream);
+  });
 
-  document
-    .querySelector("#sendonly-connect-2")
-    ?.addEventListener("click", async () => {
-      const audioInputSelect = document.querySelector<HTMLSelectElement>(
-        "#sendonly-audio-input-2",
-      );
-      const selectedAudioDeviceId = audioInputSelect?.value;
-      const stream = await navigator.mediaDevices.getUserMedia({
-        video: false,
-        audio: {
-          deviceId: selectedAudioDeviceId
-            ? { exact: selectedAudioDeviceId }
-            : undefined,
-          echoCancellation: false,
-          noiseSuppression: false,
-          autoGainControl: false,
-          channelCount: 2,
-          sampleRate: 48000,
-          sampleSize: 16,
-        },
-      });
-      await sendonly2.connect(stream);
+  document.querySelector("#sendonly-connect-2")?.addEventListener("click", async () => {
+    const audioInputSelect = document.querySelector<HTMLSelectElement>("#sendonly-audio-input-2");
+    const selectedAudioDeviceId = audioInputSelect?.value;
+    const stream = await navigator.mediaDevices.getUserMedia({
+      video: false,
+      audio: {
+        deviceId: selectedAudioDeviceId ? { exact: selectedAudioDeviceId } : undefined,
+        echoCancellation: false,
+        noiseSuppression: false,
+        autoGainControl: false,
+        channelCount: 2,
+        sampleRate: 48000,
+        sampleSize: 16,
+      },
     });
+    await sendonly2.connect(stream);
+  });
 
-  document
-    .querySelector("#recvonly-connect")
-    ?.addEventListener("click", async () => {
-      await recvonly.connect();
-    });
+  document.querySelector("#recvonly-connect")?.addEventListener("click", async () => {
+    await recvonly.connect();
+  });
 });
 
 // デバイスリストを更新する関数
@@ -100,9 +86,7 @@ async function updateDeviceLists() {
 
     if (audioInputSelect) {
       audioInputSelect.innerHTML = "";
-      const audioInputDevices = devices.filter(
-        (device) => device.kind === "audioinput",
-      );
+      const audioInputDevices = devices.filter((device) => device.kind === "audioinput");
       for (const device of audioInputDevices) {
         const option = document.createElement("option");
         option.value = device.deviceId;
@@ -170,9 +154,7 @@ class SendonlyClient {
     if (!this.connection.pc) {
       return undefined;
     }
-    const sender = this.connection.pc
-      .getSenders()
-      .find((sender) => sender.track?.kind === "audio");
+    const sender = this.connection.pc.getSenders().find((sender) => sender.track?.kind === "audio");
     if (!sender) {
       return undefined;
     }
@@ -258,11 +240,7 @@ class SendonlyClient {
 
     this.canvasCtx.fillStyle = "rgb(240, 240, 240)";
     this.canvasCtx.fillRect(0, 0, width, height);
-    const drawChannel = (
-      dataArray: Float32Array,
-      color: string,
-      offset: number,
-    ) => {
+    const drawChannel = (dataArray: Float32Array, color: string, offset: number) => {
       if (!this.canvasCtx) return;
 
       this.canvasCtx.lineWidth = 3;
@@ -304,10 +282,7 @@ class SendonlyClient {
     this.canvasCtx.fillText(isMonaural ? "Monaural" : "Stereo", 10, 30);
   }
 
-  private isMonaural(
-    dataArrayL: Float32Array,
-    dataArrayR: Float32Array,
-  ): boolean {
+  private isMonaural(dataArrayL: Float32Array, dataArrayR: Float32Array): boolean {
     const threshold = 0.001;
     for (let i = 0; i < dataArrayL.length; i++) {
       if (Math.abs(dataArrayL[i] - dataArrayR[i]) > threshold) {
@@ -340,9 +315,7 @@ class SendonlyClient {
       );
       if (channelElement) {
         channelElement.textContent =
-          channels !== undefined
-            ? `getParameters codecs channels: ${channels}`
-            : "undefined";
+          channels !== undefined ? `getParameters codecs channels: ${channels}` : "undefined";
       }
     }, 1000); // 1秒ごとにチェック
   }
@@ -369,11 +342,7 @@ class RecvonlyClient {
     this.options = {};
 
     this.sora = Sora.connection(signalingUrl, this.debug);
-    this.connection = this.sora.recvonly(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.recvonly(this.channelId, undefined, this.options);
     this.connection.on("notify", this.onnotify.bind(this));
     this.connection.on("track", this.ontrack.bind(this));
   }
@@ -382,11 +351,8 @@ class RecvonlyClient {
     const jwt = await generateJwt(this.channelId, this.secretKey);
     this.connection.metadata = { access_token: jwt };
 
-    const forceStereoOutputElement =
-      document.querySelector<HTMLInputElement>("#forceStereoOutput");
-    const forceStereoOutput = forceStereoOutputElement
-      ? forceStereoOutputElement.checked
-      : false;
+    const forceStereoOutputElement = document.querySelector<HTMLInputElement>("#forceStereoOutput");
+    const forceStereoOutput = forceStereoOutputElement ? forceStereoOutputElement.checked : false;
     this.connection.options.forceStereoOutput = forceStereoOutput;
 
     await this.connection.connect();
@@ -446,8 +412,7 @@ class RecvonlyClient {
       }
 
       // 既存のコード
-      const recvonlyStereoElement =
-        document.querySelector<HTMLDivElement>("#recvonly-stereo");
+      const recvonlyStereoElement = document.querySelector<HTMLDivElement>("#recvonly-stereo");
       if (recvonlyStereoElement) {
         recvonlyStereoElement.textContent = result;
       }
@@ -462,11 +427,7 @@ class RecvonlyClient {
     }
   }
 
-  private drawWaveforms(
-    dataArrayL: Float32Array,
-    dataArrayR: Float32Array,
-    streamId: string,
-  ) {
+  private drawWaveforms(dataArrayL: Float32Array, dataArrayR: Float32Array, streamId: string) {
     const canvasCtx = this.canvasCtxs.get(streamId);
     const canvas = this.canvases.get(streamId);
     if (!canvasCtx || !canvas) return;
@@ -477,11 +438,7 @@ class RecvonlyClient {
 
     canvasCtx.fillStyle = "rgb(240, 240, 240)";
     canvasCtx.fillRect(0, 0, width, height);
-    const drawChannel = (
-      dataArray: Float32Array,
-      color: string,
-      offset: number,
-    ) => {
+    const drawChannel = (dataArray: Float32Array, color: string, offset: number) => {
       if (!canvasCtx) return;
 
       canvasCtx.lineWidth = 3;
@@ -518,10 +475,7 @@ class RecvonlyClient {
     canvasCtx.fillText(isMonaural ? "Monaural" : "Stereo", 10, 30);
   }
 
-  private isMonaural(
-    dataArrayL: Float32Array,
-    dataArrayR: Float32Array,
-  ): boolean {
+  private isMonaural(dataArrayL: Float32Array, dataArrayR: Float32Array): boolean {
     const threshold = 0.001;
     for (let i = 0; i < dataArrayL.length; i++) {
       if (Math.abs(dataArrayL[i] - dataArrayR[i]) > threshold) {
@@ -537,9 +491,7 @@ class RecvonlyClient {
       event.event_type === "connection.created" &&
       this.connection.connectionId === event.connection_id
     ) {
-      const connectionIdElement = document.querySelector<HTMLDivElement>(
-        "#recvonly-connection-id",
-      );
+      const connectionIdElement = document.querySelector<HTMLDivElement>("#recvonly-connection-id");
       if (connectionIdElement) {
         connectionIdElement.textContent = event.connection_id;
       }
@@ -552,8 +504,7 @@ class RecvonlyClient {
     if (event.track.kind === "audio") {
       this.analyzeAudioStream(new MediaStream([event.track]), stream.id);
       const remoteAudioId = `remoteaudio-${stream.id}`;
-      const remoteAudios =
-        document.querySelector<HTMLDivElement>("#remote-audios");
+      const remoteAudios = document.querySelector<HTMLDivElement>("#remote-audios");
       if (remoteAudios && !remoteAudios.querySelector(`#${remoteAudioId}`)) {
         const remoteAudioDiv = document.createElement("div");
         remoteAudioDiv.id = `remote-audio-${remoteAudioId}`;
diff --git a/messaging/main.ts b/messaging/main.ts
index 7f0035e..d1b5e06 100644
--- a/messaging/main.ts
+++ b/messaging/main.ts
@@ -21,13 +21,9 @@ document.addEventListener("DOMContentLoaded", async () => {
   const client = new SoraClient(signalingUrl, channelId, secretKey);
 
   document.querySelector("#connect")?.addEventListener("click", async () => {
-    const checkCompress = document.getElementById(
-      "check-compress",
-    ) as HTMLInputElement;
+    const checkCompress = document.getElementById("check-compress") as HTMLInputElement;
     const compress = checkCompress.checked;
-    const checkHeader = document.getElementById(
-      "check-header",
-    ) as HTMLInputElement;
+    const checkHeader = document.getElementById("check-header") as HTMLInputElement;
     const header = checkHeader.checked;
 
     await client.connect(compress, header);
@@ -37,16 +33,12 @@ document.addEventListener("DOMContentLoaded", async () => {
     await client.disconnect();
   });
 
-  document
-    .querySelector("#send-message")
-    ?.addEventListener("click", async () => {
-      const value = document.querySelector<HTMLInputElement>(
-        "input[name=message]",
-      )?.value;
-      if (value !== undefined && value !== "") {
-        await client.sendMessage(value);
-      }
-    });
+  document.querySelector("#send-message")?.addEventListener("click", async () => {
+    const value = document.querySelector<HTMLInputElement>("input[name=message]")?.value;
+    if (value !== undefined && value !== "") {
+      await client.sendMessage(value);
+    }
+  });
 
   document.querySelector("#get-stats")?.addEventListener("click", async () => {
     const statsReport = await client.getStats();
@@ -54,14 +46,9 @@ document.addEventListener("DOMContentLoaded", async () => {
     for (const report of statsReport.values()) {
       statsReportJson.push(report);
     }
-    const statsReportJsonElement =
-      document.querySelector<HTMLPreElement>("#stats-report-json");
+    const statsReportJsonElement = document.querySelector<HTMLPreElement>("#stats-report-json");
     if (statsReportJsonElement) {
-      statsReportJsonElement.textContent = JSON.stringify(
-        statsReportJson,
-        null,
-        2,
-      );
+      statsReportJsonElement.textContent = JSON.stringify(statsReportJson, null, 2);
     }
   });
 });
@@ -123,8 +110,7 @@ class SoraClient {
   async disconnect() {
     await this.connection.disconnect();
 
-    const receivedMessagesElement =
-      document.querySelector("#received-messages");
+    const receivedMessagesElement = document.querySelector("#received-messages");
     if (receivedMessagesElement) {
       receivedMessagesElement.innerHTML = "";
     }
@@ -139,10 +125,7 @@ class SoraClient {
 
   async sendMessage(message: string) {
     if (message !== "") {
-      await this.connection.sendMessage(
-        "#example",
-        new TextEncoder().encode(message),
-      );
+      await this.connection.sendMessage("#example", new TextEncoder().encode(message));
     }
   }
 
@@ -165,8 +148,7 @@ class SoraClient {
       }
 
       // 送信ボタンを有効にする
-      const sendMessageButton =
-        document.querySelector<HTMLButtonElement>("#send-message");
+      const sendMessageButton = document.querySelector<HTMLButtonElement>("#send-message");
       if (sendMessageButton) {
         sendMessageButton.disabled = false;
       }
diff --git a/package.json b/package.json
index a7dacc0..b0820c3 100644
--- a/package.json
+++ b/package.json
@@ -36,4 +36,4 @@
   "engines": {
     "node": ">=18"
   }
-}
\ No newline at end of file
+}
diff --git a/recvonly/main.ts b/recvonly/main.ts
index d3a2ef4..898eb5e 100644
--- a/recvonly/main.ts
+++ b/recvonly/main.ts
@@ -34,14 +34,9 @@ document.addEventListener("DOMContentLoaded", () => {
     for (const report of statsReport.values()) {
       statsReportJson.push(report);
     }
-    const statsReportJsonElement =
-      document.querySelector<HTMLPreElement>("#stats-report-json");
+    const statsReportJsonElement = document.querySelector<HTMLPreElement>("#stats-report-json");
     if (statsReportJsonElement) {
-      statsReportJsonElement.textContent = JSON.stringify(
-        statsReportJson,
-        null,
-        2,
-      );
+      statsReportJsonElement.textContent = JSON.stringify(statsReportJson, null, 2);
     }
   });
 });
@@ -120,8 +115,7 @@ class SoraClient {
     // Sora の場合、event.streams には MediaStream が 1 つだけ含まれる
     const stream = event.streams[0];
     const remoteVideoId = `remote-video-${stream.id}`;
-    const remoteVideos =
-      document.querySelector<HTMLDivElement>("#remote-videos");
+    const remoteVideos = document.querySelector<HTMLDivElement>("#remote-videos");
     if (remoteVideos && !remoteVideos.querySelector(`#${remoteVideoId}`)) {
       const remoteVideo = document.createElement("video");
       remoteVideo.id = remoteVideoId;
diff --git a/replace_track/main.ts b/replace_track/main.ts
index 515047b..6bd1493 100644
--- a/replace_track/main.ts
+++ b/replace_track/main.ts
@@ -24,16 +24,14 @@ document.addEventListener("DOMContentLoaded", async () => {
     await client.connect();
   });
 
-  document
-    .querySelector("#replace-stream")
-    ?.addEventListener("click", async () => {
-      // audio: true, video: true なので要注意
-      const stream = await navigator.mediaDevices.getUserMedia({
-        audio: true,
-        video: true,
-      });
-      await client.replaceStream(stream);
+  document.querySelector("#replace-stream")?.addEventListener("click", async () => {
+    // audio: true, video: true なので要注意
+    const stream = await navigator.mediaDevices.getUserMedia({
+      audio: true,
+      video: true,
     });
+    await client.replaceStream(stream);
+  });
 
   document.querySelector("#disconnect")?.addEventListener("click", async () => {
     await client.disconnect();
@@ -45,14 +43,9 @@ document.addEventListener("DOMContentLoaded", async () => {
     for (const report of statsReport.values()) {
       statsReportJson.push(report);
     }
-    const statsReportJsonElement =
-      document.querySelector<HTMLPreElement>("#stats-report-json");
+    const statsReportJsonElement = document.querySelector<HTMLPreElement>("#stats-report-json");
     if (statsReportJsonElement) {
-      statsReportJsonElement.textContent = JSON.stringify(
-        statsReportJson,
-        null,
-        2,
-      );
+      statsReportJsonElement.textContent = JSON.stringify(statsReportJson, null, 2);
     }
   });
 });
@@ -83,11 +76,7 @@ class SoraClient {
     this.stream = new MediaStream();
 
     this.sora = Sora.connection(signalingUrl, this.debug);
-    this.connection = this.sora.sendrecv(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.sendrecv(this.channelId, undefined, this.options);
     this.connection.on("notify", this.onnotify.bind(this));
     this.connection.on("track", this.ontrack.bind(this));
     this.connection.on("removetrack", this.onremovetrack.bind(this));
@@ -110,16 +99,10 @@ class SoraClient {
 
   async replaceStream(stream: MediaStream) {
     if (stream.getAudioTracks().length > 0) {
-      await this.connection.replaceAudioTrack(
-        this.stream,
-        stream.getAudioTracks()[0],
-      );
+      await this.connection.replaceAudioTrack(this.stream, stream.getAudioTracks()[0]);
     }
     if (stream.getVideoTracks().length > 0) {
-      await this.connection.replaceVideoTrack(
-        this.stream,
-        stream.getVideoTracks()[0],
-      );
+      await this.connection.replaceVideoTrack(this.stream, stream.getVideoTracks()[0]);
     }
     this.stream = stream;
   }
diff --git a/sendonly/main.ts b/sendonly/main.ts
index c6c74dc..81ed3b8 100644
--- a/sendonly/main.ts
+++ b/sendonly/main.ts
@@ -38,14 +38,9 @@ document.addEventListener("DOMContentLoaded", async () => {
     for (const report of statsReport.values()) {
       statsReportJson.push(report);
     }
-    const statsReportJsonElement =
-      document.querySelector<HTMLPreElement>("#stats-report-json");
+    const statsReportJsonElement = document.querySelector<HTMLPreElement>("#stats-report-json");
     if (statsReportJsonElement) {
-      statsReportJsonElement.textContent = JSON.stringify(
-        statsReportJson,
-        null,
-        2,
-      );
+      statsReportJsonElement.textContent = JSON.stringify(statsReportJson, null, 2);
     }
   });
 });
@@ -86,8 +81,7 @@ class SoraClient {
 
     await this.connection.connect(stream);
 
-    const videoElement =
-      document.querySelector<HTMLVideoElement>("#local-video");
+    const videoElement = document.querySelector<HTMLVideoElement>("#local-video");
     if (videoElement) {
       videoElement.srcObject = stream;
     }
@@ -96,8 +90,7 @@ class SoraClient {
   async disconnect(): Promise<void> {
     await this.connection.disconnect();
 
-    const videoElement =
-      document.querySelector<HTMLVideoElement>("#local-video");
+    const videoElement = document.querySelector<HTMLVideoElement>("#local-video");
     if (videoElement) {
       videoElement.srcObject = null;
     }
diff --git a/sendrecv/main.ts b/sendrecv/main.ts
index 70148b9..b4b4771 100644
--- a/sendrecv/main.ts
+++ b/sendrecv/main.ts
@@ -37,14 +37,9 @@ document.addEventListener("DOMContentLoaded", async () => {
     for (const report of statsReport.values()) {
       statsReportJson.push(report);
     }
-    const statsReportJsonElement =
-      document.querySelector<HTMLPreElement>("#stats-report-json");
+    const statsReportJsonElement = document.querySelector<HTMLPreElement>("#stats-report-json");
     if (statsReportJsonElement) {
-      statsReportJsonElement.textContent = JSON.stringify(
-        statsReportJson,
-        null,
-        2,
-      );
+      statsReportJsonElement.textContent = JSON.stringify(statsReportJson, null, 2);
     }
   });
 });
@@ -66,11 +61,7 @@ class SoraClient {
     this.options = {};
 
     this.sora = Sora.connection(signalingUrl, this.debug);
-    this.connection = this.sora.sendrecv(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.sendrecv(this.channelId, undefined, this.options);
     this.connection.on("notify", this.onnotify.bind(this));
     this.connection.on("track", this.ontrack.bind(this));
     this.connection.on("removetrack", this.onremovetrack.bind(this));
diff --git a/simulcast/main.ts b/simulcast/main.ts
index 3836847..c5521d6 100644
--- a/simulcast/main.ts
+++ b/simulcast/main.ts
@@ -19,45 +19,25 @@ document.addEventListener("DOMContentLoaded", () => {
   const channelName = urlParams.get("channelName") || "";
   const channelId = `${channelIdPrefix}:${channelName}:${channelIdSuffix}`;
 
-  const sendonly = new SimulcastSendonlySoraClient(
-    signalingUrl,
-    channelId,
-    secretKey,
-    {
-      audio: false,
-      video: true,
-      videoCodecType: "VP8",
-      videoBitRate: 2500,
-      simulcast: true,
-    },
-  );
-  const recvonlyR0 = new SimulcastRecvonlySoraClient(
-    signalingUrl,
-    channelId,
-    secretKey,
-    {
-      simulcast: true,
-      simulcastRid: "r0",
-    },
-  );
-  const recvonlyR1 = new SimulcastRecvonlySoraClient(
-    signalingUrl,
-    channelId,
-    secretKey,
-    {
-      simulcast: true,
-      simulcastRid: "r1",
-    },
-  );
-  const recvonlyR2 = new SimulcastRecvonlySoraClient(
-    signalingUrl,
-    channelId,
-    secretKey,
-    {
-      simulcast: true,
-      simulcastRid: "r2",
-    },
-  );
+  const sendonly = new SimulcastSendonlySoraClient(signalingUrl, channelId, secretKey, {
+    audio: false,
+    video: true,
+    videoCodecType: "VP8",
+    videoBitRate: 2500,
+    simulcast: true,
+  });
+  const recvonlyR0 = new SimulcastRecvonlySoraClient(signalingUrl, channelId, secretKey, {
+    simulcast: true,
+    simulcastRid: "r0",
+  });
+  const recvonlyR1 = new SimulcastRecvonlySoraClient(signalingUrl, channelId, secretKey, {
+    simulcast: true,
+    simulcastRid: "r1",
+  });
+  const recvonlyR2 = new SimulcastRecvonlySoraClient(signalingUrl, channelId, secretKey, {
+    simulcast: true,
+    simulcastRid: "r2",
+  });
 
   document.querySelector("#connect")?.addEventListener("click", async () => {
     // sendonly
@@ -92,14 +72,9 @@ document.addEventListener("DOMContentLoaded", () => {
     for (const report of statsReport.values()) {
       statsReportJson.push(report);
     }
-    const statsReportJsonElement =
-      document.querySelector<HTMLPreElement>("#stats-report-json");
+    const statsReportJsonElement = document.querySelector<HTMLPreElement>("#stats-report-json");
     if (statsReportJsonElement) {
-      statsReportJsonElement.textContent = JSON.stringify(
-        statsReportJson,
-        null,
-        2,
-      );
+      statsReportJsonElement.textContent = JSON.stringify(statsReportJson, null, 2);
     }
   });
 });
@@ -126,11 +101,7 @@ class SimulcastSendonlySoraClient {
     this.options = options;
 
     this.sora = Sora.connection(signaling_url, this.debug);
-    this.connection = this.sora.sendonly(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.sendonly(this.channelId, undefined, this.options);
     this.connection.on("notify", this.onnotify.bind(this));
   }
 
@@ -170,9 +141,7 @@ class SimulcastSendonlySoraClient {
       event.event_type === "connection.created" &&
       event.connection_id === this.connection.connectionId
     ) {
-      const localVideoConnectionId = document.querySelector(
-        "#local-video-connection-id",
-      );
+      const localVideoConnectionId = document.querySelector("#local-video-connection-id");
       if (localVideoConnectionId) {
         localVideoConnectionId.textContent = `${event.connection_id}`;
       }
@@ -202,11 +171,7 @@ class SimulcastRecvonlySoraClient {
     this.options = options;
 
     this.sora = Sora.connection(signaling_url, this.debug);
-    this.connection = this.sora.recvonly(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.recvonly(this.channelId, undefined, this.options);
     this.connection.on("notify", this.onnotify.bind(this));
     this.connection.on("track", this.ontrack.bind(this));
     this.connection.on("removetrack", this.onremovetrack.bind(this));
diff --git a/spotlight_sendrecv/main.ts b/spotlight_sendrecv/main.ts
index 5895c8b..47ea06b 100644
--- a/spotlight_sendrecv/main.ts
+++ b/spotlight_sendrecv/main.ts
@@ -55,11 +55,7 @@ class SoraClient {
       spotlightNumber: 1,
     };
 
-    this.connection = this.sora.sendrecv(
-      this.channelId,
-      undefined,
-      this.options,
-    );
+    this.connection = this.sora.sendrecv(this.channelId, undefined, this.options);
 
     this.connection.on("notify", this.onnotify.bind(this));
     this.connection.on("track", this.ontrack.bind(this));
@@ -102,8 +98,7 @@ class SoraClient {
       event.event_type === "connection.created" &&
       this.connection.connectionId === event.connection_id
     ) {
-      const connectionIdElement =
-        document.querySelector<HTMLDivElement>("#connection-id");
+      const connectionIdElement = document.querySelector<HTMLDivElement>("#connection-id");
       if (connectionIdElement) {
         connectionIdElement.textContent = event.connection_id;
       }
@@ -113,8 +108,7 @@ class SoraClient {
   private ontrack(event: RTCTrackEvent): void {
     const stream = event.streams[0];
     const remoteVideoId = `remote-video-${stream.id}`;
-    const remoteVideos =
-      document.querySelector<HTMLDivElement>("#remote-videos");
+    const remoteVideos = document.querySelector<HTMLDivElement>("#remote-videos");
     if (remoteVideos && !remoteVideos.querySelector(`#${remoteVideoId}`)) {
       const remoteVideo = document.createElement("video");
       remoteVideo.id = remoteVideoId;
@@ -131,13 +125,9 @@ class SoraClient {
 
   private onremovetrack(event: MediaStreamTrackEvent): void {
     const target = event.target as MediaStream;
-    const remoteVideo = document.querySelector<HTMLVideoElement>(
-      `#remote-video-${target.id}`,
-    );
+    const remoteVideo = document.querySelector<HTMLVideoElement>(`#remote-video-${target.id}`);
     if (remoteVideo) {
-      document
-        .querySelector<HTMLDivElement>("#remote-videos")
-        ?.removeChild(remoteVideo);
+      document.querySelector<HTMLDivElement>("#remote-videos")?.removeChild(remoteVideo);
     }
   }
 }
diff --git a/src/misc.ts b/src/misc.ts
index 07b9d49..a14cb95 100644
--- a/src/misc.ts
+++ b/src/misc.ts
@@ -1,9 +1,6 @@
 import * as jose from "jose";
 
-export const generateJwt = async (
-  channelId: string,
-  secretKey: string,
-): Promise<string> => {
+export const generateJwt = async (channelId: string, secretKey: string): Promise<string> => {
   const header = { alg: "HS256", typ: "JWT" };
   return (
     new jose.SignJWT({
diff --git a/tests/sendrecv.test.ts b/tests/sendrecv.test.ts
index e0b5760..a814870 100644
--- a/tests/sendrecv.test.ts
+++ b/tests/sendrecv.test.ts
@@ -6,12 +6,8 @@ test("sendrecv x2", async ({ browser }) => {
 
   // テストごとに異なる channelName を生成
   const channelName = crypto.randomUUID();
-  await sendrecv1.goto(
-    `http://localhost:9000/sendrecv/?channelName=${channelName}`,
-  );
-  await sendrecv2.goto(
-    `http://localhost:9000/sendrecv/?channelName=${channelName}`,
-  );
+  await sendrecv1.goto(`http://localhost:9000/sendrecv/?channelName=${channelName}`);
+  await sendrecv2.goto(`http://localhost:9000/sendrecv/?channelName=${channelName}`);
 
   await sendrecv1.click("#connect");
   await sendrecv2.click("#connect");
@@ -20,20 +16,14 @@ test("sendrecv x2", async ({ browser }) => {
   await sendrecv1.waitForSelector("#connection-id:not(:empty)");
 
   // "connection-id" 要素の内容を取得
-  const sendrecv1ConnectionId = await sendrecv1.$eval(
-    "#connection-id",
-    (el) => el.textContent,
-  );
+  const sendrecv1ConnectionId = await sendrecv1.$eval("#connection-id", (el) => el.textContent);
   console.log(`sendrecv1 connectionId=${sendrecv1ConnectionId}`);
 
   // "connection-id" 要素が存在し、その内容が空でないことを確認するまで待つ
   await sendrecv2.waitForSelector("#connection-id:not(:empty)");
 
   // "connection-id" 要素の内容を取得
-  const sendrecv2ConnectionId = await sendrecv2.$eval(
-    "#connection-id",
-    (el) => el.textContent,
-  );
+  const sendrecv2ConnectionId = await sendrecv2.$eval("#connection-id", (el) => el.textContent);
   console.log(`sendrecv2 connectionId=${sendrecv2ConnectionId}`);
 
   // レース対策
@@ -48,15 +38,10 @@ test("sendrecv x2", async ({ browser }) => {
   // 統計情報が表示されるまで待機
   await sendrecv1.waitForSelector("#stats-report-json");
   // テキストコンテンツから統計情報を取得
-  const sendrecv1StatsReportJson: Record<string, unknown>[] =
-    await sendrecv1.evaluate(() => {
-      const statsReportElement = document.querySelector(
-        "#stats-report-json",
-      ) as HTMLPreElement;
-      return statsReportElement
-        ? JSON.parse(statsReportElement.textContent || "[]")
-        : [];
-    });
+  const sendrecv1StatsReportJson: Record<string, unknown>[] = await sendrecv1.evaluate(() => {
+    const statsReportElement = document.querySelector("#stats-report-json") as HTMLPreElement;
+    return statsReportElement ? JSON.parse(statsReportElement.textContent || "[]") : [];
+  });
 
   const sendrecv1VideoOutboundRtpStats = sendrecv1StatsReportJson.find(
     (stats) => stats.type === "outbound-rtp" && stats.kind === "video",
@@ -80,15 +65,10 @@ test("sendrecv x2", async ({ browser }) => {
   // 統計情報が表示されるまで待機
   await sendrecv2.waitForSelector("#stats-report-json");
   // デキストコンテンツから統計情報を取得
-  const sendrecv2StatsReportJson: Record<string, unknown>[] =
-    await sendrecv2.evaluate(() => {
-      const statsReportElement = document.querySelector(
-        "#stats-report-json",
-      ) as HTMLPreElement;
-      return statsReportElement
-        ? JSON.parse(statsReportElement.textContent || "[]")
-        : [];
-    });
+  const sendrecv2StatsReportJson: Record<string, unknown>[] = await sendrecv2.evaluate(() => {
+    const statsReportElement = document.querySelector("#stats-report-json") as HTMLPreElement;
+    return statsReportElement ? JSON.parse(statsReportElement.textContent || "[]") : [];
+  });
 
   const sendrecv2VideoOutboundRtpStats = sendrecv2StatsReportJson.find(
     (stats) => stats.type === "outbound-rtp" && stats.kind === "video",