Historial del chat

ChatGPT

Sora

Photo Realistic Image GPT

Explorar GPT

Proyectos

Nuevo proyecto

7 días anteriores

Remuestreo vs cambio inteligente

Descargar jq Windows

30 días anteriores

Espectrometría y cromatografía forense

Serpiente y rana venenosa

Renovación y posibles problemas

Error en archivo ZIP

Problema con PayPal Checkout

enero

Preguntar sobre webs

Ver planesAcceso ilimitado, características de Team y más

Abrir barra lateral

ChatGPT o3-mini-high

ChatGPT o3-mini-high

Compartir

Dijiste:

Me podrias traducir esto al ingles por favor Chat!!!
/////////////
Necesitaria hacer una serie de videos hablados con audio mp3, se puede hacer con vuestra API?

Donde hay documentacion sobre vuestra API?

En https://www.hedra.com/api-profile ya vi que existe la API y que tiene un precio, lo cual no me importaria si en vez de ir haciendo manualmente unos 100 videos que necesito hacer, quisiera automatizar mediante la API, y que coste tendrian en creditos unos 100 videos de medio minuto realizados mediante la API?

Pago mensualmente Hedra, mi username es mi email, este [email-masked]

Gracias por adelantado, y aguardo vuestra respuesta...

Ana
////////////////////

Razonado durante 7 segundos

I would need to make a series of spoken videos with MP3 audio. Is it possible to do that with your API?

Where can I find documentation about your API?

At https://www.hedra.com/api-profile, I’ve seen that there is an API and that it has a cost. That wouldn’t bother me if, instead of manually making around 100 videos, I could automate them through the API. How many credits would 100 30-second videos created with the API cost?

I pay Hedra monthly, and my username is my email address ([email-masked]).

Thank you in advance, and I look forward to your response.

Ana

Dijiste:

Parece que Hedra si tiene una API:
https://www.hedra.com/api-profile

Sabrias la documentacion para usarla?

Razonado sobre la documentación de la API de Hedra durante 4 segundos

No existe mucha información pública en internet (al menos fácilmente accesible) sobre la documentación de la API de Hedra fuera de la página que has compartido [hedra.com/api−profile](https://www.hedra.com/api−profile)[hedra.com/api-profile](https://www.hedra.com/api-profile)[hedra.com/api−profile](https://www.hedra.com/api−profile). Dado que esa sección parece más una página informativa sobre la existencia de la API, pero no la documentación completa, lo más probable es que la documentación detallada esté disponible de alguna de estas maneras:

Dentro de tu cuenta de Hedra:

A veces, para acceder a la documentación de la API, necesitas iniciar sesión y, desde tu panel, encontrar algún apartado como “Developer” o “API Docs” o “Integraciones”.

Contacto directo con el soporte de Hedra:

Si no la encuentras en tu panel, tal vez debas solicitarles acceso o documentación por correo o por un formulario de contacto.

Ellos suelen darte una clave de API o un token de autenticación y explicarte los endpoints y la estructura de las llamadas.

Soporte o FAQ en su página principal:

En la parte inferior de la página de Hedra, puede que haya un enlace a “Soporte” o “FAQ” donde se incluya la documentación o una guía para desarrolladores.

Eventualmente, un portal dedicado a desarrolladores (por ejemplo, developers.hedra.com o algo similar):

Este tipo de plataformas a veces tiene un subdominio o una URL distinta para el portal de desarrolladores.

Si ya has revisado la página [hedra.com/api−profile](https://www.hedra.com/api−profile)[hedra.com/api-profile](https://www.hedra.com/api-profile)[hedra.com/api−profile](https://www.hedra.com/api−profile) y no ves nada más allá de la información de precios y uso, te recomendaría:

Ingresar en tu cuenta de Hedra y buscar en tu panel de control opciones de desarrollador/API.

Contactar con el soporte de Hedra para que te envíen la documentación o un enlace específico.

En resumen, parece que Hedra sí dispone de una API, pero la documentación no está públicamente enlazada de forma clara. Por tanto, la mejor opción es (1) buscar dentro de tu panel de usuario, y (2) contactar directamente al soporte para que te den la documentación oficial, los endpoints y los ejemplos de uso.

Dijiste:

Yo les consulte ayer, y parece que me han enviado esto:
////////////////////
Michael Lingelbach <[email-masked]>
mar, 25 feb, 19:06 (hace 19 horas)
para mí, support

Hi Ana,

100 videos of 30 seconds each would be 50 credits, which works out to be ~25 USD. The credits are billed separately from your monthly account. Here's some code to get you started:

https://github.com/hedra-labs/hedra-api-starter

Michael
////////////////////

Podrias ir a https://github.com/hedra-labs/hedra-api-starter y si me puedes ayudar a como se hace?

Yo ya tengo mi API Key, sabrias como seria el codigo de archivo bat - a ser posible enviarle varios, o sea, por lotes - para enviarle una foto y un audio hecho con https://elevenlabs.io/app/speech-synthesis/text-to-speech y que me creara el video y me lo bajara a mi Pc?

Razonado durante 14 segundos

Te daré una guía general de cómo podrías automatizar la subida de una imagen y un audio a la API de Hedra para generar un video y luego descargarlo a tu PC, usando un archivo .bat en Windows. Sin embargo, debes tener en cuenta que:

Desconozco los endpoints exactos que Hedra utiliza para subir la imagen, el audio y descargar el video.

El repositorio que te pasaron [hedra−labs/hedra−api−starter](https://github.com/hedra−labs/hedra−api−starter)[hedra-labs/hedra-api-starter](https://github.com/hedra-labs/hedra-api-starter)[hedra−labs/hedra−api−starter](https://github.com/hedra−labs/hedra−api−starter) probablemente muestre ejemplos en Node.js o Python, no en batch.

En un archivo .bat puro es bastante incómodo hacer peticiones HTTP y procesar respuestas JSON (por ejemplo, para extraer un video_id o una URL de descarga).

Por eso, a veces es mucho más fácil usar un script en Node.js o Python (como el del repositorio) que te permita subir la imagen y audio, y luego descargar el video, todo en el mismo flujo.

1. Estructura más habitual de la API

Normalmente, el flujo para crear un video con una API como la de Hedra podría ser:

Enviar una petición POST con:

Tu API Key (en la cabecera Authorization: Bearer <TU_API_KEY>).

El archivo de imagen (image=@ruta\de\tu\archivo.jpg).

El archivo de audio (audio=@ruta\de\tu\archivo.mp3).

La API, si es asíncrona, te devuelve un ID o un estado indicando que tu video se está procesando.

Esperas unos segundos (o llamas a otro endpoint) para que el video termine de procesarse.

Descargas el archivo de video de una URL que la API te habrá proporcionado en el paso anterior (o en otra llamada).

Cada API es distinta, así que lo ideal es mirar la documentación oficial o el ejemplo del repositorio en GitHub.

2. Ejemplo simplificado usando curl en Windows

Asumiendo (¡ojo, es un ejemplo hipotético!) que la API de Hedra tiene un endpoint de tipo:

bash

Copiar

POST https://api.hedra.com/v1/videos

donde le mandas image y audio, y te responde con un JSON que contiene un campo download_url para descargar el video. Y suponiendo también que el procesamiento es inmediato (lo cual es raro, pero vamos a simplificar). Podrías tener algo así en un .bat:

bat

Copiar

@echo off
REM =======================
REM Configura tus variables
REM =======================
SET API_KEY=TU_API_KEY_AQUI
SET IMAGE_PATH=C:\ruta\imagen.jpg
SET AUDIO_PATH=C:\ruta\audio.mp3

REM El nombre final del video al descargarlo
SET OUTPUT_VIDEO=C:\ruta\video_final.mp4

REM =============
REM Subir a Hedra
REM =============
echo Subiendo imagen y audio a Hedra...
curl ^
-X POST ^
-H "Authorization: Bearer %API_KEY%" ^
-F "image=@%IMAGE_PATH%" ^
-F "audio=@%AUDIO_PATH%" ^
https://api.hedra.com/v1/videos ^
-o response.json

REM =============================================
REM En este punto, 'response.json' contiene el JSON
REM devuelto por la API de Hedra. Hace falta leerlo
REM y extraer el campo 'download_url' (por ejemplo).
REM Con batch puro es complicado parsear JSON.
REM =============================================

REM Simulemos que la respuesta es algo así:
REM {
REM "status": "ok",
REM "download_url": "https://api.hedra.com/v1/videos/abc123/output.mp4"
REM }

REM Para parsear JSON en Windows, se suele usar jq (si lo tienes instalado)
REM Descarga jq.exe y colócala en tu %PATH% o en la misma carpeta.

for /f "usebackq tokens=* delims=" %%i in (`jq -r ".download_url" response.json`) do (
set DOWNLOAD_URL=%%i
)

echo La URL de descarga es: %DOWNLOAD_URL%

REM =====================
REM Descargar el archivo
REM =====================
echo Descargando el video final...
curl -L "%DOWNLOAD_URL%" -o "%OUTPUT_VIDEO%"

echo Proceso completado. El video está en %OUTPUT_VIDEO%.
pause

¿Qué hace este script?

Define tu %API_KEY%, la ruta de la imagen y la del audio.

Llama con curl al endpoint POST /v1/videos con los campos image y audio adjuntos. La respuesta se almacena en response.json.

Usa jq (una herramienta de línea de comandos para procesar JSON en Windows/Mac/Linux) para extraer el valor de "download_url" de ese JSON.

Lo guarda en la variable %DOWNLOAD_URL%.

Ejecuta otro curl para descargar el video final a la ruta %OUTPUT_VIDEO%.

Nota: Esto solo funcionará si la API te da la URL de descarga inmediatamente. Si la API de Hedra requiere un tiempo de proceso, seguramente te devuelva un video_id y necesites llamar a otro endpoint varios segundos después (o consultar en un bucle) hasta que el video esté disponible.

3. Hacerlo “por lotes” (varios videos a la vez)

Si tienes una carpeta con, por ejemplo, 100 audios y 1 imagen fija, podrías hacer un bucle. Supongamos que todos tus .mp3 están en una carpeta C:\audios y se llaman audio1.mp3, audio2.mp3, ..., audio100.mp3. Podrías hacer algo así:

bat

Copiar

@echo off
SET API_KEY=TU_API_KEY_AQUI
SET IMAGE_PATH=C:\ruta\imagen.jpg
SET AUDIO_FOLDER=C:\audios
SET OUTPUT_FOLDER=C:\videos_listos

for %%A in (%AUDIO_FOLDER%\*.mp3) do (
echo Procesando el audio %%~nA.mp3

REM 1) Subir a la API
curl -X POST ^
-H "Authorization: Bearer %API_KEY%" ^
-F "image=@%IMAGE_PATH%" ^
-F "audio=@%%A" ^
https://api.hedra.com/v1/videos ^
-o response.json

REM 2) Extraer la URL de descarga con jq
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".download_url" response.json`) do (
set DOWNLOAD_URL=%%i
)

REM 3) Descargar video
curl -L "%DOWNLOAD_URL%" -o "%OUTPUT_FOLDER%\%%~nA.mp4"

echo Video guardado en %OUTPUT_FOLDER%\%%~nA.mp4
echo ---------------------------
)

pause

%%~nA en batch es el nombre del archivo sin la extensión (por ejemplo, si %%A = C:\audios\audio1.mp3, entonces %%~nA = audio1).

Así, vas generando audio1.mp4, audio2.mp4, etc.

Pero ojo, reitero: Esto es un flujo muy simplificado que asume:

Que la API responde al instante con la download_url.

Que no hace falta esperar a que Hedra termine de procesar.

Que la respuesta JSON se parsea sin problemas con jq.

En la práctica, puede que necesites:

Enviar la imagen y el audio.

Recibir un ID o “job ID”.

Consultar en bucle GET /v1/videos/<job_id>/status hasta que aparezca “completed”.

Luego descargar con GET /v1/videos/<job_id>/download o similar.

4. Revisando el repositorio hedra-api-starter

Lo ideal es que, antes de lanzarte con un .bat, mires el ejemplo en
hedra-labs/hedra-api-starter
para ver:

Cuál es el endpoint.

Qué parámetros exactamente requiere (image vs photo, voice vs audio, etc.).

Si la creación de video es síncrona o asíncrona.

Cómo y cuándo se obtiene la URL de descarga.

Puede que el ejemplo use Node.js con algo así (pseudo-código):

js

Copiar

const axios = require('axios');
const FormData = require('form-data');
...
const form = new FormData();
form.append('image', fs.createReadStream('path/to/image.jpg'));
form.append('audio', fs.createReadStream('path/to/audio.mp3'));

const response = await axios.post('https://api.hedra.com/v1/videos', form, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
...form.getHeaders()
}
});
// Procesar response.data

Luego, si devuelven un video_id, seguramente haya que hacer algo como:

js

Copiar

let videoUrl;
do {
const status = await axios.get(`https://api.hedra.com/v1/videos/${video_id}`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
if (status.data.ready) {
videoUrl = status.data.download_url;
break;
}
await new Promise(r => setTimeout(r, 5000)); // Espera 5 seg
} while (!videoUrl);

// Finalmente descargas:
const videoFile = fs.createWriteStream('output.mp4');
const downloadResponse = await axios.get(videoUrl, { responseType: 'stream' });
downloadResponse.data.pipe(videoFile);

Eso es mucho más fácil de hacer en un script en Node.js, Python u otro lenguaje con manejo de JSON y HTTP, que en un .bat.

Conclusión

Sí se puede hacerlo con un .bat usando curl, pero solo si la API de Hedra funciona de forma muy simple (o si instalas utilidades adicionales como jq para parsear JSON y te encargas de la lógica de esperar a que el video esté listo).

Lo ideal: Revisar el hedra-api-starter y quizás adaptar ese código en Node.js o Python. Esto te permitirá automatizar la subida de 100 audios y la descarga de 100 videos de manera mucho más sencilla y robusta.

En cualquier caso, necesitarás tu API Key y las rutas correctas de imagen/audio.

Si de todos modos insistes en .bat, el ejemplo que te di arriba puede servir de punto de partida, pero debes ajustarlo a cómo sea realmente la API de Hedra:

Endpoint real.

Campos de formulario reales.

Manejo de respuesta asíncrona.

Descarga del video final.

¡Suerte con la integración!

Dijiste:

Evidentemente Hedra no va a crear los videos de forma instantenea, como si hace el audio https://elevenlabs.io/app/speech-synthesis/text-to-speech que ayer em distes un codigo genial que creaba todos los mp3 a trtaves de un texto, el codigo fue estupendo, pero la creacion de video no creo que pueda ser rapida, mirare la documentacion de github del api de hedra, pero te he preguntado antes porque ya sabia yo que me darias algunas indicaciones que em ayudarian en el entendimiento de lo que hay en gitHub.

Muchas gracias Chat, eres un Lujo!!!

Razonado durante un segundo

¡Me alegra que te sirva! Sí, seguramente Hedra necesitará un tiempo para procesar cada video y, en consecuencia, tendrás que hacer llamadas adicionales (o un bucle) para saber cuándo está listo y descargarlo. Si en el repositorio de GitHub usan Node.js o Python, verás que todo ese flujo de “pedir → esperar → descargar” se maneja más fácilmente que en un simple .bat.

Cualquier duda que te surja al revisar el proyecto de GitHub, plantéamela. Estaré encantado de ayudarte a descifrar cómo adaptar el código a tu flujo de trabajo. ¡Suerte con la integración!

Dijiste:

Voy a mirar el github, y luego ya te consultare detalles!!! Lo dicho, Muchas Gracias!!!

Razonado sobre la integración con la API de Hedra durante un segundo

¡Perfecto! Tómate el tiempo necesario para revisar el repositorio de GitHub. Cuando tengas dudas específicas sobre la integración o el proceso, tráelas por aquí y con gusto lo vemos en detalle.

¡Mucha suerte con la implementación!

Dijiste:

openapi.json

Archivo

En esta pagina hay codigos de ejemplo:
https://www.hedra.com/docs

Y hay un json para bajar, que te lo paso aqui, no se si puedes interpretarlo y para que sirve...

Le he preguntado a los de Hedra esto:
//////////////////////////
Thank you very much Michael for the information, just a few more questions:

1.- Could you tell me what is the maximum time that can be made with each video?
Videos of 1 minute or more can be made with the API, what is the time limit if you could answer me.

2.- I see that you have examples of phyton, could it be done with a batch bat file?

Sorry for the inconvenience with this query, and thank you very much in advance...

Bests Regards,

Ana
//////////////////////////

Y a ver que em responden, si se puede hacer con batch, aun asi, no me seria mucho problema en hacerlo en phyton si tu me ayudas...

Te paso este mensaje por si en la pagina de documentacion y en el json ves como hacer un archivo por lotes subiendole el audio y la imagen a cada video dentro del archivo por lotes - aunque sea en phyton, aunque preferiria batch simple, pero si no hay otra, pues en phyton -...

Que me puedes decir?

Razonado sobre uso de la API de Hedra durante 38 segundos

El JSON que me has pasado es la especificación OpenAPI de la API de Hedra, y define los endpoints que puedes utilizar para:

Subir audio:

Endpoint: POST /v1/audio

Envías un archivo (clave "file") y recibes en la respuesta un JSON con la URL del audio.

Subir imagen:

Endpoint: POST /v1/portrait

Similar al de audio, envías el archivo de imagen y recibes la URL de la imagen.

Generar el video (avatar hablando):

Endpoint: POST /v1/characters

Aquí envías un JSON que incluye:

"avatarImage": la URL de la imagen que subiste.

"audioSource": puede ser "audio" (si ya tienes un audio) o "tts" (si quieres que se genere el audio a partir de texto).

"voiceUrl": la URL del audio (en caso de usar audio ya generado).

"aspectRatio": proporción deseada (por ejemplo, "1:1", "16:9" o "9:16").

Opcionalmente, también puedes incluir texto, voiceId, etc.

La respuesta a esta llamada te devuelve un JSON con un "jobId", que es el identificador del proyecto o trabajo de generación.

Consultar el estado del proyecto y obtener el video:

Endpoint: GET /v1/projects/{project_id}

Con este endpoint puedes ver el estado (por ejemplo, "Queued", "InProgress", "Completed" o "Failed") y, una vez completado, obtener la URL del video generado en el campo "videoUrl".

¿Cómo automatizar el proceso?

Para generar un video a partir de una imagen y un audio, el flujo general es:

Subir el audio y obtener su URL.

Subir la imagen y obtener su URL.

Iniciar la generación del video llamando a /v1/characters con un JSON que incluya la URL del audio y de la imagen (además de otros parámetros que necesites, como el aspect ratio).

Recoger el jobId de la respuesta.

Consultar el estado del proyecto mediante /v1/projects/{jobId} en un bucle hasta que el estado sea "Completed".

Obtener la URL del video (campo "videoUrl") y descargarlo a tu PC.

¿Batch con archivo .bat o Python?

Archivo .bat:
Aunque es posible hacer peticiones HTTP con herramientas como curl y hasta parsear JSON usando herramientas adicionales como jq, la lógica de espera (para el procesamiento asíncrono del video) y el manejo de errores se vuelve bastante complejo en un archivo batch puro.

Python:
Es mucho más sencillo, ya que con la librería requests se puede manejar el envío de peticiones y el procesamiento de respuestas JSON de forma nativa. Además, se puede implementar un bucle para esperar a que el video esté listo y descargarlo automáticamente.

Ejemplo de código en Python

Aquí tienes un ejemplo de cómo podría ser un script en Python que implemente el flujo descrito:

python

Copiar

import requests
import time

API_KEY = 'TU_API_KEY_AQUI'
BASE_URL = 'https://mercury.dev.dream-ai.com/api'

def upload_audio(file_path):
url = f"{BASE_URL}/v1/audio"
headers = {'X-API-Key': API_KEY}
with open(file_path, 'rb') as f:
files = {'file': f}
response = requests.post(url, headers=headers, files=files)
response.raise_for_status()
return response.json()['url']

def upload_image(file_path):
url = f"{BASE_URL}/v1/portrait"
headers = {'X-API-Key': API_KEY}
with open(file_path, 'rb') as f:
files = {'file': f}
response = requests.post(url, headers=headers, files=files)
response.raise_for_status()
return response.json()['url']

def create_video(image_url, audio_url, aspect_ratio="1:1", audio_source="audio", text=None, voice_id=None):
url = f"{BASE_URL}/v1/characters"
headers = {'X-API-Key': API_KEY}
payload = {
"avatarImage": image_url,
"audioSource": audio_source,
"voiceUrl": audio_url,
"aspectRatio": aspect_ratio
}
if text:
payload["text"] = text
if voice_id:
payload["voiceId"] = voice_id
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
return response.json()['jobId']

def poll_project(job_id, poll_interval=5, timeout=300):
url = f"{BASE_URL}/v1/projects/{job_id}"
headers = {'X-API-Key': API_KEY}
start_time = time.time()
while time.time() - start_time < timeout:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
status = data.get("status")
if status == "Completed":
return data.get("videoUrl")
elif status == "Failed":
raise Exception("La generación del video ha fallado.")
else:
print(f"Estado actual: {status}. Esperando {poll_interval} segundos...")
time.sleep(poll_interval)
raise TimeoutError("Tiempo de espera excedido para la generación del video.")

def download_video(video_url, output_path):
response = requests.get(video_url)
response.raise_for_status()
with open(output_path, "wb") as f:
f.write(response.content)

if __name__ == "__main__":
audio_path = "ruta/al/audio.mp3" # Cambia por la ruta de tu archivo de audio
image_path = "ruta/a/la/imagen.png" # Cambia por la ruta de tu archivo de imagen
output_video = "video_generado.mp4" # Nombre del video descargado

print("Subiendo audio...")
audio_url = upload_audio(audio_path)
print("URL del audio:", audio_url)

print("Subiendo imagen...")
image_url = upload_image(image_path)
print("URL de la imagen:", image_url)

print("Iniciando generación del video...")
job_id = create_video(image_url, audio_url, aspect_ratio="16:9")
print("Job ID:", job_id)

print("Esperando a que el video se genere...")
video_url = poll_project(job_id)
print("URL del video:", video_url)

print("Descargando el video...")
download_video(video_url, output_video)
print("Video descargado en:", output_video)

Procesamiento por lotes

Si necesitas hacer varios videos en lote, puedes envolver este flujo en un bucle. Por ejemplo, si tienes una lista de archivos de audio (o pares de imagen/audio) y quieres procesarlos todos de forma secuencial, podrías hacer algo como:

python

Copiar

import os

# Suponiendo que la imagen es la misma para todos, y tienes una carpeta de audios:
audio_folder = "ruta/a/la/carpeta_de_audios"
output_folder = "ruta/a/la/carpeta_de_videos"

for audio_file in os.listdir(audio_folder):
if audio_file.lower().endswith(".mp3"):
audio_path = os.path.join(audio_folder, audio_file)
output_video = os.path.join(output_folder, os.path.splitext(audio_file)[0] + ".mp4")
print(f"Procesando {audio_file}...")
try:
audio_url = upload_audio(audio_path)
image_url = upload_image(image_path) # Si usas la misma imagen para todos
job_id = create_video(image_url, audio_url, aspect_ratio="16:9")
video_url = poll_project(job_id)
download_video(video_url, output_video)
print(f"Video generado: {output_video}")
except Exception as e:
print(f"Error procesando {audio_file}: {e}")

Conclusiones

La especificación OpenAPI que compartiste te indica cómo se estructuran las peticiones y respuestas de la API de Hedra.

La secuencia es: subir audio → subir imagen → iniciar generación del video (obteniendo un jobId) → consultar el estado del proyecto → descargar el video una vez completado.

Aunque podrías intentar hacer esto con un archivo batch (.bat), usar Python simplifica mucho el manejo de peticiones HTTP, el procesamiento de JSON y la lógica de espera.

Si tienes alguna duda o necesitas ayuda para adaptar el código a tu flujo de trabajo (por ejemplo, para procesamiento en lote), no dudes en consultarme.

¡Espero que esto te ayude a avanzar en la integración!

Dijiste:

Ok, gracias, voy a examinar todo lo que me dices!!!

Razonado durante 6 segundos

¡Perfecto, Ana! Tómate tu tiempo para revisarlo todo y no dudes en consultarme cualquier duda o detalle adicional que necesites resolver en el proceso. ¡Éxito con la integración!

Dijiste:

O sea, por lo que veo, si uso la misma imaghen para todos los videos por lotes - que es mi caso -, solo tendria que tener los audios en una carpeta, parece que los quiere en formato wav, al menos en algun ejemplo que he visto pone en wav - no me seria muy dificil convertirlos de mp3 a wav, me imagino que el propio ffmpeg lo hara -, aqui lo pone:

https://github.com/hedra-labs/hedra-api-starter

1:1
python main.py --api-key sk_hedra-*** --audio assets/audio.wav --img assets/1:1.jpg --ar 1:1

Pero no se si admitira mp3...

Sigo mirando lo que em has escrito, Gracias Chat...

Razonado durante 14 segundos

Sí, efectivamente, si vas a usar la misma imagen para todos los videos por lotes, bastará con tener tus audios en una carpeta. En el ejemplo que has visto se utiliza un archivo WAV, lo que podría indicar que la API espera ese formato para garantizar la calidad o por cuestiones de consistencia en el procesamiento.

No obstante, no está del todo claro si la API admite directamente archivos MP3. Podrías:

Probar enviando un MP3 directamente y ver si la API lo procesa correctamente.

Convertir los MP3 a WAV utilizando herramientas como ffmpeg, lo cual es relativamente sencillo.

Si el ejemplo en GitHub usa WAV, es posible que sea lo recomendado. En cualquier caso, te conviene revisar la documentación en detalle o consultar con el soporte de Hedra para confirmar el formato óptimo.

¡Sigue explorando y cualquier duda me consultas!

Dijiste:

Una pregunta aparte, sabes si sitios como https://elevenlabs.io/app/speech-synthesis/text-to-speech se puede comprar una voz TTS e implementar en un programa propio, para asi no tener que ir pagando mes a mes...

Tengo entendido que algunas se pueden comprar, pero son validas para usar en un Pc solo, si yo hiciera un programa que se instalara en pc's de msi clientes, tendria que pagar cada cliente el TTS?

Hay buenas TTS gratis?

Razonado durante 16 segundos

En general, la mayoría de los servicios TTS de alta calidad, como ElevenLabs, funcionan bajo un modelo de suscripción o pago por uso, en lugar de venderte una licencia única y perpetua. Esto significa que, en un entorno comercial o si deseas integrar la voz en un programa distribuido a múltiples clientes, probablemente debas negociar un contrato o pagar según el uso (o por suscripción) para cada instancia o cliente.

Algunos proveedores grandes (por ejemplo, Nuance o Acapela) sí ofrecen licencias on-premise o para integraciones comerciales a gran escala, pero suelen requerir acuerdos empresariales y, en muchos casos, precios que varían según el número de usuarios o el volumen de uso.

Si buscas opciones gratuitas, existen motores TTS de código abierto como:

eSpeak: Es ligero pero la calidad es bastante robótica.

Festival o MaryTTS: Son opciones que puedes instalar y ejecutar localmente, aunque su calidad natural puede no estar a la altura de los servicios comerciales.

Mozilla TTS / Coqui TTS: Proyectos más recientes que, con algo de configuración, pueden ofrecer voces más naturales sin coste de licencia, pero pueden requerir más trabajo para integrarlos y optimizarlos.

La elección dependerá de la calidad de voz que necesites, la escala de distribución y los recursos que dispongas para la integración y el mantenimiento. Si deseas la mejor calidad y facilidad de integración, suele convenir aceptar un modelo de suscripción o pago por uso; si el coste es una preocupación y puedes asumir un mayor esfuerzo técnico, podrías explorar soluciones open source.

Si tienes más preguntas o necesitas ayuda con la integración, aquí estoy para ayudarte.

Dijiste:

Ok, solo era por saber que informacon me podrias dar, intentare mirar que hay por ahi, sobretodo en vbforums, que a mi em gusta vb6, porque lo domino muy bien y tengo prisa por temrinar mi programa...

Saludos Chat y Gracias, ya seguiremos mañana con la API de Hedra!!!

Razonado durante 7 segundos

¡Perfecto, Ana! Me alegra que la información te haya resultado útil. Mucho éxito con tu proyecto en VB6; si necesitas ayuda mañana con la API de Hedra o con cualquier otro tema, aquí estaré para apoyarte. ¡Saludos y que tengas un excelente día!

Dijiste:

generaraudiosanos_esp2.bat

Archivo

mapa_anos1935to2015.txt

Documento

Hola Chat, mira, para hacer audios con https://elevenlabs.io/app/speech-synthesis/text-to-speech m,e distes al final estos 2 codigos - archivos que te paso en copy paste -, que eran batch, no se puede hacer lo mismo con la API de Hedra?

En el github de hedra https://github.com/hedra-labs/hedra-api-starter hay codigos con phyton, pero me gustaria hacerlo con archivos bat por lotes, como se ha podido hacer con https://elevenlabs.io/app/speech-synthesis/text-to-speech

Razonado sobre automatización con archivos BAT durante 19 segundos

Sí, es posible hacer algo similar con la API de Hedra usando archivos batch, aunque ten en cuenta que, a diferencia de la generación de audio (que suele ser síncrona), la creación de video es asíncrona. Eso implica que tendrás que hacer un bucle que consulte el estado del trabajo (job) hasta que el video esté listo para descargarse.

A continuación, te dejo un ejemplo de cómo podrías estructurar un archivo batch (por lotes) que use curl y jq (para parsear JSON) para interactuar con la API de Hedra:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

REM ===========================================
REM Configuración: Reemplaza con tus datos reales
REM ===========================================
set API_KEY=sk_hedra-XXX
set IMAGE_PATH=C:\ruta\a\imagen.jpg
set AUDIO_PATH=C:\ruta\a\audio.wav
set OUTPUT_VIDEO=C:\ruta\a\video_final.mp4

REM ===========================================
REM 1. Subir el audio
REM ===========================================
echo Subiendo audio...
curl -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_PATH%" "https://mercury.dev.dream-ai.com/api/v1/audio" -o audio_response.json

REM Extrae la URL del audio de la respuesta (requiere jq)
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%i
echo Audio URL: %AUDIO_URL%

REM ===========================================
REM 2. Subir la imagen
REM ===========================================
echo Subiendo imagen...
curl -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "https://mercury.dev.dream-ai.com/api/v1/portrait" -o image_response.json

for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set IMAGE_URL=%%i
echo Imagen URL: %IMAGE_URL%

REM ===========================================
REM 3. Iniciar la generación del video
REM ===========================================
echo Iniciando generación del video...
curl -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "{\"avatarImage\": \"%IMAGE_URL%\", \"audioSource\": \"audio\", \"voiceUrl\": \"%AUDIO_URL%\", \"aspectRatio\": \"1:1\"}" "https://mercury.dev.dream-ai.com/api/v1/characters" -o video_response.json

for /f "usebackq tokens=* delims=" %%i in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%i
echo Job ID: %JOB_ID%

REM ===========================================
REM 4. Consultar el estado del proyecto (polling)
REM ===========================================
echo Consultando el estado del video...
:poll
curl -X GET -H "X-API-Key: %API_KEY%" "https://mercury.dev.dream-ai.com/api/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".status" project_status.json`) do set STATUS=%%i
echo Estado actual: %STATUS%

if "%STATUS%"=="Completed" goto download_video
if "%STATUS%"=="Failed" (
echo La generación del video ha fallado.
goto end
)

REM Espera 5 segundos antes de volver a consultar
timeout /t 5 >nul
goto poll

:download_video
REM Extrae la URL del video generado
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%i
echo Video URL: %VIDEO_URL%

echo Descargando el video...
curl -L "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado en: %OUTPUT_VIDEO%

:end
endlocal
pause

Detalles importantes:

Herramientas necesarias:
• Debes tener curl instalado y accesible en el PATH.
• Para parsear JSON, se utiliza jq; también debe estar instalado y en el PATH.

Flujo del script:

Subida de archivos: Se sube el audio (recomendado en formato WAV, según el ejemplo) y la imagen. Cada uno devuelve una URL.

Creación del video: Se llama al endpoint /v1/characters con la URL del audio y de la imagen, junto con otros parámetros (en este ejemplo, se usa "1:1" para el aspect ratio). La respuesta devuelve un jobId.

Polling: Se realiza un bucle que consulta el endpoint /v1/projects/{jobId} hasta que el estado sea "Completed" o se detecte un fallo.

Descarga: Una vez que el video está listo, se extrae la URL y se descarga el archivo.

Asincronía:
Dado que la generación del video no es instantánea, el script implementa un "polling" cada 5 segundos. Puedes ajustar ese intervalo según tus necesidades.

Este ejemplo intenta emular, en batch, el proceso que en los ejemplos de ElevenLabs se hacía de forma más directa, adaptándolo a la naturaleza asíncrona de la generación de video de Hedra.

Si te surge alguna duda o necesitas modificar algún detalle, ¡no dudes en decírmelo!

Dijiste:

Ok, mira, tengo la API Key de Hedra, que es esta:
sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2

La imagen que quiero poner en todos los audios la tengo aqui:
C:\alinamedico0000.png

Y los audios que quiero darle estan en esta carpeta:
C:\audios

Como seria el archivo Bat?

Razonado durante 52 segundos

A continuación te dejo un ejemplo de archivo BAT que procesa en lote todos los audios (en formato WAV) de la carpeta C:\audios usando la misma imagen (C:\alinamedico0000.png) y la API de Hedra. Este script utiliza curl para hacer las peticiones HTTP y jq para parsear las respuestas JSON. Asegúrate de tener ambas herramientas instaladas y en el PATH.

Copia el siguiente código en un archivo .bat (por ejemplo, generar_videos.bat):

bat

Copiar

@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración (reemplaza según corresponda)
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM 2.2 Iniciar la generación del video
set "PAYLOAD={\"avatarImage\": \"%IMAGE_URL%\", \"audioSource\": \"audio\", \"voiceUrl\": \"%AUDIO_URL%\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Cómo funciona el script

Configuración:

Se definen variables con la API Key, el BASE_URL, la ruta de la imagen, la carpeta de audios y la carpeta de salida para los videos.

Subida de la imagen:

Se envía la imagen a POST /v1/portrait y se extrae la URL devuelta (almacenada en IMAGE_URL). Esta URL se usará para todos los videos.

Procesamiento por lotes:

Se itera sobre todos los archivos *.wav en la carpeta C:\audios.

Por cada audio se llama a la subrutina :process_audio.

Subrutina :process_audio:

Sube el audio a POST /v1/audio y extrae la URL (AUDIO_URL).

Llama a POST /v1/characters con un payload JSON que incluye avatarImage (la URL de la imagen), audioSource (fijado a "audio"), voiceUrl (la URL del audio) y aspectRatio ("1:1"). Se extrae el jobId.

Entra en un bucle de polling que consulta el estado del trabajo (con GET en /v1/projects/{jobId}) cada 5 segundos hasta que el estado sea "Completed" o "Failed".

Una vez completado, se extrae videoUrl y se descarga el video a la carpeta de salida, nombrándolo igual que el archivo de audio (con extensión .mp4).

Finalización:

Se procesa cada audio y, al final, se muestra un mensaje de finalización.

Notas importantes

Formatos:
Asegúrate de que tus archivos de audio sean compatibles (el ejemplo asume formato WAV). Si son MP3, podrías probar directamente o convertirlos con ffmpeg.

Herramientas:
Este script requiere que curl y jq estén instalados y disponibles en la variable de entorno PATH.

Pruebas:
Te recomiendo probar primero con un único archivo para verificar que la API responde como esperas.

Si surge cualquier duda o necesitas ajustar algún detalle, ¡aquí estoy para ayudarte!

Dijiste:

Los audios los tengo en mp3, podriamos probar con mp3? Es que https://elevenlabs.io/app/speech-synthesis/text-to-speech me los deja en mp3

Razonado durante unos segundos

Aquí te dejo la versión del archivo BAT adaptado para procesar archivos MP3 en lugar de WAV. La lógica es la misma, solo se cambia la extensión de búsqueda para los audios:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración: Reemplaza según corresponda
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio MP3 en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.mp3") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM 2.2 Iniciar la generación del video
set "PAYLOAD={\"avatarImage\": \"%IMAGE_URL%\", \"audioSource\": \"audio\", \"voiceUrl\": \"%AUDIO_URL%\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Detalles del script:

Configuración:

La variable AUDIOS_DIR apunta a la carpeta con tus archivos MP3.

La variable IMAGE_PATH contiene la ruta de la imagen que se usará en todos los videos.

Se usa la API Key proporcionada y la URL base de la API.

Subida de imagen:

Se realiza una única vez y se guarda la URL resultante en la variable IMAGE_URL.

Procesamiento por lotes:

Se itera sobre todos los archivos con extensión .mp3 en la carpeta indicada.

Por cada audio, se ejecuta la subrutina :process_audio.

Subrutina :process_audio:

Se sube el audio a POST /v1/audio y se extrae la URL (AUDIO_URL).

Se inicia la generación del video llamando a POST /v1/characters con el JSON que incluye la URL de la imagen, la del audio y el aspecto (aspectRatio "1:1"). Se extrae el jobId.

Se implementa un bucle de polling que consulta el estado del trabajo (GET a /v1/projects/{jobId}) cada 5 segundos hasta que el estado sea "Completed" o "Failed".

Una vez completado, se extrae la URL del video (videoUrl) y se descarga a la carpeta de salida, utilizando el nombre base del audio y la extensión .mp4.

Requisitos:

curl: Debe estar instalado y en el PATH.

jq: Necesario para parsear las respuestas JSON; también debe estar instalado y en el PATH.

Prueba este script y, si la API de Hedra acepta archivos MP3 sin inconvenientes, debería funcionar correctamente. Si tienes alguna duda o necesitas ajustar algún detalle, ¡avísame!

Dijiste:

Debo de crear el directorio o carpeta:
C:\videos

Razonado durante unos segundos

No es estrictamente necesario crearlo manualmente, ya que el script incluye una línea que crea la carpeta "C:\videos" si no existe. Sin embargo, si prefieres hacerlo de antemano o tienes algún problema de permisos, puedes crearla manualmente.

Dijiste:

Ok, voy a probar, gracias Chat!!! Ya le ingrese a hedra 10 US$ para probar, o sea, ya tengo creditos para hacer las pruebas... Probando!!!

Razonado durante 7 segundos

¡Genial, Ana! Me alegra que ya tengas créditos para probar. Mucha suerte con las pruebas y no dudes en avisarme si necesitas ajustar algo o surge alguna duda durante el proceso. ¡Éxito!

Dijiste:

Me dice esto cuando ejecuto el bat:

"jq" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Imagen subida, URL:

Razonado durante 14 segundos

El mensaje de error indica que el comando "jq" no está disponible en tu sistema. "jq" es una herramienta de línea de comandos para procesar JSON, y es necesaria en este script para extraer datos de las respuestas de la API.

Para solucionarlo, sigue estos pasos:

Descargar jq para Windows:
Puedes descargar jq desde su página oficial de descargas. Asegúrate de elegir la versión para Windows (por ejemplo, jq-win64.exe).

Agregar jq al PATH:
Una vez descargado, renombra el archivo a jq.exe (si es necesario) y colócalo en una carpeta que esté en tu variable de entorno PATH (como C:\Windows\System32) o en una carpeta de tu preferencia y luego añade esa carpeta al PATH.

Para agregar una carpeta al PATH en Windows, busca "Editar las variables de entorno del sistema" en el Panel de Control, haz clic en "Variables de entorno", selecciona la variable "Path" en "Variables del sistema" y añade la ruta donde colocaste jq.exe.

Verificar la instalación:
Abre una nueva ventana del símbolo del sistema (cmd) y escribe:

css

Copiar

jq --version

Si se muestra la versión, significa que se instaló correctamente.

Con jq instalado y accesible, el script debería funcionar sin mostrar ese error. ¡Prueba de nuevo y avísame si tienes alguna otra duda!

Dijiste:

Ok, ya instale el jq, ahora el bat me dice todo esto - le puse 4 audios pequeños para hacer las pruebas -:
/////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/e04efd75-b83c-4b12-8c6e-41957f92533a.jpg

===========================================
Procesando audio: C:\audios\audio_1935.mp3
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: 86307471-83cb-4faf-8945-ba45f117f8b5
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1935.mp3.
Proceso finalizado para C:\audios\audio_1935.mp3.

===========================================
Procesando audio: C:\audios\audio_1936.mp3
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: dc9acdb7-5d4e-4668-966d-bf84f39af556
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1936.mp3.
Proceso finalizado para C:\audios\audio_1936.mp3.

===========================================
Procesando audio: C:\audios\audio_1937.mp3
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: c61db6ad-4921-438e-a58d-6098fab9a271
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1937.mp3.
Proceso finalizado para C:\audios\audio_1937.mp3.

===========================================
Procesando audio: C:\audios\audio_1938.mp3
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: 373dfd85-0178-4abf-b81e-c4f6bf075a5e
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1938.mp3.
Proceso finalizado para C:\audios\audio_1938.mp3.

===========================================
Procesando audio: C:\audios\audio_1939.mp3
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: 355a5f48-f0a6-4875-b404-bd9ff9328dc2
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1939.mp3.
Proceso finalizado para C:\audios\audio_1939.mp3.

Todos los audios procesados.
Presione una tecla para continuar . . .
////////////////////

Razonado durante 14 segundos

El mensaje "Audio subido, URL: null" indica que, aunque se realizó la llamada a la API para subir el audio, la respuesta no contiene una URL válida, lo que provoca que la generación del video falle.

Es muy probable que la API de Hedra espere archivos en formato WAV, tal como se indica en el ejemplo de GitHub (se usa audio.wav). Al subir un archivo MP3, la API podría no procesarlo correctamente y por eso devuelve null.

Te recomiendo probar lo siguiente:

Convertir MP3 a WAV:
Utiliza una herramienta como ffmpeg para convertir tus archivos MP3 a WAV antes de subirlos. Esto lo puedes automatizar en un script batch o hacerlo de forma previa.

Prueba con un archivo WAV:
Verifica con un archivo WAV que se genere correctamente, para confirmar que el proceso funciona bien con el formato esperado.

Si necesitas ayuda para incorporar la conversión de MP3 a WAV dentro de un archivo batch, avísame y te puedo ayudar a elaborar ese script. ¡Suerte con las pruebas!

Dijiste:

Dime, por favoir Chat, un codigo ffmpeg para convertir los audios en C:\ audios de mp3 a wav

Razonado durante 6 segundos

Aquí tienes un ejemplo de código batch que usa ffmpeg para convertir todos los archivos MP3 en la carpeta C:\audios a archivos WAV en la misma carpeta:

bat

Copiar

@echo off
echo Convirtiendo archivos MP3 a WAV en C:\audios...
for %%F in ("C:\audios\*.mp3") do (
echo Convirtiendo %%F a %%~nF.wav...
ffmpeg -y -i "%%F" "C:\audios\%%~nF.wav"
)
echo Conversión completada.
pause

Explicación:

for %%F in ("C:\audios*.mp3") do (...)
Este bucle recorre todos los archivos con extensión .mp3 en la carpeta C:\audios.

ffmpeg -y -i "%%F" "C:\audios%%~nF.wav"

-y: Sobrescribe automáticamente el archivo de salida si ya existe.

-i "%%F": Especifica el archivo de entrada (cada MP3).

"C:\audios%%~nF.wav": Define la ruta y el nombre del archivo de salida, usando el mismo nombre base pero con extensión .wav.

Guarda este código en un archivo .bat y ejecútalo para realizar la conversión. ¡Suerte!

Dijiste:

Ok, el archiv bat que me distes para convertir los audios a videos en hedra tiene estas lineas de codigo:
/////////////////////////////
@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración: Reemplaza según corresponda
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (jq -r ".url" image_response.json) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio MP3 en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.mp3") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (jq -r ".url" audio_response.json) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM 2.2 Iniciar la generación del video
set "PAYLOAD={\"avatarImage\": \"%IMAGE_URL%\", \"audioSource\": \"audio\", \"voiceUrl\": \"%AUDIO_URL%\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (jq -r ".jobId" video_response.json) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (jq -r ".status" project_status.json) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (jq -r ".videoUrl" project_status.json) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b
/////////////////////

Y al ejecutarlo - ya deje solo archivos wav en el directorio C:\audios -, me sale esto:

////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/0f3208a1-fc1b-4f49-b911-10c95fa997be.jpg

Todos los audios procesados.
Presione una tecla para continuar . . .
////////////////////

Pero no ha creado ningun video, y ha sido inmediata la respuesta, no ha durado ni 1 segundo...

Razonado durante 8 segundos

El problema es que el script está buscando archivos con extensión *.mp3 en la carpeta C:\audios, pero ahora tienes archivos WAV. Por eso el bucle no encuentra ningún archivo y no procesa ningún audio.

Para solucionarlo, simplemente cambia la línea del bucle for para que busque archivos *.wav. Por ejemplo, modifica:

bat

Copiar

for %%F in ("%AUDIOS_DIR%\*.mp3") do (
call :process_audio "%%F"
)

por:

bat

Copiar

for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)

Con ese cambio, el script encontrará y procesará tus archivos WAV. ¡Prueba ese ajuste y dime si funciona correctamente!

Dijiste:

Ok, ejecutando el bat, con el codigo cambiado a archivos de audio wav, me dice:

/////////////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/851a7eeb-a3f4-470b-b44a-993e6c533db0.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: f5f784f8-948c-4d16-afcf-44a1081e5042
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1937.wav.
Proceso finalizado para C:\audios\audio_1937.wav.

===========================================
Procesando audio: C:\audios\audio_1938.wav
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: e7029053-a70c-418a-ba2b-35a68730ad36
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1938.wav.
Proceso finalizado para C:\audios\audio_1938.wav.

===========================================
Procesando audio: C:\audios\audio_1939.wav
Audio subido, URL: null
Iniciando generaci├│n del video...
Job ID: b01c309f-3a6c-4a10-af40-dcffe2d37de8
Esperando a que el video se genere...
Estado: Failed
La generaci├│n del video ha fallado para C:\audios\audio_1939.wav.
Proceso finalizado para C:\audios\audio_1939.wav.

Todos los audios procesados.
Presione una tecla para continuar . . .
//////////////////////

Razonado durante 32 segundos

El hecho de que la respuesta del endpoint de audio devuelva una URL nula indica que la carga del audio no se está procesando correctamente. Esto puede deberse a que la API espera que se envíe el archivo con un tipo de contenido específico (por ejemplo, audio/wav) y, al usar simplemente -F "file=@%AUDIO_FILE%", es posible que no se esté forzando ese tipo.

Para solucionarlo, intenta modificar la línea que sube el audio para forzar el tipo de contenido. Es decir, cambia esta línea:

bat

Copiar

curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%" "%BASE_URL%/v1/audio" -o audio_response.json

por esta:

bat

Copiar

curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json

Esto indicará a curl que envíe el archivo con el Content-Type "audio/wav". Así, la API podría reconocer correctamente el archivo y procesarlo.

Además, te recomiendo abrir el archivo audio_response.json (por ejemplo, abriéndolo en un editor de texto) para ver si la API está devolviendo algún mensaje de error o validación que te indique el problema exacto.

Intenta este cambio y vuelve a probar. Si sigues teniendo problemas, podemos revisar más detalles de la respuesta o investigar si existen otros requisitos en la API para los archivos de audio. ¡Avísame cómo te va!

Dijiste:

Probando, gracias Chat, al final llegaremos a al solucion, estoy seguro de que lo conseguiras...

Razonado durante un par de segundos

¡Claro, Ana! Estoy aquí para ayudarte en lo que necesites. Avísame cualquier novedad o si surge otro detalle en el proceso. ¡Seguimos en contacto y vamos a lograrlo!

Dijiste:

Ahora con este codigo en el archivo bat - creo que lso cambios que em has dado los he hecho bien -:
/////////////////////////
@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración: Reemplaza según corresponda
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (jq -r ".url" image_response.json) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio MP3 en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (jq -r ".url" audio_response.json) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM 2.2 Iniciar la generación del video
set "PAYLOAD={\"avatarImage\": \"%IMAGE_URL%\", \"audioSource\": \"audio\", \"voiceUrl\": \"%AUDIO_URL%\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (jq -r ".jobId" video_response.json) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (jq -r ".status" project_status.json) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (jq -r ".videoUrl" project_status.json) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b
/////////////////////////

Me dice esto el temrinal:
/////////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/6d990a86-3fd6-4607-973d-049c2e9b761e.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/d51b44dc-d04d-4b5e-88df-d02e41faa243/audio.wav?AWSAccessKeyId=ASIA5B2OER27JZFNPTDV
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
curl: (2) no URL specified
curl: try 'curl --help' for more information
jq: error: Could not open file video_response.json: No such file or directory
Job ID:
Esperando a que el video se genere...
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
Estado:
/////////////////////////

Y asi se queda... Lo he cortado por darme variso mensajes de error...

Razonado durante 29 segundos

El problema es que la URL del audio devuelta por la API incluye caracteres especiales (como &), que en el entorno batch se interpretan como separadores de comandos. Esto hace que al construir el payload JSON se rompa la cadena, y por ello la llamada al endpoint de generación de video falla.

Para solucionarlo, debemos "escapar" los caracteres & (y otros que puedan causar problemas) en la variable que contiene la URL del audio. Una forma de hacerlo es crear una variable auxiliar en la que se reemplacen los & por ^&, para que el intérprete de comandos no los interprete.

A continuación, te muestro el bloque modificado de la subrutina :process_audio con las modificaciones necesarias:

bat

Copiar

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM Escapar los caracteres especiales en la URL (por ejemplo, &)
set "AUDIO_URL_ESCAPED=!AUDIO_URL:&=^&!"

REM 2.2 Iniciar la generación del video
REM Usamos delayed expansion para que se reemplacen correctamente las variables
set "PAYLOAD={\"avatarImage\": \"!IMAGE_URL!\", \"audioSource\": \"audio\", \"voiceUrl\": \"!AUDIO_URL_ESCAPED!\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Explicación:

Escapar la URL:
Después de obtener la URL del audio en la variable AUDIO_URL, se crea AUDIO_URL_ESCAPED reemplazando cada & por ^&:

arduino

Copiar

set "AUDIO_URL_ESCAPED=!AUDIO_URL:&=^&!"

Esto evita que el intérprete trate el carácter & como separador de comandos.

Construcción del JSON:
Se utiliza delayed expansion (!VARIABLE!) para incluir las variables IMAGE_URL y AUDIO_URL_ESCAPED dentro del JSON que se envía al endpoint /v1/characters.

Con estas modificaciones, la línea que inicia la generación del video debería recibir una URL válida (con los caracteres especiales correctamente escapados) y la API debería poder procesarla sin que se corte la línea de comandos.

Prueba el script modificado y verifica que se inicie correctamente el job de generación de video. Si todo funciona, el polling debería eventualmente detectar un estado "Completed" y descargar el video.

¡Avísame si necesitas más ayuda o si surgen nuevos mensajes de error!

Dijiste:

No me podrias dar todo el bat con los nuevos cambios, para que yo no cometa algun error al hacer lso cambios?

Razonado durante 17 segundos

Aquí tienes el archivo BAT completo con las modificaciones para escapar los caracteres especiales en la URL del audio:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración: Reemplaza según corresponda
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio WAV en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio (forzando el Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM Escapar caracteres especiales (por ejemplo, &) en la URL del audio
set "AUDIO_URL_ESCAPED=!AUDIO_URL:&=^&!"

REM 2.2 Iniciar la generación del video
set "PAYLOAD={\"avatarImage\": \"!IMAGE_URL!\", \"audioSource\": \"audio\", \"voiceUrl\": \"!AUDIO_URL_ESCAPED!\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero con extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Notas importantes:

Formato de audio:
El script asume que los archivos están en formato WAV y se buscan en la carpeta C:\audios. Si deseas trabajar con otro formato, asegúrate de ajustar tanto la extensión en el bucle for como el tipo en la línea del curl.

Herramientas necesarias:
Asegúrate de tener instalados y en el PATH:

curl

jq

Escapado de caracteres:
La línea
set "AUDIO_URL_ESCAPED=!AUDIO_URL:&=^&!"
se encarga de reemplazar los caracteres & por ^& para evitar que el intérprete de comandos los trate como separadores.

Con este archivo BAT completo, prueba a ejecutarlo y verifica si el proceso de generación de video se inicia correctamente. Si surgen nuevos errores o necesitas más ajustes, ¡avísame!

Dijiste:

Ok, me dice esto el terminal Chat, lo he parado por algun mensaje de error que dice:
////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/cb61dc39-c682-4f25-8a43-aaac41758264.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/d6fc85d2-1303-4698-a4c3-be4735fb057a/audio.wav?AWSAccessKeyId=ASIA5B2OER27E55OIPTQ
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 3096c28a-33c4-4844-962e-f33778270e80
Esperando a que el video se genere...
Estado: Queued
Estado: Queued
Estado: Queued
//////////////////

Razonado durante 50 segundos

Prueba el siguiente archivo BAT completo, donde se usa el comando "call set" para escapar correctamente los caracteres especiales en la URL del audio:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración: Reemplaza según corresponda
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio WAV en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio (forzando el Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM Escapar caracteres especiales en la URL del audio (por ejemplo, &)
call set "AUDIO_URL_ESCAPED=%%AUDIO_URL:&=^&%%"
echo Audio URL escapada: %AUDIO_URL_ESCAPED%

REM 2.2 Iniciar la generación del video
set "PAYLOAD={\"avatarImage\": \"!IMAGE_URL!\", \"audioSource\": \"audio\", \"voiceUrl\": \"!AUDIO_URL_ESCAPED!\", \"aspectRatio\": \"1:1\"}"
echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d "!PAYLOAD!" "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero con extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Explicación:

Subida de la imagen: Se sube una única vez y se guarda su URL en IMAGE_URL.

Procesamiento por lotes: Se recorre cada archivo WAV en la carpeta C:\audios.

Subida del audio: Se forza el Content-Type a audio/wav para que la API lo procese correctamente.

Escapado de la URL del audio:
La línea

sql

Copiar

call set "AUDIO_URL_ESCAPED=%%AUDIO_URL:&=^&%%"

reemplaza todas las ocurrencias de & en AUDIO_URL por ^&, evitando que el intérprete de comandos las interprete como separadores.

Generación y polling: Se envía el JSON con los parámetros (incluyendo la URL escapada) para iniciar la generación del video y luego se espera (cada 5 segundos) hasta que el estado sea "Completed" o "Failed".

Prueba este script y observa si se inicia correctamente el proceso de generación del video sin que se rompa la URL. ¡Cualquier novedad me avisas!

Dijiste:

Probando

Razonado durante unos segundos

Perfecto, avísame cómo te va o si encuentras algún nuevo error para poder ayudarte a ajustar lo que sea necesario. ¡Estoy aquí para lo que necesites!

Dijiste:

Me dice esto el terminal:
//////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/ed046614-ff01-4275-8d1c-5e4e7f70478d.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/e12fca90-977f-4d58-a04c-a7289843cfa0/audio.wav?AWSAccessKeyId=ASIA5B2OER27EIWPUY3X
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/e12fca90-977f-4d58-a04c-a7289843cfa0/audio.wav?AWSAccessKeyId=ASIA5B2OER27EIWPUY3X^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: feed5006-f755-4686-97e9-fb9d5e028d16
Esperando a que el video se genere...
Estado: Queued
Estado: Queued
///////////////////

No he esperado, quizas deberia de esperar a ver si crea algun video a pesar de que expires parece no gustarle...

En un momento me dijistes:
////////////////
Asegúrate de tener instalados y en el PATH:
curl
jq
////////////////

Como chequeo que los tego bien? No sea que por ahi venga el problema...

Razonado durante un par de segundos

Para comprobar que tienes curl y jq instalados y en tu PATH, abre una ventana del símbolo del sistema (cmd) y ejecuta estos comandos:

Para curl:

css

Copiar

curl --version

Esto debería mostrar la versión de curl y algunas opciones disponibles.

Para jq:

css

Copiar

jq --version

Deberías ver la versión de jq instalada.

Si alguno de estos comandos no muestra información (o te da un mensaje de error indicando que no se reconoce), es probable que la herramienta no esté instalada o que la carpeta donde se encuentra no esté añadida a la variable de entorno PATH. En ese caso, tendrás que instalarla o ajustar el PATH según corresponda.

Dijiste:

Me dice esto de curl:
/////////////////////
PS C:\Users\Administrador> curl --version
curl 8.8.0 (Windows) libcurl/8.8.0 Schannel zlib/1.3 WinIDN
Release-Date: 2024-05-22
Protocols: dict file ftp ftps http https imap imaps ipfs ipns mqtt pop3 pop3s smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM SPNEGO SSL SSPI threadsafe Unicode UnixSockets
PS C:\Users\Administrador>
//////////////////

Y me dice esto de jq:
////////////////////
PS C:\Users\Administrador> jq --version
jq-1.7.1
PS C:\Users\Administrador>
////////////////////

Parece estar todo bien en esto de curl y jq

Razonado durante 33 segundos

A continuación te propongo una versión del BAT que evita construir el JSON directamente en la línea de comandos (lo que ocasiona problemas con los caracteres especiales en la URL del audio) y, en su lugar, escribe el payload en un archivo temporal que luego se envía a curl. Así no tendrás que preocuparte por escapar manualmente los caracteres como &, ya que el contenido se leerá desde el archivo.

Copia y pega el siguiente código en tu archivo BAT:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

REM ================================
REM Configuración: Reemplaza según corresponda
REM ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

REM Crear carpeta de salida si no existe
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

REM ================================
REM 1. Subir la imagen (única para todos los videos)
REM ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set IMAGE_URL=%%i
echo Imagen subida, URL: %IMAGE_URL%
echo.

REM ================================
REM 2. Procesar cada audio WAV en la carpeta
REM ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
REM %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

REM 2.1 Subir el audio (forzando el Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set AUDIO_URL=%%a
echo Audio subido, URL: %AUDIO_URL%

REM 2.2 Escribir el payload JSON a un archivo temporal para evitar problemas con caracteres especiales
(
echo {\"avatarImage\": \"!IMAGE_URL!\",
echo \"audioSource\": \"audio\",
echo \"voiceUrl\": \"!AUDIO_URL!\",
echo \"aspectRatio\": \"1:1\"}
) > payload.json

echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d @payload.json "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set JOB_ID=%%j
echo Job ID: %JOB_ID%

REM 2.3 Hacer polling para esperar a que el video se genere
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set STATUS=%%s
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set VIDEO_URL=%%v
echo Video completado, URL: %VIDEO_URL%
REM Se guarda el video con el mismo nombre base que el audio, pero con extensión .mp4
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Cómo funciona este script:

Subida de imagen:
Se sube la imagen y se guarda la URL en la variable IMAGE_URL.

Procesamiento por lotes:
Se recorre cada archivo WAV en la carpeta C:\audios y se llama a la subrutina :process_audio para cada uno.

Subida del audio:
Se sube el archivo de audio (forzando el Content-Type a audio/wav) y se extrae la URL resultante en AUDIO_URL.

Creación del payload:
En vez de construir el JSON directamente en la línea de comandos, se escribe a un archivo llamado payload.json usando paréntesis. Esto evita problemas con caracteres especiales en la URL.

Generación y polling:
Se envía el archivo payload.json a la API para iniciar la generación del video, se obtiene el jobId y luego se consulta el estado del job cada 5 segundos hasta que se complete o falle.

Descarga del video:
Una vez que el estado es "Completed", se extrae la URL del video y se descarga en la carpeta de salida, usando el mismo nombre base que el audio (con extensión .mp4).

Prueba este script; de este modo el payload se envía desde el archivo y debería evitar los errores que estabas viendo. Avísame cómo te va o si necesitas más ajustes.

Dijiste:

Ahora dice esto el terminal:
///////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/91ba15ac-3ba3-422b-949a-6837c3854d73.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/ded88d11-0758-469b-9539-1d942053649f/audio.wav?AWSAccessKeyId=ASIA5B2OER27JHNVKPXE
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: null
Esperando a que el video se genere...
Estado: null
Estado: null
Estado: null
///////////////////////

Lo he cortado por los mensajes de error...

Razonado durante 1m 21s

Prueba el siguiente archivo BAT completo, que usa un método para "escapar" los ampersands en la URL del audio antes de escribir el payload en un archivo. Este método utiliza el comando CALL SET para reemplazar cada & por ^& y luego genera el archivo payload.json de forma sencilla:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

:: ================================
:: Configuración: Reemplaza según corresponda
:: ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

:: ================================
:: 1. Subir la imagen (única para todos los videos)
:: ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set "IMAGE_URL=%%i"
echo Imagen subida, URL: %IMAGE_URL%
echo.

:: ================================
:: 2. Procesar cada audio WAV en la carpeta
:: ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
:: %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

:: 2.1 Subir el audio (forzando el Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set "AUDIO_URL=%%a"
echo Audio subido, URL: %AUDIO_URL%

:: Escapar ampersands en la URL del audio
call set "AUDIO_URL_ESCAPED=%AUDIO_URL:&=^&%"
echo Audio URL escapada: %AUDIO_URL_ESCAPED%

:: 2.2 Crear el payload JSON en un archivo (payload.json)
:: Usamos una sola línea para evitar problemas con saltos de línea
echo {"avatarImage": "%IMAGE_URL%", "audioSource": "audio", "voiceUrl": "%AUDIO_URL_ESCAPED%", "aspectRatio": "1:1"} > payload.json

echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d @payload.json "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set "JOB_ID=%%j"
echo Job ID: %JOB_ID%

:: 2.3 Polling para esperar a que se genere el video
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set "STATUS=%%s"
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set "VIDEO_URL=%%v"
echo Video completado, URL: %VIDEO_URL%
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Explicación de lo importante:

Subida del audio y extracción de la URL:
El audio se sube forzando el Content-Type a audio/wav. Luego se extrae la URL devuelta en la variable AUDIO_URL.

Escapado de ampersands:
La línea

sql

Copiar

call set "AUDIO_URL_ESCAPED=%AUDIO_URL:&=^&%"

reemplaza cada & en la URL por ^&, de forma que cuando se escriba el payload, los ampersands no sean interpretados como separadores de comando.

Creación del payload en un archivo:
Se escribe el JSON en una sola línea en payload.json. Así evitamos que el intérprete de comandos divida la cadena por los caracteres especiales.

Generación, polling y descarga:
Se envía el payload al endpoint de generación de video. Luego, se hace polling cada 5 segundos hasta que el estado del proyecto sea "Completed" o "Failed", y se descarga el video si se completa.

Verifica que tus archivos de audio estén en formato WAV en la carpeta C:\audios. Si se genera el job correctamente, deberías ver mensajes de estado (por ejemplo, "Queued", "InProgress" y eventualmente "Completed").

Prueba este script y dime si el job se inicia sin mostrar errores por los ampersands y si luego llega a completarse. ¡Estoy aquí para seguir ayudándote!

Dijiste:

Ok chat, ahora, aunque da errores el codigo, pero si ha creado los 3 videos, los audios que el he puesto son pequeños, pero si ha creado los videos aunque haya dado algunos mensajes de error...

Te paso lo que ha dicho el terminal:
///////////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/18478ee4-fc5c-4a60-95fb-8b12ac5d846d.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/c8af8ed0-cca1-4558-b1c5-64e8f2291c55/audio.wav?AWSAccessKeyId=ASIA5B2OER27IAZHBSQU
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/c8af8ed0-cca1-4558-b1c5-64e8f2291c55/audio.wav?AWSAccessKeyId=ASIA5B2OER27IAZHBSQU^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 2d2d16c9-032a-4c12-8c29-d8acf3a7098b
Esperando a que el video se genere...
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/2ad99af2-000e-437f-99d1-06c7ea8d4cfd.mp4?AWSAccessKeyId=ASIA5B2OER27JXVZDUK6
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1937.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1937.wav.

===========================================
Procesando audio: C:\audios\audio_1938.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/5a6e35af-4455-477a-b767-a9de20460614/audio.wav?AWSAccessKeyId=ASIA5B2OER27ARWV2OUI
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/5a6e35af-4455-477a-b767-a9de20460614/audio.wav?AWSAccessKeyId=ASIA5B2OER27ARWV2OUI^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 1c94b5cd-aeab-4aff-a60d-79ec04c3e838
Esperando a que el video se genere...
Estado: InProgress
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/2f6749c0-760b-467a-9f47-8942e9aec671.mp4?AWSAccessKeyId=ASIA5B2OER27D2IUL4XO
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1938.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1938.wav.

===========================================
Procesando audio: C:\audios\audio_1939.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/85f95561-e7c6-4a87-aa04-021e31667fef/audio.wav?AWSAccessKeyId=ASIA5B2OER27C2ZVEVDR
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/85f95561-e7c6-4a87-aa04-021e31667fef/audio.wav?AWSAccessKeyId=ASIA5B2OER27C2ZVEVDR^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 3295581f-9d4a-4c2c-8c1f-db1480c947d3
Esperando a que el video se genere...
Estado: InProgress
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/22084ae0-0439-427e-bf20-512bc958bed9.mp4?AWSAccessKeyId=ASIA5B2OER27JZFNPTDV
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1939.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1939.wav.

Todos los audios procesados.
Presione una tecla para continuar . . .
///////////////////////////

Razonado durante 20 segundos

Los errores que ves (“Signature no se reconoce…”, “x-amz-security-token…”, “Expires…”) se deben a que la URL devuelta incluye parámetros de consulta (query string) con ampersands (&) y otros caracteres especiales. Aunque ya estamos tratando de escapar esos ampersands, el intérprete de comandos sigue “intentando” interpretarlos como comandos cuando se usan en un contexto (como al hacer echo) sin un manejo adecuado.

Lo bueno es que, a pesar de esos mensajes, el proceso finaliza correctamente y los videos se crean y descargan. Si quieres evitar ver esos mensajes, tienes varias opciones:

No mostrar (o suprimir) el contenido completo de la URL
Puedes comentar o eliminar la línea de echo que muestra la variable con la URL escapada.

Redirigir la salida de error a NUL
Podrías redirigir la salida de error (stderr) de la línea de echo a NUL para que no se muestren esos mensajes.

Te dejo una versión final del BAT que, además de utilizar el archivo payload.json para evitar problemas con el JSON, evita hacer echo de la URL escapada (lo que provoca que el intérprete intente ejecutar parte de ella):

bat

Copiar

@echo off
setlocal enabledelayedexpansion

:: ================================
:: Configuración: Reemplaza según corresponda
:: ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

:: ================================
:: 1. Subir la imagen (única para todos los videos)
:: ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set "IMAGE_URL=%%i"
echo Imagen subida, URL: %IMAGE_URL%
echo.

:: ================================
:: 2. Procesar cada audio WAV en la carpeta
:: ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
:: %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

:: 2.1 Subir el audio (forzando el Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set "AUDIO_URL=%%a"
echo Audio subido, URL: %AUDIO_URL%

:: Escapar ampersands en la URL del audio
call set "AUDIO_URL_ESCAPED=%AUDIO_URL:&=^&%"
:: Si prefieres no ver la URL escapada, puedes comentar la siguiente línea:
:: echo Audio URL escapada: %AUDIO_URL_ESCAPED%

:: 2.2 Crear el payload JSON en un archivo (payload.json)
(
echo {"avatarImage": "%IMAGE_URL%", "audioSource": "audio", "voiceUrl": "%AUDIO_URL_ESCAPED%", "aspectRatio": "1:1"}
) > payload.json

echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d @payload.json "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set "JOB_ID=%%j"
echo Job ID: %JOB_ID%

:: 2.3 Polling para esperar a que se genere el video
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set "STATUS=%%s"
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set "VIDEO_URL=%%v"
echo Video completado, URL: %VIDEO_URL%
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Comentarios:

Se ha comentado la línea que hace echo Audio URL escapada: ... para evitar que se muestren esos mensajes de error.

Los comandos que usan curl para enviar la URL están entre comillas, lo que ayuda a que el intérprete trate el contenido completo como una cadena.

Estos mensajes de error provienen del hecho de que el intérprete de Windows sigue intentando “ejecutar” partes de la URL que contienen ampersands, pero al no mostrarlos, ya no molestan en la salida.

Si los videos se crean y se descargan correctamente, esos mensajes son simplemente "ruido" y no afectan el funcionamiento.

Prueba esta versión y, si ya no ves los mensajes indeseados (o si te molestan, pero no afectan la funcionalidad) puedes considerarlo solucionado. ¡Estoy aquí para cualquier ajuste adicional que necesites!

Dijiste:

Probando Chat, pero ya estamos muy cerca!!!

Razonado durante 5 segundos

¡Perfecto, Ana! Me alegra que ya estemos muy cerca de la solución. Aunque veas esos mensajes de error, si los videos se generan y se descargan correctamente, significa que el proceso funciona.

Cuando estés lista para probar con audios más largos o si necesitas ajustar algún detalle adicional, no dudes en avisarme. ¡Sigue así y éxito en tus pruebas!

Dijiste:

Ok, sigue dando mensajes de error, pero creando bien los videos. aunque esta vez ha tardado bastante mas tiempo, quizas porr saturacion de la IA de Hedra, tendria quizas que pprobar con el codigo justo anterior si lo sigue haciendo rapido.

Te paso lo que dice el terminal:
//////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/18478ee4-fc5c-4a60-95fb-8b12ac5d846d.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/c8af8ed0-cca1-4558-b1c5-64e8f2291c55/audio.wav?AWSAccessKeyId=ASIA5B2OER27IAZHBSQU
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/c8af8ed0-cca1-4558-b1c5-64e8f2291c55/audio.wav?AWSAccessKeyId=ASIA5B2OER27IAZHBSQU^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 2d2d16c9-032a-4c12-8c29-d8acf3a7098b
Esperando a que el video se genere...
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/2ad99af2-000e-437f-99d1-06c7ea8d4cfd.mp4?AWSAccessKeyId=ASIA5B2OER27JXVZDUK6
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1937.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1937.wav.

===========================================
Procesando audio: C:\audios\audio_1938.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/5a6e35af-4455-477a-b767-a9de20460614/audio.wav?AWSAccessKeyId=ASIA5B2OER27ARWV2OUI
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/5a6e35af-4455-477a-b767-a9de20460614/audio.wav?AWSAccessKeyId=ASIA5B2OER27ARWV2OUI^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 1c94b5cd-aeab-4aff-a60d-79ec04c3e838
Esperando a que el video se genere...
Estado: InProgress
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/2f6749c0-760b-467a-9f47-8942e9aec671.mp4?AWSAccessKeyId=ASIA5B2OER27D2IUL4XO
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1938.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1938.wav.

===========================================
Procesando audio: C:\audios\audio_1939.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/85f95561-e7c6-4a87-aa04-021e31667fef/audio.wav?AWSAccessKeyId=ASIA5B2OER27C2ZVEVDR
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Audio URL escapada: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/85f95561-e7c6-4a87-aa04-021e31667fef/audio.wav?AWSAccessKeyId=ASIA5B2OER27C2ZVEVDR^
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 3295581f-9d4a-4c2c-8c1f-db1480c947d3
Esperando a que el video se genere...
Estado: InProgress
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/22084ae0-0439-427e-bf20-512bc958bed9.mp4?AWSAccessKeyId=ASIA5B2OER27JZFNPTDV
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1939.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1939.wav.

Todos los audios procesados.
Presione una tecla para continuar . . .
//////////////////

Razonado durante 50 segundos

Aquí tienes una versión final del archivo BAT que utiliza PowerShell para escribir el payload JSON de forma segura, de modo que no se interpongan los problemas de los ampersands y otros caracteres especiales en la URL del audio:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

:: ================================
:: Configuración: Reemplaza según corresponda
:: ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

:: ================================
:: 1. Subir la imagen (única para todos los videos)
:: ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set "IMAGE_URL=%%i"
echo Imagen subida, URL: %IMAGE_URL%
echo.

:: ================================
:: 2. Procesar cada audio WAV en la carpeta
:: ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
:: %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

:: 2.1 Subir el audio (forzando Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set "AUDIO_URL=%%a"
echo Audio subido, URL: %AUDIO_URL%

:: 2.2 Crear el payload JSON usando PowerShell para evitar problemas con caracteres especiales
powershell -NoProfile -Command "Set-Content -Path 'payload.json' -Value ('{\"avatarImage\": \"'+$env:IMAGE_URL+'\", \"audioSource\": \"audio\", \"voiceUrl\": \"'+$env:AUDIO_URL+'\", \"aspectRatio\": \"1:1\"}')"

echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d @payload.json "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set "JOB_ID=%%j"
echo Job ID: %JOB_ID%

:: 2.3 Hacer polling para esperar a que se genere el video
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set "STATUS=%%s"
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set "VIDEO_URL=%%v"
echo Video completado, URL: %VIDEO_URL%
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Notas importantes:

Subida de archivos:

La imagen se sube una sola vez y su URL se guarda en la variable IMAGE_URL.

Cada archivo de audio (en formato WAV) se sube y su URL se guarda en AUDIO_URL.

Generación del payload:
Se usa PowerShell para crear el archivo payload.json usando las variables de entorno (IMAGE_URL y AUDIO_URL), lo que evita problemas al imprimir directamente una cadena con caracteres especiales (como &).

Polling y descarga:
El script consulta cada 5 segundos el estado del job hasta que esté "Completed" (o "Failed") y, si se completa, descarga el video en la carpeta de salida.

Herramientas necesarias:
Asegúrate de tener curl y jq instalados y en el PATH, lo cual ya confirmaste.

Con este enfoque, los mensajes de error relacionados con "Signature", "x-amz-security-token" o "Expires" ya no deberían interferir (se seguirán mostrando en la salida del comando curl, pero no interrumpirán el proceso).

Prueba este script y, si los videos se crean y descargan correctamente, aunque se muestren esos mensajes, ya sabrás que el proceso funciona. Si necesitas suprimir la salida de error de curl (por ejemplo, redirigiendo stderr a NUL), se puede agregar la redirección 2>nul a las líneas de curl.

¡Suerte con las pruebas y avísame cualquier novedad o duda!

Dijiste:

Probando...

Razonado durante un segundo

Perfecto, Ana. Espero que esta versión funcione mejor para ti. Avísame cómo te va o si necesitas más ajustes. ¡Suerte con la prueba!

Dijiste:

Ok, aqui ha ido mas rapido - puede ser cosas de la saturacion de hedra, no lo se -, aunque sigue dando esos mensajes de error:

////////////////////////
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
////////////////////////

////////////////////////
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
////////////////////////

Como podriamos suprimirlos?

Eso si, igualmente que los 3 ultimos codigos del bat, los videos se crean correctamente...!!!

Dice esto el terminal:
/////////////////////
Subiendo imagen...
Imagen subida, URL: https://dream-product.s3.us-west-2.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/images/af13ac17-c135-4ace-963a-280dc746844c.jpg

===========================================
Procesando audio: C:\audios\audio_1937.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/3fdf9c11-e5d3-424e-969a-c7e392802bfb/audio.wav?AWSAccessKeyId=ASIA5B2OER27IAZHBSQU
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: a5833273-a127-411a-ac73-8bf112a2068b
Esperando a que el video se genere...
Estado: Queued
Estado: Queued
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/3e771669-3709-424c-84c7-1019152f66ce.mp4?AWSAccessKeyId=ASIA5B2OER27D2IUL4XO
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1937.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1937.wav.

===========================================
Procesando audio: C:\audios\audio_1938.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/0464da40-afb2-4653-96b9-8e4f63ce5e1b/audio.wav?AWSAccessKeyId=ASIA5B2OER27FPFTET2R
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 47d80a38-7722-467e-a77a-0835abbdaac9
Esperando a que el video se genere...
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/1b8cf116-3d32-4632-8b31-de3d8653a63d.mp4?AWSAccessKeyId=ASIA5B2OER27E55OIPTQ
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1938.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1938.wav.

===========================================
Procesando audio: C:\audios\audio_1939.wav
Audio subido, URL: https://dream-product.s3.amazonaws.com/projects/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/avatar-app/4737eaa4-9dee-48db-a604-8beb58da30a2/audio.wav?AWSAccessKeyId=ASIA5B2OER27IAZHBSQU
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Iniciando generaci├│n del video...
Job ID: 41977a14-446d-41b0-945c-fcc823d02128
Esperando a que el video se genere...
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: InProgress
Estado: Completed
Video completado, URL: https://dream-product.s3.amazonaws.com/outputs/users/b881f310-90e1-70e7-ab5b-72dfb12b888f/59d7013c-8715-4fa1-ad07-517258ef50cf.mp4?AWSAccessKeyId=ASIA5B2OER27JXVZDUK6
"Signature" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"x-amz-security-token" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
"Expires" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
Descargando video a C:\videos\audio_1939.mp4...
Video descargado.
Proceso finalizado para C:\audios\audio_1939.wav.

Todos los audios procesados.
Presione una tecla para continuar . . .
///////////////////////

Razonado durante 21 segundos

Aquí tienes una versión final del BAT con una modificación en la línea que escapa los ampersands, para redirigir su salida de error (stderr) a NUL y así suprimir esos mensajes:

bat

Copiar

@echo off
setlocal enabledelayedexpansion

:: ================================
:: Configuración: Reemplaza según corresponda
:: ================================
set API_KEY=sk_hedra-xJb1IKXtj-CjaBLiUb3_bX8IakQVyWBh7AO53QBAcU0qyFkAxnTmUGaTyXOrHcf2
set BASE_URL=https://mercury.dev.dream-ai.com/api
set IMAGE_PATH=C:\alinamedico0000.png
set AUDIOS_DIR=C:\audios
set OUTPUT_DIR=C:\videos

if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"

:: ================================
:: 1. Subir la imagen (única para todos los videos)
:: ================================
echo Subiendo imagen...
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%IMAGE_PATH%" "%BASE_URL%/v1/portrait" -o image_response.json
for /f "usebackq tokens=* delims=" %%i in (`jq -r ".url" image_response.json`) do set "IMAGE_URL=%%i"
echo Imagen subida, URL: %IMAGE_URL%
echo.

:: ================================
:: 2. Procesar cada audio WAV en la carpeta
:: ================================
for %%F in ("%AUDIOS_DIR%\*.wav") do (
call :process_audio "%%F"
)
echo Todos los audios procesados.
pause
endlocal
exit /b

:process_audio
:: %1 es el archivo de audio (incluye ruta)
set "AUDIO_FILE=%~1"
echo ===========================================
echo Procesando audio: %AUDIO_FILE%

:: 2.1 Subir el audio (forzando Content-Type a audio/wav)
curl -s -X POST -H "X-API-Key: %API_KEY%" -F "file=@%AUDIO_FILE%;type=audio/wav" "%BASE_URL%/v1/audio" -o audio_response.json
for /f "usebackq tokens=* delims=" %%a in (`jq -r ".url" audio_response.json`) do set "AUDIO_URL=%%a"
echo Audio subido, URL: %AUDIO_URL%

:: Escapar ampersands en la URL del audio y suprimir mensajes de error redirigiendo stderr a NUL
call set "AUDIO_URL_ESCAPED=%AUDIO_URL:&=^&%" 2>nul

:: (No se hace echo de AUDIO_URL_ESCAPED para evitar mostrar errores)

:: 2.2 Crear el payload JSON usando PowerShell para evitar problemas con caracteres especiales
powershell -NoProfile -Command "Set-Content -Path 'payload.json' -Value ('{\"avatarImage\": \"'+$env:IMAGE_URL+'\", \"audioSource\": \"audio\", \"voiceUrl\": \"'+$env:AUDIO_URL_ESCAPED+'\", \"aspectRatio\": \"1:1\"}')"

echo Iniciando generación del video...
curl -s -X POST -H "Content-Type: application/json" -H "X-API-Key: %API_KEY%" -d @payload.json "%BASE_URL%/v1/characters" -o video_response.json
for /f "usebackq tokens=* delims=" %%j in (`jq -r ".jobId" video_response.json`) do set "JOB_ID=%%j"
echo Job ID: %JOB_ID%

:: 2.3 Polling para esperar a que se genere el video
echo Esperando a que el video se genere...
:poll
curl -s -X GET -H "X-API-Key: %API_KEY%" "%BASE_URL%/v1/projects/%JOB_ID%" -o project_status.json
for /f "usebackq tokens=* delims=" %%s in (`jq -r ".status" project_status.json`) do set "STATUS=%%s"
echo Estado: %STATUS%
if /I "%STATUS%"=="Completed" goto download_video
if /I "%STATUS%"=="Failed" (
echo La generación del video ha fallado para %AUDIO_FILE%.
goto end_process
)
timeout /t 5 >nul
goto poll

:download_video
for /f "usebackq tokens=* delims=" %%v in (`jq -r ".videoUrl" project_status.json`) do set "VIDEO_URL=%%v"
echo Video completado, URL: %VIDEO_URL%
set "OUTPUT_VIDEO=%OUTPUT_DIR%\%~n1.mp4"
echo Descargando video a %OUTPUT_VIDEO%...
curl -L -s "%VIDEO_URL%" -o "%OUTPUT_VIDEO%"
echo Video descargado.
goto end_process

:end_process
echo Proceso finalizado para %AUDIO_FILE%.
echo.
exit /b

Explicación:

La línea que escapa la URL del audio ahora se ha modificado para incluir 2>nul:

sql

Copiar

call set "AUDIO_URL_ESCAPED=%AUDIO_URL:&=^&%" 2>nul

Esto redirige cualquier error generado por esa operación a NUL, evitando que se muestren en pantalla.

Se sigue usando PowerShell para generar el archivo payload.json, lo que ayuda a manejar correctamente los caracteres especiales.

Con esta modificación, deberías ver que, aunque aparezcan algunos mensajes de error en otros comandos (como los de curl al descargar el video), la salida ya no incluye los mensajes relacionados con "Signature", "x-amz-security-token" o "Expires" provenientes de la operación de escape.

Prueba este script y, si los videos se crean y descargan correctamente sin mostrar esos mensajes, ya estará todo listo. ¡Avísame si necesitas más ajustes o tienes alguna otra duda!

Dijiste:

Gracias Chat, probando, sin ti seria casi imposible hacer estos codigos!!!

Razonado durante 17 segundos

¡De nada, Ana! Me alegra mucho saber que te he podido ayudar. Si en el futuro necesitas ajustar más detalles o tienes cualquier otra duda, aquí estaré para echarte una mano. ¡Mucho éxito con tus proyectos!

Dijiste:

Sigue dando esos errores, pero bueno, lo importante es que crea perfectamente los videos...

Muchas gracias Chat, sin ti seria imposible casi, o tener un estudio muy profundo del el lenguaje de programacion del archivo BATCH.

Una pregunta, que lenguaje en especifico usas en el batch? Es javascript?

Razonado durante 5 segundos

El código del archivo BAT está escrito en el lenguaje de comandos de Windows, también conocido como Batch o CMD scripting. No es JavaScript; se basa en comandos propios de Windows (como set, echo, for, call, etc.) que se ejecutan mediante el intérprete de comandos (cmd.exe).

Dijiste:

Saludos chat, intentaremos otro dia el hacerlo con phyton, tengo que empezar ha hacer algo con Phyton... Y me imagino que con phyton no habra errores... Pero eso, otro dia!!!

Altamente agradecido Chat!!!

Razonado durante 11 segundos

¡Perfecto, Ana! Me alegra mucho haber podido ayudarte con el código batch. Python sin duda te dará más flexibilidad y probablemente un entorno más amigable para evitar esos errores de escapado y similares. Cuando decidas darle una oportunidad a Python, aquí estaré para apoyarte en lo que necesites.

¡Mucho éxito con tu proyecto y hasta la próxima!

Dijiste:

Una cuestion, en phyton se podra hacer un exe al que se le puedan pasar unos parametros como en VB6 y tros lenguajes, los command?

Es que mi idea es hacerme un simplisimo programa en VB6 al que yo le diga la imagen que quiero usar para hacer con la api de hedra, y pasarle tambien el directorio donde estan los audios, y que lo ejecute, asi puedo automatizar mucho mas el proceso de crear los videos de hedra con una API...

Tambien puedo hacerlo con el codigo batch, es sencillo... Asi con escoger una imagen, y con escoger un directorio, se el da a crear el batch, en el que se le ponen los datos de la imagen y de la carpeta de audios y de al carpeta de destino, y zas, asi es mucho mas facil...

Razonado durante 8 segundos

Sí, en Python es totalmente posible crear un ejecutable (.exe) que acepte parámetros de línea de comandos. Puedes usar la librería "argparse" (o incluso "sys.argv" para casos simples) para manejar los argumentos que le pases, como la imagen, el directorio de audios y el directorio de destino.

Además, una vez que tengas tu script en Python funcionando, puedes convertirlo a un .exe usando herramientas como PyInstaller, cx_Freeze, o py2exe. Esto te permitirá distribuir tu programa como un ejecutable independiente sin necesidad de tener Python instalado en cada máquina.

En resumen, podrías hacer algo así:

Desarrollas un script en Python que:

Use argparse para recoger parámetros (por ejemplo, la ruta de la imagen, la carpeta de audios y la carpeta de salida).

Realice la llamada a la API de Hedra y genere los videos según esos parámetros.

Luego, lo conviertes en un .exe usando PyInstaller (por ejemplo, ejecutando pyinstaller --onefile tu_script.py).

Esto te dará la flexibilidad de tener un programa similar al que mencionas en VB6 o el script batch, pero con la robustez y facilidad de manejo de Python. ¡Si necesitas ayuda cuando empieces con Python, aquí estaré para ayudarte!

o3-mini-high

Dijiste:

Ok, gracias de nuevo Chat!!!

Razonado durante un segundo

¡De nada, Ana! Cualquier cosa que necesites, aquí estaré. ¡Suerte con tus proyectos!

o3-mini-high

Esta conversación está archivada. Para continuar, desarchívala primero.

Desarchivar

?