Skip to content

Conexión con la interfaz de usuario

Comience con el flujo de navegador más sencillo posible y, a continuación, adáptelo a su framework de interfaz de usuario.

Ejemplo mínimo

Este ejemplo inicia el reconocimiento mediante un único botón y registra el nombre de la campaña reconocida.

html
<button id="start-button" type="button">Start Recognition</button>

<script type="module">
  import { AudioRecognizer } from "@sorisdk/web-audio";

  const startButton = document.querySelector("#start-button");

  const recognizer = new AudioRecognizer({
    appId: "YOUR_APP_ID",
    ephemeralKey: async () => {
      const response = await fetch("/api/ephemeral-key", {
        method: "POST"
      });

      if (!response.ok) {
        throw new Error(`Ephemeral key request failed: HTTP ${response.status}`);
      }

      const { ephemeral_key } = await response.json();
      return ephemeral_key;
    }
  });

  recognizer.on("campaign", (event) => {
    console.log(event.campaign.name);
  });

  startButton?.addEventListener("click", async () => {
    await recognizer.start();
  });
</script>

Este ejemplo presupone que ya dispone de un endpoint de claves efímeras. Consulte Clave efímera para conocer la configuración estándar.

Ejemplos avanzados

Los siguientes ejemplos muestran las campañas reconocidas en la interfaz de usuario. Si utiliza React, Vue u otro framework basado en Vite, configure primero el cargador Wasm en Configuración.

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SORI Web SDK</title>
    <style>
      #campaign-list {
        padding: 0;
        list-style: none;
      }

      #campaign-list li + li {
        margin-top: 8px;
      }
    </style>
  </head>
  <body>
    <main>
      <button id="start-button" type="button">Start Recognition</button>
      <ul id="campaign-list"></ul>
    </main>

    <script type="module">
      import { AudioRecognizer } from "@sorisdk/web-audio";

      const startButton = document.querySelector("#start-button");
      const campaignList = document.querySelector("#campaign-list");

      const recognizer = new AudioRecognizer({
        appId: "YOUR_APP_ID",
        ephemeralKey: async () => {
          const response = await fetch("/api/ephemeral-key", {
            method: "POST"
          });

          if (!response.ok) {
            throw new Error(`Ephemeral key request failed: HTTP ${response.status}`);
          }

          const { ephemeral_key } = await response.json();
          return ephemeral_key;
        }
      });

      recognizer.on("campaign", (event) => {
        console.log(event.campaign.name);
        if (campaignList) {
          const item = document.createElement("li");
          const link = document.createElement("a");

          link.href = String(event.campaign.action_url);
          link.textContent = String(event.campaign.title);
          link.target = "_blank";
          link.rel = "noreferrer";

          item.append(link);
          campaignList.prepend(item);
        }
      });

      startButton?.addEventListener("click", async () => {
        await recognizer.start();
      });

      globalThis.addEventListener("beforeunload", () => {
        void recognizer.destroy();
      });
    </script>
  </body>
</html>
tsx
import { useEffect, useRef, useState } from "react";
import { AudioRecognizer } from "@sorisdk/web-audio";

type CampaignCard = {
  title: string;
  imageUrl: string;
  actionUrl: string;
};

export default function App() {
  const recognizerRef = useRef<AudioRecognizer | null>(null);
  const [campaigns, setCampaigns] = useState<CampaignCard[]>([]);

  useEffect(() => {
    const recognizer = new AudioRecognizer({
      appId: "YOUR_APP_ID",
      ephemeralKey: async () => {
        const response = await fetch("/api/ephemeral-key", {
          method: "POST"
        });

        if (!response.ok) {
          throw new Error(`Ephemeral key request failed: HTTP ${response.status}`);
        }

        const { ephemeral_key } = await response.json();
        return ephemeral_key;
      }
    });

    recognizer.on("campaign", (event) => {
      console.log(event.campaign.name);
      setCampaigns((current) => [
        {
          title: String(event.campaign.title),
          imageUrl: String(event.campaign.image_url),
          actionUrl: String(event.campaign.action_url)
        },
        ...current
      ]);
    });

    recognizerRef.current = recognizer;

    return () => {
      void recognizer.destroy();
      recognizerRef.current = null;
    };
  }, []);

  return (
    <main>
      <button
        type="button"
        onClick={() => {
          void recognizerRef.current?.start();
        }}
      >
        Start Recognition
      </button>
      <div>
        {campaigns.map((campaign, index) => (
          <a
            key={`${campaign.title}-${index}`}
            href={campaign.actionUrl}
            target="_blank"
            rel="noreferrer"
          >
            <img src={campaign.imageUrl} alt={campaign.title} />
            <strong>{campaign.title}</strong>
          </a>
        ))}
      </div>
    </main>
  );
}
vue
<script setup lang="ts">
import { onBeforeUnmount } from "vue";
import { ref } from "vue";
import { AudioRecognizer } from "@sorisdk/web-audio";

const campaigns = ref<
  Array<{ title: string; imageUrl: string; actionUrl: string }>
>([]);

const recognizer = new AudioRecognizer({
  appId: "YOUR_APP_ID",
  ephemeralKey: async () => {
    const response = await fetch("/api/ephemeral-key", {
      method: "POST"
    });

    if (!response.ok) {
      throw new Error(`Ephemeral key request failed: HTTP ${response.status}`);
    }

    const { ephemeral_key } = await response.json();
    return ephemeral_key;
  }
});

recognizer.on("campaign", (event) => {
  console.log(event.campaign.name);
  campaigns.value.unshift({
    title: String(event.campaign.title),
    imageUrl: String(event.campaign.image_url),
    actionUrl: String(event.campaign.action_url)
  });
});

async function startRecognition() {
  await recognizer.start();
}

onBeforeUnmount(() => {
  void recognizer.destroy();
});
</script>

<template>
  <main>
    <button type="button" @click="startRecognition">Start Recognition</button>
    <div class="campaign-grid">
      <a
        v-for="campaign in campaigns"
        :key="`${campaign.actionUrl}-${campaign.title}`"
        :href="campaign.actionUrl"
        target="_blank"
        rel="noreferrer"
        class="campaign-card"
      >
        <img :src="campaign.imageUrl" :alt="campaign.title" />
        <strong>{{ campaign.title }}</strong>
      </a>
    </div>
  </main>
</template>

<style scoped>
.campaign-grid {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}

.campaign-card {
  display: grid;
  gap: 8px;
  color: inherit;
  text-decoration: none;
}
</style>
svelte
<script lang="ts">
  import { onMount } from "svelte";
  import { AudioRecognizer } from "@sorisdk/web-audio";

  let campaigns: Array<{ title: string; imageUrl: string; actionUrl: string }> = [];
  let recognizer: AudioRecognizer;

  onMount(() => {
    recognizer = new AudioRecognizer({
      appId: "YOUR_APP_ID",
      ephemeralKey: async () => {
        const response = await fetch("/api/ephemeral-key", {
          method: "POST"
        });

        if (!response.ok) {
          throw new Error(`Ephemeral key request failed: HTTP ${response.status}`);
        }

        const { ephemeral_key } = await response.json();
        return ephemeral_key;
      }
    });

    recognizer.on("campaign", (event) => {
      console.log(event.campaign.name);
      campaigns = [
        {
          title: String(event.campaign.title),
          imageUrl: String(event.campaign.image_url),
          actionUrl: String(event.campaign.action_url)
        },
        ...campaigns
      ];
    });

    return () => {
      void recognizer.destroy();
    };
  });

  async function startRecognition() {
    await recognizer.start();
  }
</script>

<main>
  <button type="button" on:click={startRecognition}>Start Recognition</button>
  <div class="campaign-grid">
    {#each campaigns as campaign}
      <a
        href={campaign.actionUrl}
        target="_blank"
        rel="noreferrer"
        class="campaign-card"
      >
        <img src={campaign.imageUrl} alt={campaign.title} />
        <strong>{campaign.title}</strong>
      </a>
    {/each}
  </div>
</main>

<style>
  .campaign-grid {
    display: grid;
    gap: 12px;
    margin-top: 16px;
  }

  .campaign-card {
    display: grid;
    gap: 8px;
    color: inherit;
    text-decoration: none;
  }
</style>

Notas

  • Solicite acceso al micrófono únicamente a partir de una acción del usuario, como hacer clic en un botón.
  • Si la página o el componente pueden eliminarse, llame a destroy() durante la limpieza.
  • Si necesita un flujo de control más completo, añada stop() y otros handlers de eventos una vez que esta conexión mínima funcione.