Felo API PlatformFelo API Platform

Contenido

Convierte un vídeo de YouTube en un artículo publicable

Obtén la transcripción con timestamps, organízala en bloques legibles, haz esquema y borrador con un modelo que controlas y deja el resultado en un LiveDoc para revisión.

Tiempo25 minutosNivelIntermedioActualizado2026-10-29
Para quiénEquipos de contenidoAutores de newslettersEditores de vídeo y podcast

Copiar el prompt

Sustituye los campos entre corchetes y pégalo en Claude Code, Codex o cualquier IA con acceso a terminal. Instala el skill de Felo, pregunta antes de gastar créditos y ejecuta el flujo.

Convierte este vídeo en un artículo publicable: [URL de YouTube o ID de vídeo].

Audiencia: [lectores]. Tono: [estilo de publicación]. Longitud objetivo: [800–1200 palabras] en [idioma].
Tratamiento de fuentes: conserva el título, el canal y la URL. Cita como máximo pasajes breves, con marcas de tiempo.

Genera:
1. Un título de trabajo.
2. Una entradilla.
3. Secciones con párrafos cortos.
4. Dos o tres citas con marca de tiempo.
5. Lo que el vídeo no cubrió.
6. Una lista de fuentes con el vídeo y las páginas enlazadas.

Reglas:
- No reproduzcas la transcripción completa. Resume y cita brevemente.
- Toda afirmación fáctica del vídeo necesita marca de tiempo; las de páginas enlazadas necesitan URL.
- Marca como «No verificado» todo lo que no pudiste comprobar.
- Pregunta antes de gastar créditos en transcripciones o extracción de páginas.
- No publiques, programes ni envíes nada.
- Escribe el resultado en ./video-article.md y resúmelo en el chat.

La copia también incluye los pasos de instalación y las reglas de seguridad.

Lo que obtienes

Salida de ejemplo de una ejecución. No es generación en vivo.

Ejemplo de artículo (extracto)

Lo que dijo de verdad una charla de 40 minutos sobre agentes

Entradilla

La demo impresionó; la parte útil fue el manejo de fallos.

La afirmación que todos citaron

> «El agente no se volvió más listo. Solo dejamos de permitirle reintentar sin presupuesto.» — [12:40]

Lo que el vídeo no cubrió

El coste por tarea exitosa y qué pasa cuando la fuente recuperada es incorrecta.

Fuentes

  • Vídeo: https://www.youtube.com/watch?v=...
  • Benchmark enlazado: https://example.com/benchmark

Las llamadas exactas

Para desarrolladores: el mismo flujo como código, en orden de ejecución.

Mostrar las llamadas reales a la API
  1. Obtén la transcripción

    Usa YouTube Subtitling para los subtítulos en el idioma objetivo y guarda inicio y duración de cada línea.

    article.ts
    const BASE = "https://openapi.felo.ai";
    const headers = {
      Authorization: `Bearer ${process.env.FELO_API_KEY}`,
      "Content-Type": "application/json",
    };
    
    async function felo<T>(path: string, body?: unknown): Promise<T> {
      const res = await fetch(`${BASE}${path}`, {
        method: body ? "POST" : "GET",
        headers,
        body: body ? JSON.stringify(body) : undefined,
      });
      if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
      return res.json() as Promise<T>;
    }
    
    type Transcript = {
      data: {
        title: string;
        contents: { text: string; start: number; duration: number }[];
      };
    };
    
    export async function fetchTranscript(videoId: string, language = "en") {
      const query = new URLSearchParams({
        video_code: videoId,
        language,
        with_time: "true",
      });
      const { data } = await felo<Transcript>(`/v2/youtube/subtitling?${query}`);
      if (data.contents.length === 0) throw new Error("This video has no subtitles");
      return data;
    }

    Salida de ejemplo

    {
      "title": "How we rebuilt onboarding",
      "contents": [
        { "text": "Welcome back to the channel.", "start": 0.32, "duration": 4.1 }
      ]
    }
  2. Organiza en bloques legibles

    Divide por temas, elimina muletillas y conserva los timestamps.

    article.ts
    const toClock = (seconds: number) => {
      const minutes = Math.floor(seconds / 60);
      const rest = Math.floor(seconds % 60);
      return `${String(minutes).padStart(2, "0")}:${String(rest).padStart(2, "0")}`;
    };
    
    export function toBlocks(
      contents: Transcript["data"]["contents"],
      window = 60,
    ) {
      const grouped = new Map<number, string[]>();
      for (const line of contents) {
        const bucket = Math.floor(line.start / window) * window;
        grouped.set(bucket, [...(grouped.get(bucket) ?? []), line.text.trim()]);
      }
      return [...grouped]
        .map(([start, lines]) => `[${toClock(start)}] ${lines.join(" ")}`)
        .join("\n\n");
    }

    Salida de ejemplo

    [00:00] Welcome back to the channel. Today we are talking about onboarding.
    
    [01:00] The first thing we changed was the welcome screen.
  3. Recupera las fuentes citadas

    Con Web Fetch, lee las páginas nombradas en el vídeo y añade enlaces y hechos.

    article.ts
    type ExtractData = { data: { content: string } };
    
    export async function fetchSources(urls: string[]) {
      return Promise.all(
        urls.slice(0, 5).map(async (url) => {
          const page = await felo<ExtractData>("/v2/web/extract", {
            url,
            output_format: "markdown",
            with_readability: true,
          });
          return { url, content: page.data.content };
        }),
      );
    }

    Salida de ejemplo

    [
      {
        "url": "https://example.com/reference",
        "content": "# Reference\n\nExtracted page text…"
      }
    ]
  4. Haz el esquema y luego el borrador

    Pide primero un esquema al Model API y escribe el artículo siguiéndolo, con citas breves y timestamps.

    article.ts
    const MODEL_API = "https://openapi.felo.ai/api/v1";
    
    type Completion = {
      choices: { message: { content: string } }[];
      usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number };
    };
    
    async function complete(model: string, prompt: string): Promise<Completion> {
      const res = await fetch(`${MODEL_API}/chat/completions`, {
        method: "POST",
        headers,
        body: JSON.stringify({ model, messages: [{ role: "user", content: prompt }] }),
      });
      if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
      return res.json() as Promise<Completion>;
    }
    
    export async function draftArticle(title: string, transcript: string) {
      const outline = await complete(
        "claude-haiku-5-5",
        "Outline a short article from this transcript. Return only headings.\n\n" + transcript,
      );
      const article = await complete(
        "claude-sonnet-5-5",
        `Write the article "${title}" from the transcript. Follow the outline and keep [mm:ss] on direct quotes.\n\nOutline:\n${outline.choices[0].message.content}\n\nTranscript:\n${transcript}`,
      );
      return {
        outline: outline.choices[0].message.content,
        article: article.choices[0].message.content,
        usage: article.usage,
      };
    }

    Salida de ejemplo

    {
      "outline": "1. The problem\n2. What changed\n3. What we learned",
      "article": "## The problem\n\nWhen we…",
      "usage": { "prompt_tokens": 4120, "completion_tokens": 640, "total_tokens": 4760 }
    }
  5. Déjalo en el LiveDoc para revisión

    Guarda borrador y citas en el LiveDoc y entrégalo al editor para corrección y aprobación.

    article.ts
    type LiveDocData = { data: { short_id: string } };
    type ResourceData = { data: { id: string } };
    
    export async function saveDraft(
      title: string,
      result: { outline: string; article: string },
    ) {
      const doc = await felo<LiveDocData>("/v2/livedocs", {
        name: `Article draft: ${title}`,
        description: "Draft generated from a video transcript",
      });
    
      await felo<ResourceData>(`/v2/livedocs/${doc.data.short_id}/resources/doc`, {
        title: "Draft",
        content: result.article,
      });
    
      await felo<ResourceData>(`/v2/livedocs/${doc.data.short_id}/resources/doc`, {
        title: "Outline",
        content: result.outline,
      });
    
      return doc.data.short_id;
    }

    Salida de ejemplo

    { "short_id": "PvyKouzJirXjFdst4uKRK3" }

Qué incluye

  • Transcripción de YouTube con timestamps
  • Páginas citadas por el vídeo en Markdown
  • Esquema y borrador de tu Model API
  • LiveDoc con el borrador para revisión

Qué no hace

  • No reproduce la transcripción completa; solo citas breves y reescritura
  • El vídeo necesita subtítulos
  • Comprueba derechos y límite de cita antes de publicar
  • El modelo hace esquema y borrador; la decisión final es del editor
  • No publica ni traduce automáticamente

Preguntas

¿El vídeo necesita subtítulos?

Sí. El flujo empieza por los subtítulos; si faltan, se detiene en vez de adivinar lo dicho.

¿Puedo convertir un podcast en artículo?

Este flujo es para YouTube. Para podcast, prepara antes una transcripción y usa las mismas reglas.

¿Puedo escribir en otro idioma?

Sí. Indica el idioma objetivo; las citas quedan en el original con traducción si hace falta.

¿Quién escribe el artículo?

El agent de IA al que pegas el prompt escribe el borrador; Felo aporta transcripción, páginas y espacio de revisión.

¿Puedo republicar toda la transcripción?

No. El flujo crea un artículo nuevo con citas breves y no copia la transcripción completa.

¿Cuánto cuesta una ejecución?

Transcripción y extracción se facturan por uso; las tarifas están en la página de precios y el prompt pide aprobación antes de gastar.

Flujos relacionados

Hazlo tuyo

La misma receta, adaptada a cómo entregas de verdad.

Solo citas con timestamps

No escribas el artículo; entrega una lista de citas verificables para reutilizar.

Primero la versión newsletter

Convierte el artículo en una versión más corta y conversacional.

Procesa un canal en lote

Repite los pasos por vídeo y guarda LiveDocs separados.

Las páginas de referencia detrás de esta receta y los siguientes pasos.