async waitForBlobResponse() {
    return new Promise((resolve) => {
      let timeout = null;
      const handleMessage = (event) => {
        if (event.data.type === "error") {
          this.worker.removeEventListener("message", handleMessage);
          timeout && clearTimeout(timeout);
          return resolve({ blobURL: null, error: event.data.message });
        }

        if (event.data.type !== "result") {
          console.log("PiperTTSWorker debug event:", event.data);
          return;
        }
        resolve({
          blobURL: URL.createObjectURL(event.data.audio),
          error: null,
        });
        this.worker.removeEventListener("message", handleMessage);
        timeout && clearTimeout(timeout);
      };

      timeout = setTimeout(() => {
        resolve({ blobURL: null, error: "PiperTTSWorker Worker timed out." });
      }, 30_000);
      this.worker.addEventListener("message", handleMessage);
    });
  }
Runs prediction via webworker so we can get an audio blob back.
@returns {Promise<{blobURL: string|null, error: string|null}>} objectURL blob: type.