2025-05-12
Retomo esto, lo primero que voy a hacer es valorar la imagen que tengo deployada, ver su API y ver si me funciona para lo que quiero, que probablemente si, pero como tengo el tema de la autenticación ahora vemos.

Vale, un tema que tengo es que el formato no es el mismo y tendria que modificar la llamada.
Sinceramente, no se hasta que punto me merece la pena hacer esto, creo que lo voy a enviar al BucketList, porque creo que me va a salir mas caro, de todas maneras, como esto es una dependencia de n8n Worklog, voy a seguir por ahi

2025-05-09
Empiezo por hacerle un informe de Gemini para hacer lo de WhisperX
https://gemini.google.com/app/e5975af0acfe07a7

lo que parece mas viable es tirar un Runpod.io, veo que tienen una docker image en sitio ya: https://www.runpod.io/console/explore/v7xyt1e57i

Oh boy, this might be even easier than I thought, as Runpod.io includes a Serverless option, but it's in Faster-Whisper, although we can look into creating a WhisperX version after the fact

How to create a pod: https://docs.runpod.io/serverless/workers/custom-worker

Idea: Monetize API

si la parte de atras es secreta, y protegida por API key, se podria hacer una app que sea solo wallet de una API?

En plan, uso el serverless de runpod y la app intermedia solo mueve llamadas, como template para sacar startups a porrillo.

Pues mira, lo puedes hacer, en esencia es lo que hace open router
Mira es un auth, que lo puedes hacer con nextauth, es un wallet, es una integración con Stripe.

Vale, aqui es donde lo dejo porque me voy a comer al el almacén (51 pavos)

Me he quedado en probarlo, he cambiado la URL y auth del Whisper node de Long Form Video Generator, pero no tira, me da un 401, y no se si es porque estoy usando el Bearer incorrecto o porque el Bearer directamente no tira, porque en otro nodo, que ahora mismo no recuerdo tuve que meter el Header hardcodeado, asi que creo que el bearer hace algo raro.

Total, lo dejo porque se ha acado el Time slot

URLs:
https://n8n.guiom.dev/workflow/L7xydtxoFKSGYT2l
Esto era para mirar lo de n8n con ffmpeg: https://www.runpod.io/console/deploy
API keys de Runpod.io: https://www.runpod.io/console/user/settings
Oh yeah, este chat con Claude es buena mierda: https://claude.ai/chat/1db6ab7f-4698-46c5-9650-dc3fc07d69db
https://claude.ai/chat/a0b9116a-12d3-471a-af08-2a56e4c62092

https://claude.ai/chat/a0b9116a-12d3-471a-af08-2a56e4c62092:


2025-04-11
Dice que para poder usar el ejemplo necesito una cuenta de podchasers, que no se que es (Es una base de datos de podcasts), lo que no esta mal, lo dejo en la recamara.

https://modal.com/docs/examples/whisper-transcriber
https://github.com/modal-labs/modal-examples/tree/main/06_gpu_and_ml/openai_whisper/pod_transcriber

Modal puede hostear SPA de acuerdo con este tutorial

para poder hacer eso use dos comandos:
Esto para lanzar lo que llama una ephemeral app

modal serve -m app.main

y esto para el deployment:

modal deploy -m app.main

Para poner contexto app es carpeta tiene main.py.

Main.py es el unico fichero que importa modal (No veo un requirements.txt? No lo hay porque si te fijas en las imagenes se declaran las dependencias)

y lo que veo es esto:

import modal

volume = modal.NetworkFileSystem.from_name(
    "dataset-cache-vol", create_if_missing=True
)

app_image = (
    modal.Image.debian_slim(python_version="3.10")
    .apt_install("git")
    .pip_install(
        "git+https://github.com/openai/whisper.git",
        "dacite",
        "jiwer",
        "ffmpeg-python",
        "gql[all]~=3.0.0a5",
        "pandas",
        "loguru==0.6.0",
        "torchaudio==2.1.0",
        "fastapi[standard]==0.115.4",
        "numpy<2",
    )
    .apt_install("ffmpeg")
    .pip_install("ffmpeg-python")
)
search_image = modal.Image.debian_slim(python_version="3.10").pip_install(
    "scikit-learn~=1.3.0",
    "tqdm~=4.46.0",
    "numpy~=1.23.3",
    "dacite",
)

app = modal.App(
    "whisper-pod-transcriber",
    image=app_image,
    secrets=[modal.Secret.from_name("podchaser")],
)

in_progress = modal.Dict.from_name(
    "pod-transcriber-in-progress", create_if_missing=True
)

@modal.asgi_app()
def fastapi_app():
    import fastapi.staticfiles

    from .api import web_app

    web_app.mount(
        "/", fastapi.staticfiles.StaticFiles(directory="/assets", html=True)
    )

    return web_app

@app.function(
    image=app_image,
    network_file_systems={config.CACHE_DIR: volume},
    cpu=2,
    timeout=400,
)
def transcribe_segment(
    start: float,
    end: float,
    audio_filepath: pathlib.Path,
    model: config.ModelSpec,
):
    import tempfile
    import time

    import ffmpeg
    import torch
    import whisper

    t0 = time.time()
    with tempfile.NamedTemporaryFile(suffix=".mp3") as f:
        (
            ffmpeg.input(str(audio_filepath))
            .filter("atrim", start=start, end=end)
            .output(f.name)
            .overwrite_output()
            .run(quiet=True)
        )

        use_gpu = torch.cuda.is_available()
        device = "cuda" if use_gpu else "cpu"
        model = whisper.load_model(
            model.name, device=device, download_root=config.MODEL_DIR
        )
        result = model.transcribe(f.name, language="en", fp16=use_gpu)  # type: ignore

    logger.info(
        f"Transcribed segment {start:.2f} to {end:.2f} ({end - start:.2f}s duration) in {time.time() - t0:.2f} seconds."
    )

    # Add back offsets.
    for segment in result["segments"]:
        segment["start"] += start
        segment["end"] += start

    return result

Y en referencia a docs eso significa estas url:
https://modal.com/docs/reference/modal.NetworkFileSystem
https://modal.com/docs/reference/modal.Image
https://modal.com/docs/reference/modal.App
https://modal.com/docs/reference/modal.Dict
https://modal.com/docs/reference/modal.asgi_app

Core Structure

Key Components

  1. Environment Setup:
    • Two custom Docker images are defined:
      • app_image: Main image with Whisper, ffmpeg, and other dependencies
      • search_image: Specialized image for search functionality
  2. Data Storage:
    • Uses Modal's NetworkFileSystem for persistent storage
    • Stores podcast metadata, audio files, and transcriptions
    • Uses Modal.Dict to track in-progress transcriptions
  3. Main Workflow:
    • search_podcast: Searches for podcasts by name
    • populate_podcast_metadata: Fetches metadata for a specific podcast
    • fetch_episodes: Retrieves episode data for a podcast
    • process_episode: Main function to download and process a podcast episode
    • transcribe_episode: Coordinates transcription of an episode
    • transcribe_segment: Processes individual audio segments using Whisper
    • split_silences: Divides audio into segments at silence points
  4. Search Functionality:
    • refresh_index: Creates search indices for transcribed content
    • Uses scikit-learn for TF-IDF feature extraction and similarity calculation
  5. Web Interface:
    • fastapi_app: Provides a web interface using FastAPI
    • Deployed as an ASGI application using Modal's web endpoint feature

How It Works

  1. The user searches for a podcast by name
  2. The app fetches metadata for the selected podcast and its episodes
  3. For each episode:
    • Audio is downloaded
    • Audio is split into segments at silence points
    • Each segment is transcribed using Whisper
    • Results are combined and stored
  4. A search index is created for the transcribed content
  5. Users can access the data through a web interface

This is a great example of how Modal can be used to build a complex serverless application with multiple functions working together. It leverages Modal's key features:

Function-as-a-Service Architecture
Modal Function Communication Patterns
Serverless Data Persistence Strategies
Modal Execution Model
Ephemeral vs. Persistent Storage in Serverless

--- pues lo que mq queda es seguir con Windsurf, lo tengo en C:\code\modal-examples\guiom , no lo he probado, lo je dekado diciendo que use test antes de subirlo.

Porque tendria que tener un audio para hacer las prubeas y tal, necesito mas tiempo y no lo tengo
y me voy de vacaciones