← Ruta Perico
Etapa 03

Inventariar las fuentes antes de escribir código

2ª categoría Publicada Investigación
03

En la etapa anterior comprobamos que los subtítulos de YouTube existen y se bajan. Eso responde a «¿se puede?». Falta la pregunta que decide si el proyecto sale bien: ¿cuánto material hay realmente?

Es la pregunta que más se salta la gente. Se encuentran dos o tres fuentes prometedoras, se da por hecho que «habrá más», y se construye el pipeline entero. Cuando aparece el corpus real, ya es tarde para cambiar de estrategia.

Error cometido en este proyecto

Tras medir un solo podcast de 20.004 palabras, la conclusión fue «cinco o seis vídeos así y superamos el objetivo». Era falso, y se tardó una hora en descubrirlo. Palabras no son frases: hay que medir también la densidad, y eso exige leer una muestra.

Paso 1 — Barrido amplio, no dos búsquedas

Una búsqueda da lo que YouTube considera popular, no lo que existe. Con diez consultas salieron 30 candidatos. Con cuarenta y cuatro salieron 76 y el triple de horas. La diferencia no es el buscador: es cuántos ángulos distintos se le atacan.

Ángulos que funcionan, y que conviene combinar:

  • Variantes del nombre — nombre real, apodo, apellido solo.
  • Formatos — entrevista, podcast, charla, conferencia, coloquio, tertulia, ponencia, masterclass, mesa redonda.
  • Temas de los que habla — su ciudad, sus rivales, sus victorias, sus aficiones.
  • Programas y medios donde suele aparecer.
barrido.sh
#!/bin/zsh
Q=(
 "Perico Delgado entrevista"   "Pedro Delgado podcast"
 "Perico Delgado conferencia"  "Perico Delgado tertulia"
 "Perico Delgado Segovia"      "Perico Delgado Indurain"
 # ...44 consultas en total
)
for q in "${Q[@]}"; do
  yt-dlp "ytsearch25:$q" --flat-playlist \
    --print "%(duration)s|%(title)s|%(id)s|%(channel)s"
done

--flat-playlist es la clave: pide solo los metadatos del listado, sin abrir cada vídeo. Un barrido de 1.100 resultados tarda minutos en vez de horas.

Paso 2 — Filtrar el ruido con la máquina

551 vídeos únicos salieron del barrido. La mayoría no valen, y revisarlos a mano es inviable. Tres filtros automáticos quitan casi todo:

filtrar.py
import re

RUIDO = re.compile(
    r"marcha|cicloturista|gameplay|spectrum|"
    r"pro cycling manager|stage \d",
    re.I,
)

candidatos = []
vistos = set()

for linea in open("barrido.txt", encoding="utf-8"):
    partes = linea.rstrip("\n").split("|")
    if len(partes) != 4 or not partes[0].isdigit():
        continue

    duracion, titulo, video_id, canal = int(partes[0]), *partes[1:]

    if video_id in vistos:        # 1. el mismo video sale en varias busquedas
        continue
    vistos.add(video_id)

    if not re.search(r"perico|pedro delgado", titulo, re.I):
        continue                  # 2. no habla de el
    if duracion < 600 or RUIDO.search(titulo):
        continue                  # 3. corto, o ruido conocido

    candidatos.append((duracion, titulo, video_id, canal))

candidatos.sort(reverse=True)     # los mas largos primero

Qué hace cada pieza de Python nueva

CódigoQué esEquivalente en JS
set()Conjunto sin duplicados. Comprobar si algo está dentro es instantáneonew Set()
re.compile(...)Expresión regular precompilada. re.I = ignorar mayúsculas/.../i
*partes[1:]Desempaqueta el resto de la lista en variables sueltas...rest en destructuring
continueSalta a la siguiente vuelta del bucleidéntico
sort(reverse=True)Ordena en el sitio, no devuelve copia.sort() sí devuelve
Nombres iguales, personas distintas

El filtro por nombre arrastra homónimos. En este proyecto aparecieron un médico, un académico chileno y un videojuego de Spectrum de 1989 llamado igual que el protagonista. Ningún filtro automático los distingue: hay que mirar la lista final con los ojos.

Paso 3 — Minar canales, no solo búsquedas

Este paso multiplica el inventario y casi nadie lo hace. La lógica es simple: si un canal publicó un vídeo bueno, probablemente tenga más. Un podcast que lo entrevistó una vez lo entrevista cada temporada.

Se detecta contando qué canales se repiten entre los candidatos:

python
import collections

cuenta = collections.Counter(canal for _, _, _, canal in candidatos)

for canal, n in cuenta.most_common():
    if n > 1:
        print(f"{n}x  {canal}")

Y luego se lista el canal entero, que es mucho más barato que buscar a ciegas:

terminal
url=$(yt-dlp --print "%(channel_url)s" --skip-download "$VIDEO_URL")

yt-dlp "${url}/videos" --flat-playlist --playlist-end 300 \
   --print "%(duration)s|%(title)s|%(id)s|%(channel)s"

Aquí apareció lo que ninguna búsqueda había devuelto: un canal oficial del propio Perico. Buscando por temas nunca sale; minando canales, sí.

Paso 4 — Medir de verdad, no estimar

Con la lista filtrada, se bajan los subtítulos de todos y se cuentan palabras. Es la única forma de saber qué hay.

medir.py
import re, pathlib

def texto_de_vtt(ruta):
    """Convierte un .vtt en texto corrido, sin tiempos ni duplicados."""
    lineas = []
    for linea in ruta.read_text(encoding="utf-8").splitlines():
        # fuera cabeceras y marcas de tiempo
        if "-->" in linea or linea.startswith(("WEBVTT", "Kind:", "Language:")):
            continue
        if not linea.strip():
            continue
        linea = re.sub(r"<[^>]+>", "", linea).strip()   # fuera etiquetas
        # los subtitulos automaticos repiten la linea anterior al avanzar
        if linea and (not lineas or lineas[-1] != linea):
            lineas.append(linea)
    return re.sub(r"\s+", " ", " ".join(lineas))

total = 0
for fichero in sorted(pathlib.Path("subs").glob("*.vtt")):
    n = len(texto_de_vtt(fichero).split())
    total += n
    print(f"{n:>7,}  {fichero.name}")

print(f"TOTAL {total:,} palabras")

Ese lineas[-1] != linea importa más de lo que parece: los subtítulos automáticos repiten la línea anterior cada vez que avanzan, para dar el efecto de texto que se desliza. Sin ese filtro, el recuento sale al doble.

Paso 5 — Medir la densidad, no solo el volumen

Este es el paso que se salta todo el mundo, y el que evita construir sobre una expectativa falsa.

Se coge una muestra de unos cientos de palabras y se lee. Con 105.525 palabras recogidas, la cuenta de frases aprovechables sobre la muestra dio una por cada 250-350 palabras. Es decir: unas 350 frases, no los «miles» que sugería el volumen bruto.

Leer la muestra reveló además algo que ninguna métrica automática habría dicho:

«...tuviste que aprender francés efe a leches...» — era «a hachazos»
«...los triunfos de la unsj amstrong...» — era «Lance Armstrong»

La calidad de transcripción varía enormemente entre vídeos

Un fragmento que hay que reparar para entenderlo deja de ser una cita: es una reconstrucción. Si se indexa, el sistema aprende a imitar el error.

La regla general

Volumen bruto × densidad = corpus real. Medir solo el volumen te da un número entre tres y diez veces optimista, y no lo descubres hasta tener el pipeline montado.

Resumen del método

PasoQué respondeCoste
1. Barrido amplio¿Qué existe?minutos
2. Filtro automático¿Qué es del tema?segundos
3. Minado de canales¿Qué no devolvió la búsqueda?minutos
4. Medición¿Cuánto volumen hay?minutos
5. Muestra leída¿Cuánto sirve?15 minutos, y es el paso decisivo

Media hora larga en total, y sustituye una suposición por un número. En un proyecto donde el corpus es el producto, es la mejor media hora que vas a invertir.

Accesible no es lo mismo que rentable

El inventario responde «cuánto hay». La pregunta que viene justo detrás es «¿hace falta más?», y ahí se cuela el error más caro de todos.

Buscando fuentes aparece siempre una que tienta: enorme y, además, accesible. En este proyecto fue el archivo de RTVE, la televisión pública española. Perico lleva décadas siendo su comentarista de ciclismo, así que son años de retransmisiones con él hablando — volumen prácticamente ilimitado.

Y es accesible de verdad. yt-dlp trae extractores para RTVE — los módulos que saben hablar con cada web concreta — y funcionan:

extractores de yt-dlp para RTVE
rtve.es:alacarta
rtve.es:program
rtve.es:television

No hay ninguna barrera técnica. Y aun así es la peor de las cinco fuentes que se valoraron.

El motivo es la densidad. Una retransmisión de carrera es, en su mayor parte, narración técnica: «cambia el ritmo, quiere reaccionar el otro». Y el micrófono se comparte con el compañero de cabina sin ninguna marca de quién habla, así que a la poca cosecha hay todavía que restarle lo que dijo el otro.

Medido sobre un recopilatorio de retransmisiones — el mismo que ya salió en la etapa 2 con la densidad marcada como «baja»:

MaterialFrases aprovechables
Entrevista o podcast1 por cada ~300 palabras
Retransmisión2 o 3 en 1.503 palabras, o sea 1 por cada ~600

La mitad de rendimiento por palabra, y eso antes de descontar lo que dijo el compañero.

Aquí está lo que cuesta ver: una fuente con el doble de volumen y la mitad de densidad no es el doble de buena — es lo mismo, cobrado al doble. Duplicas las horas de audio que bajar, la transcripción, el texto que limpiar y el coste de clasificar, para acabar con la misma cantidad de frases. Con un factor de diez, la aritmética es idéntica y el destrozo es de diez.

«Es accesible» y «merece la pena» son dos preguntas distintas, y la primera no contesta a la segunda.

El matiz de derechos

Descargar la programación completa de una televisión no es lo mismo que transcribir vídeos que alguien subió públicamente a una plataforma: es otra escala de copia. No lo descarta para uso personal, pero es una decisión que se toma antes de bajarse cincuenta horas de Tour, no una que se descubre después.

Decide midiendo lo que ya tienes, no suponiendo que necesitas más

La otra mitad de la respuesta es más incómoda, porque casi siempre significa no hacer nada.

Con unas 400.000 palabras limpias y la densidad estimada de una frase por cada 300, la proyección son unas 1.300 frases: ya dentro del objetivo. Dicho de otro modo, en el momento exacto de la tentación la fuente enorme no hacía falta. Ir a por ella antes de contar el rendimiento real de lo que ya hay en casa es la forma más segura de acabar procesando cincuenta horas de material flojo que nadie necesitaba.

Y es el tercer caso del mismo patrón en este proyecto:

  • Al principio de esta etapa, estimar el corpus entero a partir de un solo podcast de 20.004 palabras.
  • En la etapa 8, dar por buenas las transcripciones leyendo trozos del medio de los ficheros.
  • Y ahora, dar por hecho que hace falta más material sin haber contado el que ya se tiene.

Tres veces no es mala suerte. Es extrapolar en vez de contar, y reaparece siempre que un número es caro de conseguir y fácil de estimar a ojo.

El orden para ampliar un corpus

Cuando de verdad se queda corto, la siguiente fuente se elige por densidad por hora invertida, no por volumen disponible. Aquí el orden quedó así:

  1. Radio y podcasts fuera de YouTube. Mismo tratamiento que ya está montado, y densidad de entrevista.
  2. Prensa escrita con citas entrecomilladas. Poco volumen, pero el texto viene perfecto: ni un error de transcripción que reparar.
  3. Retransmisiones. La última, y filtrando muy fuerte.

Fíjate en que la lista va justo al revés que el volumen disponible: las retransmisiones son, de largo, lo que más material tiene.