programa
Microsoft ha lanzado tres modelos listos para producción bajo su paraguas MAI (Microsoft AI): MAI-Transcribe-1 para voz a texto, MAI-Voice-1 para texto a voz, y MAI-Image-2 para generación de imágenes desde texto. Los tres están disponibles a través de Microsoft Foundry, con acceso real a la API.
En este tutorial haremos dos cosas: primero, verás paso a paso cómo aprovisionar y conectar cada modelo vía Azure. Después, construiremos una app en Streamlit que prueba los tres modelos con prompts reales y llamadas a la API.
Al terminar, serás capaz de:
- Aprovisionar MAI-Transcribe-1, MAI-Voice-1 y MAI-Image-2 en Azure
- Entender los benchmarks clave y qué significan en la práctica
- Llamar a los tres modelos desde Python a través de una interfaz en Streamlit
- Conocer las funciones y limitaciones clave de cada modelo antes de comprometerte a construir sobre ellos
El código completo está disponible en el repositorio de GitHub.
¿Qué son los modelos MAI de Microsoft?
La familia de modelos MAI de Microsoft está desarrollada por el equipo Microsoft AI Superintelligence. Son modelos completamente internos, entrenados en la propia infraestructura de Microsoft, optimizados para su stack de serving y desplegados directamente en Azure. MAI-Transcribe-1 y MAI-Voice-1 se ejecutan sobre la misma infraestructura de Azure Speech que ya da servicio a clientes enterprise a escala, mientras que MAI-Image-2 usa una arquitectura de difusión con flow-matching y el mismo objetivo de entrenamiento que Stable Diffusion 3, con entre 10 y 50 mil millones de parámetros (sin contar embeddings).
Aquí tienes un resumen rápido de los tres:
|
Modelo |
Tarea |
Métrica clave |
Precio |
|
MAI-Transcribe-1 |
Voz a texto |
3,88% WER medio en FLEURS |
$0,36/h |
|
MAI-Voice-1 |
Texto a voz |
60 s de audio en 1 s |
$22/1M caracteres |
|
MAI-Image-2 |
Texto a imagen |
Elo 1190 global |
$5/1M tokens de texto + $33/1M tokens de imagen |
Vamos a profundizar en cada uno antes de construir.
MAI-Transcribe-1
MAI-Transcribe-1 es un modelo de voz a texto que admite 25 idiomas. Su dato estrella es un WER (Word Error Rate) medio del 3,88% en el benchmark FLEURS (cuanto más bajo, mejor), lo que lo sitúa por delante de GPT-Transcribe (4,17%), Scribe v2 (4,32%), Gemini 3.1 Flash-Lite (4,89%) y Whisper-large-v3 (7,60%).
El modelo está específicamente diseñado para audio real con ruido: entornos ruidosos, acentos variados y estilos de habla naturales. Microsoft también afirma que MAI-Transcribe-1 ofrece buena precisión con aproximadamente un 50% menos de coste de GPU que las alternativas líderes, una ventaja importante para empresas que transcriben a gran escala.
Aun así, todavía carece de transcripción en tiempo real, diarización de hablantes y sesgo de contexto, todas marcadas como "próximamente".
MAI-Voice-1
MAI-Voice-1 es el modelo TTS de alta fidelidad de Microsoft. Su capacidad clave es el "voice prompting": proporcionas una muestra de audio de 10 segundos y el modelo clona esa voz sin fine-tuning. Sin embargo, la clonación de voz requiere aprobación restringida de Microsoft; la biblioteca de voces curadas (nombres como en-us-Jasper:MAI-Voice-1, en-us-June:MAI-Voice-1) está disponible de inmediato.
El modelo genera 60 segundos de audio en un segundo con una sola GPU, admite control emocional por turno vía SSML y está pensado para contenido de larga duración como audiolibros y pódcasts. Ya impulsa Audio Expressions y funciones de pódcast de Copilot en productos de Microsoft.
Un inconveniente es que por ahora es "solo en inglés", con más de 10 idiomas en camino.
MAI-Image-2
MAI-Image-2 utiliza una arquitectura de difusión con flow-matching y 10–50 mil millones de parámetros. Es top 3 en el ranking de imágenes de Arena.ai y es el doble de rápido que MAI-Image-1 en producción. Se desarrolló en colaboración con fotógrafos, diseñadores y creadores visuales, y ya está desplegado en Copilot, Bing Image Creator y PowerPoint. Está especialmente orientado al fotorrealismo, tonos de piel precisos y texto legible dentro de la imagen.
Sus puntuaciones Elo por categoría incluyen fotorrealismo (1201) y retratos (1201), donde destaca, mientras que el renderizado de texto (1186) mejora respecto a antes pero sigue siendo su punto más débil.
Configurar Azure para todos los modelos
Los tres modelos MAI están disponibles en Microsoft Azure. MAI-Transcribe-1 y MAI-Voice-1 comparten el mismo recurso de Azure Speech, mientras que MAI-Image-2 se ejecuta a través de Microsoft Foundry. Vamos a configurar ambos paso a paso.
Requisitos previos
- Regístrate o inicia sesión en tu cuenta de Azure para obtener $200 de crédito gratis
- Python 3.9+
Paso 1: crea un recurso de Azure Speech
Tanto MAI-Transcribe-1 como MAI-Voice-1 se acceden a través del servicio Azure AI Speech, así que un único recurso cubre ambos.
-
Ve a portal.azure.com
-
En la barra de búsqueda, escribe Speech y selecciona Speech services
-
Haz clic en + Create
-
Rellena el formulario:
-
Grupo de recursos: crea uno nuevo y llámalo
mai-demo-rg -
Región: selecciona
East USporque los modelos MAI actualmente solo están soportados en East US y West US -
Nombre:
mai-speech-demo -
Nivel de precios:
Standard S0 -
Nota: Free F0 tiene límites de tasa que pueden interrumpir la demo
-
Por último, haz clic en Review and create, y tras unos segundos, pulsa Create.
Cuando termine el despliegue, ve a Keys and Endpoint en la barra lateral izquierda y copia Key 1 y toma nota de la Region (eastus).

Paso 2: crea un recurso de Foundry y despliega MAI-Image-2
Se accede a MAI-Image-2 a través de Microsoft Foundry, que es independiente del portal habitual de Azure.

-
Desde la página principal del portal de Azure, haz clic en Foundry en la fila superior de servicios
-
Haz clic en Create a resource
-
Ahora, completa estos datos:
-
Grupo de recursos: selecciona el mismo
mai-demo-rgdel Paso 1 -
Región: East US
-
Nombre:
mai-image-demo -
Nombre de proyecto por defecto:
proj-default -
Luego, haz clic en Review and create, y pulsa Create
-
Cuando el recurso esté activo, haz clic en Go to Foundry portal.
-
Después, en la interfaz de Foundry, haz clic en Model catalog en la barra lateral izquierda

- Busca
MAIen la barra y verás los cuatro modelos MAI listados

-
Selecciona MAI-Image-2 y haz clic en Use this model
-
En el cuadro de despliegue, establece:
-
Nombre del despliegue:
MAI-Image-2 -
Tipo de despliegue:
Global Standard -
Por último, haz clic en deploy

Tras el despliegue, llegarás a la página de detalles. Copia el Target URI (algo como https://mai-image-demo.services.ai.azure.com/models) y la Key.
Paso 3: configura el archivo .env
Crea un archivo .env en el directorio local del proyecto y añade los datos obtenidos en los dos pasos anteriores:
AZURE_SPEECH_KEY=your_speech_key_1_here
AZURE_SPEECH_REGION=eastus
AZURE_IMAGE_ENDPOINT=https://your-resource-name.services.ai.azure.com/models
AZURE_IMAGE_KEY=your_foundry_key_here
AZURE_IMAGE_DEPLOYMENT=MAI-Image-2
Nota importante: AZURE_IMAGE_DEPLOYMENT distingue mayúsculas y minúsculas. Usa MAI-Image-2 exactamente como aparece en Foundry; si usas mai-image-2 en minúsculas recibirás un error unknown_model.
Demo de modelos MAI: crea una app de voz, habla e imagen con Streamlit
En esta sección, construiremos una app de Streamlit con tres pestañas que llama a los tres modelos MAI mediante llamadas en vivo a la API de Azure. A alto nivel, la app hace lo siguiente:
- Pestaña 1: acepta un archivo de audio WAV, MP3 o similar y lo envía a MAI-Transcribe-1 mediante la REST API de Azure Speech, devolviendo una transcripción completa con latencia y coste estimado
- Pestaña 2: recibe texto con selección de voz y estilo emocional, construye una solicitud SSML y llama a MAI-Voice-1 para devolver un MP3 reproducible
- Pestaña 3: acepta un prompt de texto y una resolución, llama a MAI-Image-2 a través del endpoint de Azure Foundry y muestra la imagen generada con opción de descarga
- La app también muestra estimaciones de coste en tiempo real para cada modelo al configurar los inputs
Estructura de archivos:
mai_demo/
├── app.py # Interfaz de Streamlit
├── mai_clients.py # Wrappers de la API de Azure
├── requirements.txt
└── .env
La app se divide en dos archivos: mai_clients.py, que gestiona todas las llamadas a la API de Azure y devuelve diccionarios de resultados estructurados, y app.py, que maneja la UI en Streamlit. Vamos paso a paso.
Paso 1: instala dependencias
A diferencia de un setup local de modelos, esta app conecta con APIs cloud en Azure, así que la lista incluye el SDK de Azure Speech y librerías de soporte para HTTP e imagen.
pip install -r requirements.txt
El archivo requirements.txt contiene:
.txt
streamlit>=1.35.0
azure-cognitiveservices-speech>=1.38.0
requests>=2.31.0
pillow>=10.0.0
python-dotenv>=1.0.0
openai>=1.30.0
En este proyecto usaremos:
-
streamlitpara la UI de tres pestañas, subida de archivos, reproductores de audio y renderizado de imágenes -
azure-cognitiveservices-speechpara el SDK de Azure Speech, usado con MAI-Transcribe-1 y MAI-Voice-1 -
requestspara llamadas directas a las REST APIs de Azure -
pillowpara decodificar y mostrar los bytes de imagen que devuelve MAI-Image-2 -
python-dotenvpara cargar claves de Azure y endpoints desde.enven tiempo de ejecución -
openaipara el SDK compatible con Azure OpenAI, que admite endpoints de generación de imágenes de Foundry
Una vez instalado, asegúrate de que el archivo .env está en el mismo directorio que app.py antes de ejecutar la app. Las credenciales se cargan automáticamente al inicio con python-dotenv.
Paso 2: capa cliente de la API (mai_clients.py)
Todas las llamadas a la API de Azure viven en mai_clients.py, y cada función devuelve un diccionario sencillo del tipo {"success": bool, ...} para que la UI no se rompa ante errores.
MAI-Transcribe-1: voz a texto
MAI-Transcribe-1 se accede mediante el endpoint LLM Speech de la REST API de Azure Speech. La clave es que recibe una solicitud multipart con un archivo de audio y un objeto JSON de definición.
def transcribe_audio(audio_bytes: bytes, filename: str = "audio.wav") -> dict:
url = (
f"https://{speech_region}.api.cognitive.microsoft.com"
f"/speechtotext/transcriptions:transcribe?api-version=2024-11-15"
)
headers = {"Ocp-Apim-Subscription-Key": speech_key}
definition = '{"locales":["en-US"],"profanityFilterMode":"None"}'
files = {
"audio": (filename, audio_bytes, _mime_type(filename)),
"definition": (None, definition, "application/json"),
}
resp = requests.post(url, headers=headers, files=files, timeout=60)
data = resp.json()
combined = " ".join(
p.get("text", "") for p in data.get("combinedPhrases", [])
).strip()
return {"success": True, "transcript": combined, "raw": data, ...}
La respuesta vuelve como un objeto JSON con combinedPhrases, un array de segmentos de texto. Los unimos en una única transcripción. Admite formatos WAV, MP3 y FLAC. La API está limitada por región a East US y West US por ahora.
MAI-Voice-1: texto a voz
MAI-Voice-1 usa el TTS estándar de Azure Speech vía SSML. La clave está en construir el bloque <mstts:express-as> para el control de emoción y referenciar el formato correcto del nombre de voz (en-us-Jasper:MAI-Voice-1).
def _build_ssml(text: str, emotion: str, voice_name: str) -> str:
style_map = {
"neutral": None,
"joy": "joy",
"excitement": "excitement",
"empathy": "empathy",
}
style = style_map.get(emotion)
text_block = (
text if style is None
else f"<mstts:express-as style='{style}'>{text}</mstts:express-as>"
)
return f"""<speak version='1.0' xml:lang='en-US'
xmlns='http://www.w3.org/2001/10/synthesis'
xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='{voice_name}'>
{text_block}
</voice>
</speak>"""
Los nombres de voz disponibles para MAI-Voice-1 siguen el patrón en-us-{Name}:MAI-Voice-1. Actualmente están Jasper, June, Grant, Iris, Reed y Joy.
MAI-Image-2: texto a imagen
MAI-Image-2 usa un endpoint específico de Foundry, que no es la ruta estándar de Azure OpenAI /openai/deployments/. El formato correcto es:
url = f"{base_endpoint}/mai/v1/images/generations"
Aquí, base_endpoint es la raíz del recurso de Foundry (p. ej., https://your-resource.services.ai.azure.com), eliminando cualquier /models final antes de construir la solicitud. El cuerpo exige dos cosas: primero, debes pasar explícitamente el campo model con el nombre de tu despliegue, a diferencia de los endpoints OpenAI estándar, donde el modelo se infiere por la URL:
payload = { "model": deployment, # "MAI-Image-2" "prompt": prompt, "width": width, "height": height, }
Segundo, las dimensiones tienen restricciones: width y height deben ser al menos 768 píxeles, y su producto no puede superar 1.048.576, es decir, máximo 1024×1024 para imágenes cuadradas. Pasar 512×512 u omitir dimensiones devolverá 400 Bad Request.
La respuesta sigue el formato habitual de generación de imágenes de OpenAI. Cada elemento en data incluirá o bien una url a una imagen alojada o un campo b64_json con los bytes en base64. El cliente admite ambos casos:
image_url = row.get("url")
b64 = row.get("b64_json")
if b64:
img_bytes = base64.b64decode(b64)
elif image_url:
img_resp = requests.get(image_url, timeout=30)
img_bytes = img_resp.content
Ten en cuenta que las url son temporales, así que hay que descargar y almacenar los bytes inmediatamente en lugar de guardar la URL para más tarde.
Paso 3: construir la UI en Streamlit (app.py)
La app se organiza en tres pestañas, una por modelo. Esta es la estructura:
import streamlit as st
from mai_clients import transcribe_audio, synthesize_speech, generate_image
tab1, tab2, tab3 = st.tabs([
"🎙 MAI-Transcribe-1",
"🔊 MAI-Voice-1",
"🖼 MAI-Image-2",
])
Cada pestaña sigue el mismo patrón: inputs → botón → spinner → resultados → métricas de coste.
Pestaña 1: MAI-Transcribe-1
La primera pestaña gestiona la subida y transcripción de audio. Acepta archivos WAV, MP3 y FLAC, reproduce el audio inline para que verifiques la prueba y envía los bytes directamente a transcribe_audio() al hacer clic en el botón.
with tab1:
audio_file = st.file_uploader("Upload audio file", type=["wav", "mp3", "flac"])
if audio_file:
st.audio(audio_file)
if st.button("Transcribe", type="primary"):
with st.spinner("Calling MAI-Transcribe-1..."):
result = transcribe_audio(audio_file.read(), audio_file.name)
if result["success"]:
st.text_area("Transcript", value=result["transcript"], height=140)
m1, m2, m3 = st.columns(3)
m1.metric("Latency", f"{result['latency_s']}s")
m2.metric("Audio duration", f"{result['duration_ms']/1000:.1f}s")
m3.metric("Est. cost", f"${result['duration_ms']/3_600_000 * 0.36:.5f}")
Si la respuesta es correcta, la transcripción aparece en un área de texto editable, seguida de tres métricas: latencia de la API en segundos, la duración del audio obtenida de durationMilliseconds y el coste estimado calculado como horas_de_duración × $0,36.
Un clip de 7 segundos cuesta aproximadamente $0,0000007, así que puedes hacer decenas de pruebas sin apenas tocar tu crédito de Azure.
Pestaña 2: MAI-Voice-1
La segunda pestaña gestiona la síntesis de texto a voz. Expone los tres controles que más importan para probar MAI-Voice-1: el texto, el estilo emocional y la voz, que se pasan directamente a la función synthesize_speech().
with tab2:
text_input = st.text_area("Text to synthesize", value="The quarterly results exceeded...")
emotion = st.selectbox("Emotion / style", ["neutral", "joy", "excitement", "empathy"])
voice_name = st.selectbox("Voice", ["en-us-Jasper:MAI-Voice-1", "en-us-June:MAI-Voice-1", ...])
if st.button("Synthesize", type="primary"):
with st.spinner("Calling MAI-Voice-1..."):
result = synthesize_speech(text_input, emotion=emotion, voice_name=voice_name)
if result["success"]:
st.audio(result["audio_bytes"], format="audio/mp3")
El selector de emoción se mapea a estilos SSML <mstts:express-as>; neutral omite la etiqueta para una salida base limpia, mientras que joy, excitement y empathy producen variaciones claras de ritmo y tono. El desplegable de voz cubre las seis voces actuales: Jasper, June, Grant, Iris, Reed y Joy.
Si tiene éxito, los bytes MP3 se envían directamente a st.audio() para su reproducción inline. Con 113 caracteres, el coste estimado es $0,000002, así que podrás hacer varias pruebas sin agotar créditos.
Pestaña 3: MAI-Image-2
La tercera pestaña gestiona la generación de imágenes desde texto. La API actual de MAI-Image-2 expone dos parámetros de entrada: prompt y resolución. No hay niveles de calidad ni controles de estilo; el modelo lo gestiona internamente.
with tab3:
prompt = st.text_area("Image prompt", value="A worn paperback book on a café table...")
size = st.selectbox("Resolution", ["1024x1024", "1365x768", "768x1365"])
if st.button("Generate", type="primary"):
with st.spinner("Calling MAI-Image-2..."):
result = generate_image(prompt, size=size)
if result["success"]:
img = Image.open(io.BytesIO(result["image_bytes"]))
st.image(img, use_container_width=True)
Las tres resoluciones cubren las proporciones principales: cuadrada (1024×1024), apaisada (1365×768) y vertical (768×1365). La cadena de tamaño se analiza en ancho y alto antes de enviarla a la API, ya que el endpoint de Foundry los recibe como campos separados.
Si todo va bien, los bytes de imagen se envuelven en un buffer BytesIO, se abren con Pillow y se muestran a ancho completo del contenedor. La generación suele tardar 2–4 segundos, notablemente más rápido que MAI-Image-1 en el mismo entorno.
Paso 4: ejecuta la app
Con el archivo .env configurado y las dependencias instaladas, ya puedes ejecutar la app.
streamlit run app.py
Streamlit iniciará un servidor local y abrirá la app en tu navegador en http://localhost:8501. Deberías ver la interfaz de tres pestañas con MAI-Transcribe-1 activa por defecto.

Pruebas con los modelos
Esto es lo que produjeron los modelos al ejecutarlos.
Prueba 1: transcripción con ruido
Probé MAI-Transcribe-1 con un clip de 7 segundos grabado en un entorno ruidoso controlado y con acento indio. El modelo devolvió una transcripción limpia y precisa en menos de 2 segundos.
Conclusión: El resultado se mantuvo bien con habla acentuada, que es donde Whisper-large-v3 suele fallar más. Dicho esto, los datos por idioma cuentan otra historia: árabe se sitúa en 10,1% y danés en 13,2%, ambos por encima de la cifra global. Si tu caso de uso implica un idioma concreto o una distribución regional de acentos, pruébalo con tu audio real antes de llevarlo a producción.
Prueba 2: control de emoción
Sinteticé una frase de 113 caracteres con el estilo excitement usando la voz en-us-Jasper:MAI-Voice-1, y devolvió un MP3 de 6 segundos en menos de 1 segundo. La emoción se notaba claramente en el resultado, con mayor energía y variación de tono.

Conclusión: Generar un clip de 6 segundos en menos de 1 segundo es impresionante. El control SSML funciona, pero está limitado a cuatro estilos: neutral, joy, excitement y empathy. No esperes la amplitud expresiva de la librería de estilos de ElevenLabs.
Prueba 3: fotorrealismo y renderizado de texto
Esta es la prueba más interesante porque elegí un prompt que combina dos cosas: composición fotorrealista y texto dentro de la imagen. La mayoría de modelos de difusión fallan en al menos una.
Prompt: "A worn paperback book on a café table, natural window light, steam rising from an espresso cup beside it. The book cover reads: INFERENCE AT SCALE — text clearly legible, not warped."

Conclusión: El fotorrealismo es realmente sólido: luz natural de ventana, vapor convincente y texturas creíbles en el libro y la taza. El texto "INFERENCE AT SCALE" también salió correcto y legible.
Sin embargo, el renderizado de texto es inconsistente entre ejecuciones. En varias pruebas con prompts similares, el modelo a veces generó texto con errores u oscuro. Es una limitación conocida de los modelos de difusión actuales: MAI-Image-2 mejora a la mayoría, pero no es inmune. Además, la resolución máxima actual es 1024×1024 píxeles, suficiente para la web y contenido digital, pero insuficiente para impresión o formatos grandes sin un paso de upscaling. Si generas imágenes donde el texto es crítico, incorpora siempre una revisión humana.
Conclusión
La familia de modelos MAI de Microsoft es realmente potente. Los números de FLEURS de MAI-Transcribe-1 son los más verificables de los tres: un WER medio del 3,88%, líder del sector a fecha de hoy.
MAI-Voice-1 destaca por velocidad y calidad de voz, pero está limitado al inglés y a una paleta emocional reducida. MAI-Image-2 ofrece un gran fotorrealismo, con la salvedad de que pueden aparecer alucinaciones en el texto y requiere revisión humana en producción.
El código completo de este tutorial está disponible en GitHub.
Soy experta Google Developers en ML (Gen AI), triple experta en Kaggle y embajadora de Women Techmakers, con más de tres años de experiencia en el sector tecnológico. Cofundé una startup de salud en 2020 y actualmente curso un máster en informática en Georgia Tech, con especialización en aprendizaje automático.
FAQs
¿Necesito una cuenta de pago de Azure para usar los modelos MAI?
Las cuentas nuevas de Azure incluyen $200 en crédito gratuito y Azure for Students añade $100. Dado que una sesión completa de demo con los tres modelos cuesta bastante menos de $0,01, ese crédito te sobra para empezar. Tendrás que pasar a cuenta de pago si planeas usar los modelos en producción y a escala.
¿Puedo usar MAI-Transcribe-1 para transcripción en tiempo real en un agente de voz?
Todavía no. MAI-Transcribe-1 solo funciona en modo batch: envías un archivo de audio completo y recibes la transcripción. Si necesitas tiempo real sí o sí, mantén Whisper o la oferta de tiempo real de Azure Speech como alternativa mientras esperas.
¿Por qué MAI-Image-2 a veces escribe mal palabras en las imágenes generadas?
Es una limitación conocida de los modelos de generación de imágenes basados en difusión, no específica de MAI-Image-2. El modelo genera imágenes transformando ruido en píxeles, así que no tiene una comprensión explícita de la ortografía o de secuencias de caracteres como un modelo de lenguaje. MAI-Image-2 gestiona el texto visiblemente mejor que su predecesor (Elo 1186 vs 1069), pero las inconsistencias siguen apareciendo, especialmente con palabras largas o tipografías estilizadas. Incluir una revisión humana antes de usar las imágenes en producción es una buena práctica.
¿Puedo clonar cualquier voz con MAI-Voice-1?
La clonación de voz mediante la función Personal Voice requiere una muestra de 10 segundos de la persona y su consentimiento grabado explícito. El acceso es restringido, por lo que debes solicitar aprobación a través del proceso de Limited Access Review de Microsoft.




