¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Del sonido al texto con tiempos

Después de esta lección: Puedo cortar muestras en ventanas y unir una transcripción con tiempos en líneas con marcas.

Lección de 75 min7 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Una nota de voz pasa a texto

Envías una nota de voz y una aplicación muestra lo que dijiste, con una hora junto a cada parte. La aplicación nunca oyó una voz. Recibió una larga lista de números.

Esta lección enseña cómo el sonido se convierte en números, cómo se cortan y cómo vuelven las palabras con sus tiempos.

Al final de esta lección

Nota

Puedo cortar muestras en ventanas y unir una transcripción con tiempos en líneas con marcas.

Palabras clave

PalabraQué significa
Muestrauna medida de lo fuerte que suena el sonido en un instante
Frecuenciacuántas muestras se toman cada segundo
Ventanauna tanda corta de muestras tratada como un trozo
Saltocuántas muestras después de la ventana anterior empieza la siguiente
Transcripciónlas palabras dichas, con el tiempo de cada parte

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

El sonido es una lista de muestras

Un micrófono mide lo fuerte que suena el aire, una y otra vez. Cada medida es una muestra, un número que puede ser positivo o negativo.

La frecuencia dice cuántas muestras se toman cada segundo. El habla suele usar 16000 por segundo. Aquí se usa una frecuencia de 100 para que las listas sean cortas.

Cuánto mide una lista de muestras

Frecuencia (por segundo)SegundosMuestras
1001100
1003300
16000116000
16000232000

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Las ventanas cortan las muestras en trozos

Un modelo no lee una muestra cada vez. Las muestras se cortan en ventanas, tandas cortas de la misma longitud. El salto es lo que se separa el inicio de la siguiente ventana del de la anterior.

Con una ventana de 10 y un salto de 10, las ventanas no se solapan. Con un salto de 5, sí. El tiempo de inicio es el número de ventana por el salto, dividido por la frecuencia.

Un error frecuente

Advertencia

Mucha gente calcula el inicio de una ventana con el tamaño de la ventana. La siguiente empieza un salto después, no una ventana después. Si se solapan, los dos números difieren. Usa siempre el salto.

Una transcripción tiene tiempos

Un reconocedor devuelve partes: unas palabras, un inicio y un final en milisegundos. Las partes que van muy seguidas forman una línea.

Une una parte a la línea anterior cuando el hueco entre ellas es menor que un límite. Luego escribe cada línea con una marca como [00:03,0].

Escribe el ayudante del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el ayudante del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    const d = await res.json();' '    return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el script del sonido, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const RATE = 100;' 'const samples = [];' 'for (let i = 0; i < 80; i++) {' '  const amp = i >= 20 && i < 60 ? 40 : 2;' '  samples.push((i % 2 === 0 ? amp : -amp) + (i % 5));' '}' 'const parts = [' '  { start: 200, end: 900, text: \"apaga\" },' '  { start: 950, end: 1400, text: \"las luces\" },' '  { start: 3000, end: 3600, text: \"por favor\" },' '];' > sound4.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el script del sonido, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function frames(s, size, hop) {' '  const out = [];' '  for (let i = 0; i + size <= s.length; i += hop) out.push(s.slice(i, i + size));' '  return out;' '}' 'function loud(f) {' '  let t = 0;' '  for (const v of f) t += Math.abs(v);' '  return Math.floor(t / f.length);' '}' >> sound4.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el script del sonido, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function stamp(ms) {' '  const m = Math.floor(ms / 60000);' '  const s = Math.floor((ms % 60000) / 1000);' '  const t = Math.floor((ms % 1000) / 100);' '  return \"[\" + String(m).padStart(2, \"0\") + \":\" + String(s).padStart(2, \"0\") + \",\" + t + \"]\";' '}' 'function join(list, gap) {' '  const lines = [];' '  for (const p of list) {' '    const last = lines[lines.length - 1];' '    if (last && p.start - last.end < gap) { last.text += \" \" + p.text; last.end = p.end; }' '    else lines.push({ start: p.start, end: p.end, text: p.text });' '  }' '  return lines.map(function (l) { return stamp(l.start) + \" \" + l.text; });' '}' >> sound4.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el script del sonido, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const fs = frames(samples, 10, 10);' '  const levels = fs.map(loud);' '  console.log(\"ventanas \" + fs.length + \", cada una de \" + (10 * 1000 / RATE) + \" ms\");' '  console.log(\"volumen \" + levels.join(\" \"));' '  console.log(\"voz desde la ventana \" + levels.findIndex(function (v) { return v >= 10; }));' '  const lines = join(parts, 300);' '  for (const l of lines) console.log(l);' '  const q = \"Escribe un pie corto para un clip con estas líneas: \" + lines.join(\" \");' '  const reply = await ask([{ role: \"user\", content: q }], \"Alguien pide que apaguen las luces.\", 30);' '  console.log(\"respuesta: \" + reply.text);' '}' 'main();' >> sound4.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Corta el sonido y une las palabras

Comando
docker exec -w /home/node/project agent node sound4.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Las líneas que imprime

LíneaQué muestra
ventanas 8, cada una de 100 ms80 muestras en ventanas de 10 a 100 por segundo
volumen 2 2 40 40 40 40 2 2Las cuatro ventanas del medio son fuertes
voz desde la ventana 2La ventana 2 empieza en 200 ms
[00:00,2] apaga las lucesDos partes unidas, porque su hueco era de 50 ms
[00:03,0] por favorEsta parte llegó 1600 ms después, así que va sola

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.