Los sistemas RAG (Generación Aumentada por Recuperación) requieren datos de calidad para su entrenamiento. YouTube es una enorme fuente de contenido estructurado: videos con subtítulos, metadatos y comentarios. En este artículo, analizaremos cómo recolectar datos de YouTube de manera efectiva para RAG, evitando bloqueos y cumpliendo con los límites de la API.
Qué es RAG y por qué se necesitan datos de YouTube
RAG (Generación Aumentada por Recuperación) es un enfoque para construir sistemas de IA, donde un modelo de lenguaje se complementa con una base de conocimientos. En lugar de depender únicamente de los datos con los que se ha entrenado el modelo, RAG extrae información relevante de una fuente externa y la utiliza para generar respuestas.
YouTube contiene millones de horas de contenido con subtítulos en diferentes idiomas. Esto convierte a la plataforma en una valiosa fuente de datos para sistemas RAG en diversas áreas:
- Sistemas educativos — conferencias, tutoriales, cursos con marcas de tiempo
- Documentación técnica — guías en video sobre programación, DevOps, configuración de software
- Bases de conocimiento médico — conferencias de médicos, análisis de casos clínicos
- Analítica de negocios — entrevistas con expertos, casos de estudio, análisis de mercados
- Soporte de productos — reseñas de productos, preguntas frecuentes en formato de video
La ventaja de los datos de YouTube es su estructura: subtítulos con marcas de tiempo, metadatos (categorías, etiquetas), contexto social (comentarios, me gusta). Todo esto ayuda al sistema RAG a entender no solo el contenido, sino también el contexto de la información.
Qué datos de YouTube son útiles para sistemas RAG
Para que un sistema RAG funcione de manera efectiva, es necesario recolectar varios tipos de datos. Cada tipo cumple con sus propias funciones en el proceso de extracción y generación de información.
Subtítulos (Transcripts)
La principal fuente de datos textuales. YouTube proporciona dos tipos de subtítulos:
- Automáticos — generados por algoritmos de reconocimiento de voz de Google. Disponibles para la mayoría de los videos en inglés y otros idiomas populares. Precisión del 85-95% dependiendo de la calidad del sonido.
- Manuales — cargados por los autores o la comunidad. Más precisos, a menudo contienen formato y contexto adicional.
Los subtítulos incluyen marcas de tiempo (timestamps), lo que permite vincular el texto con momentos específicos del video. Esto es crítico para crear enlaces precisos a las fuentes en las respuestas de RAG.
Metadatos de video
Los metadatos ayudan al sistema RAG a comprender el contexto y la relevancia de la información:
| Tipo de datos | Aplicación en RAG |
|---|---|
| Título y descripción | Búsqueda semántica, determinación del tema |
| Etiquetas y categorías | Clasificación de contenido, filtrado |
| Fecha de publicación | Relevancia de la información (importante para temas técnicos) |
| Duración | Evaluación de la profundidad del tema |
| Estadísticas (vistas, me gusta) | Evaluación de la calidad y popularidad de la fuente |
| Información del canal | Determinación de la autoridad de la fuente |
Comentarios
Los comentarios contienen contexto adicional: preguntas de los espectadores, aclaraciones de los autores, discusiones. Para los sistemas RAG, esto es valioso, ya que:
- Los comentarios a menudo contienen preguntas frecuentes sobre el tema del video
- Los autores pueden publicar correcciones y adiciones
- Las discusiones revelan diferentes puntos de vista sobre el problema
Trabajo con YouTube Data API v3: configuración y límites
YouTube Data API v3 es la forma oficial de obtener datos. Proporciona acceso a metadatos, estadísticas y comentarios. Los subtítulos se obtienen a través de métodos separados.
Obtención de la clave API
Para trabajar con la API se necesita una clave de Google Cloud Console:
- Visite console.cloud.google.com
- Crear un nuevo proyecto o seleccionar uno existente
- Activar YouTube Data API v3 en la sección "APIs y Servicios"
- Crear credenciales (Credentials) → clave API
- Copie la clave: la necesitará para todas las solicitudes
Límites y cuotas
YouTube API utiliza un sistema de cuotas. Cada solicitud "cuesta" una cierta cantidad de unidades:
| Operación | Costo en cuotas |
|---|---|
| Búsqueda de videos (search.list) | 100 unidades |
| Obtención de datos de video (videos.list) | 1 unidad |
| Obtención de comentarios (commentThreads.list) | 1 unidad |
El límite diario por defecto es de 10,000 unidades. Esto equivale a aproximadamente 100 solicitudes de búsqueda o 10,000 solicitudes de metadatos. Para aumentar la cuota, es necesario enviar una solicitud a Google.
Ejemplo básico de trabajo con la API
import requests
API_KEY = 'tu_clave_api'
BASE_URL = 'https://www.googleapis.com/youtube/v3'
# Búsqueda de videos por consulta
def search_videos(query, max_results=10):
url = f'{BASE_URL}/search'
params = {
'part': 'snippet',
'q': query,
'type': 'video',
'maxResults': max_results,
'key': API_KEY
}
response = requests.get(url, params=params)
return response.json()
# Obtención de metadatos de video
def get_video_details(video_id):
url = f'{BASE_URL}/videos'
params = {
'part': 'snippet,contentDetails,statistics',
'id': video_id,
'key': API_KEY
}
response = requests.get(url, params=params)
return response.json()
# Ejemplo de uso
results = search_videos('tutorial de aprendizaje automático', max_results=5)
for item in results.get('items', []):
video_id = item['id']['videoId']
title = item['snippet']['title']
print(f'ID: {video_id}, Título: {title}')
# Obtenemos información detallada
details = get_video_details(video_id)
stats = details['items'][0]['statistics']
print(f"Vistas: {stats.get('viewCount')}, Me gusta: {stats.get('likeCount')}")
Análisis de subtítulos de video: automáticos y manuales
YouTube Data API v3 no proporciona acceso directo a los subtítulos. Para obtenerlos, se utilizan métodos alternativos.
Uso de la biblioteca youtube-transcript-api
La forma más sencilla es la biblioteca youtube-transcript-api para Python. Extrae subtítulos directamente, sin necesidad de clave API:
from youtube_transcript_api import YouTubeTranscriptApi
# Obtención de subtítulos
video_id = 'dQw4w9WgXcQ'
try:
# Intentar obtener subtítulos en ruso, si no hay, en inglés
transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['ru', 'en'])
# Mostrar subtítulos con marcas de tiempo
for entry in transcript:
start_time = entry['start']
duration = entry['duration']
text = entry['text']
print(f"[{start_time:.2f}s] {text}")
except Exception as e:
print(f"Error al obtener subtítulos: {e}")
# Obtener lista de idiomas disponibles
transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
for transcript in transcript_list:
print(f"Idioma: {transcript.language}, Automáticos: {transcript.is_generated}")
La biblioteca determina automáticamente los subtítulos disponibles y puede traducirlos a otros idiomas (si YouTube proporciona esa opción).
Procesamiento de marcas de tiempo para RAG
Para los sistemas RAG, es importante mantener la conexión entre el texto y las marcas de tiempo. Esto permite crear enlaces precisos a las fuentes:
def format_timestamp(seconds):
"""Conversión de segundos a formato MM:SS"""
minutes = int(seconds // 60)
secs = int(seconds % 60)
return f"{minutes:02d}:{secs:02d}"
def create_chunks_with_timestamps(transcript, chunk_size=500):
"""División de subtítulos en fragmentos manteniendo las marcas de tiempo"""
chunks = []
current_chunk = ""
chunk_start_time = 0
for i, entry in enumerate(transcript):
if len(current_chunk) == 0:
chunk_start_time = entry['start']
current_chunk += entry['text'] + " "
# Si se alcanza el tamaño deseado o el final de los subtítulos
if len(current_chunk) >= chunk_size or i == len(transcript) - 1:
chunks.append({
'text': current_chunk.strip(),
'start_time': chunk_start_time,
'timestamp': format_timestamp(chunk_start_time),
'video_id': video_id
})
current_chunk = ""
return chunks
# Uso
transcript = YouTubeTranscriptApi.get_transcript(video_id)
chunks = create_chunks_with_timestamps(transcript)
for chunk in chunks[:3]: # Primeros 3 fragmentos
print(f"[{chunk['timestamp']}] {chunk['text'][:100]}...")
Recolección de metadatos: títulos, descripciones, etiquetas
Los metadatos enriquecen el contexto para el sistema RAG. Aquí hay un ejemplo completo de recolección de todos los datos necesarios:
import requests
from datetime import datetime
def collect_video_metadata(video_id, api_key):
"""Recolección de metadatos completos de video"""
url = f'https://www.googleapis.com/youtube/v3/videos'
params = {
'part': 'snippet,contentDetails,statistics,topicDetails',
'id': video_id,
'key': api_key
}
response = requests.get(url, params=params)
data = response.json()
if 'items' not in data or len(data['items']) == 0:
return None
item = data['items'][0]
snippet = item['snippet']
stats = item.get('statistics', {})
content = item.get('contentDetails', {})
metadata = {
'video_id': video_id,
'title': snippet['title'],
'description': snippet['description'],
'channel_title': snippet['channelTitle'],
'channel_id': snippet['channelId'],
'published_at': snippet['publishedAt'],
'tags': snippet.get('tags', []),
'category_id': snippet.get('categoryId'),
'duration': content.get('duration'),
'view_count': int(stats.get('viewCount', 0)),
'like_count': int(stats.get('likeCount', 0)),
'comment_count': int(stats.get('commentCount', 0)),
'topics': item.get('topicDetails', {}).get('topicCategories', [])
}
return metadata
# Ejemplo de uso
metadata = collect_video_metadata('dQw4w9WgXcQ', API_KEY)
print(f"Título: {metadata['title']}")
print(f"Canal: {metadata['channel_title']}")
print(f"Vistas: {metadata['view_count']:,}")
print(f"Etiquetas: {', '.join(metadata['tags'][:5])}")
Determinación de la relevancia del contenido
Para temas técnicos, la frescura de la información es importante. Agreguemos una función para evaluar la relevancia:
from datetime import datetime, timedelta
def calculate_content_freshness(published_date_str):
"""Evaluación de la relevancia del contenido"""
published_date = datetime.fromisoformat(published_date_str.replace('Z', '+00:00'))
age_days = (datetime.now(published_date.tzinfo) - published_date).days
if age_days < 30:
return 'muy_fresco'
elif age_days < 180:
return 'fresco'
elif age_days < 365:
return 'moderado'
else:
return 'viejo'
def calculate_quality_score(metadata):
"""Cálculo de la puntuación de calidad de la fuente"""
score = 0
# Popularidad
views = metadata['view_count']
if views > 100000:
score += 3
elif views > 10000:
score += 2
elif views > 1000:
score += 1
# Engagement (me gusta en relación a las vistas)
if views > 0:
like_ratio = metadata['like_count'] / views
if like_ratio > 0.05:
score += 2
elif like_ratio > 0.02:
score += 1
# Relevancia
freshness = calculate_content_freshness(metadata['published_at'])
if freshness == 'muy_fresco':
score += 2
elif freshness == 'fresco':
score += 1
return score
# Uso
metadata = collect_video_metadata('dQw4w9WgXcQ', API_KEY)
quality = calculate_quality_score(metadata)
freshness = calculate_content_freshness(metadata['published_at'])
print(f"Puntuación de calidad: {quality}/7")
print(f"Relevancia: {freshness}")
Análisis de comentarios para análisis contextual
Los comentarios pueden contener información valiosa: correcciones de errores en el video, recursos adicionales, preguntas frecuentes. Para los sistemas RAG, esto es contexto adicional.
def get_video_comments(video_id, api_key, max_results=100):
"""Obtención de comentarios de video"""
url = 'https://www.googleapis.com/youtube/v3/commentThreads'
comments = []
next_page_token = None
while len(comments) < max_results:
params = {
'part': 'snippet',
'videoId': video_id,
'maxResults': min(100, max_results - len(comments)),
'order': 'relevance', # Ordenar por relevancia
'key': api_key
}
if next_page_token:
params['pageToken'] = next_page_token
response = requests.get(url, params=params)
data = response.json()
if 'items' not in data:
break
for item in data['items']:
top_comment = item['snippet']['topLevelComment']['snippet']
comments.append({
'author': top_comment['authorDisplayName'],
'text': top_comment['textDisplay'],
'like_count': top_comment['likeCount'],
'published_at': top_comment['publishedAt'],
'reply_count': item['snippet']['totalReplyCount']
})
next_page_token = data.get('nextPageToken')
if not next_page_token:
break
return comments
def filter_valuable_comments(comments, min_likes=5):
"""Filtrado de comentarios valiosos"""
valuable = []
for comment in comments:
# Criterios de valor:
# 1. Muchos me gusta (popularidad)
# 2. Hay respuestas (provocó discusión)
# 3. Texto largo (comentario detallado)
if (comment['like_count'] >= min_likes or
comment['reply_count'] > 0 or
len(comment['text']) > 200):
valuable.append(comment)
return valuable
# Uso
comments = get_video_comments('dQw4w9WgXcQ', API_KEY, max_results=50)
valuable_comments = filter_valuable_comments(comments)
print(f"Total de comentarios: {len(comments)}")
print(f"Comentarios valiosos: {len(valuable_comments)}")
for comment in valuable_comments[:3]:
print(f"\n[{comment['like_count']} me gusta] {comment['author']}:")
print(comment['text'][:200])
Uso de proxies para escalar la recolección de datos
Al recolectar datos a gran escala, surgen dos problemas: los límites de la API de YouTube (10,000 cuotas por día) y bloqueos al analizar subtítulos. Los proxies ayudan a resolver ambas tareas.
Cuándo se necesitan proxies para el análisis de YouTube
- Exceso de cuotas de API — utilizando varias claves API a través de diferentes IP, se puede aumentar el límite diario
- Análisis de subtítulos evitando la API — la biblioteca youtube-transcript-api realiza solicitudes directas, que pueden ser bloqueadas a alta frecuencia
- Recolección de datos de diferentes regiones — algunos videos solo están disponibles en ciertos países
- Recolección paralela — distribución de la carga en varias IP para acelerar el proceso
Elección del tipo de proxy
| Tipo de proxy | Ventajas | Cuándo usar |
|---|---|---|
| Centro de datos | Alta velocidad, bajo costo | Trabajo con API, volúmenes pequeños |
| Residenciales | Bajo riesgo de bloqueos, IP reales | Análisis masivo de subtítulos, eludir restricciones |
| Móviles | Máxima confianza, bloqueos raros | Recolección de datos de aplicaciones móviles, tareas críticas |
Para la mayoría de las tareas de los sistemas RAG, son adecuados los proxies residenciales — ofrecen un equilibrio entre costo y confiabilidad al analizar a gran escala.
Configuración de proxies en el código
import requests
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api._api import TranscriptListFetcher
# Configuración de proxy
PROXY = {
'http': 'http://usuario:contraseña@servidor-proxy:puerto',
'https': 'http://usuario:contraseña@servidor-proxy:puerto'
}
# Para trabajar con la API a través de proxy
def get_video_details_with_proxy(video_id, api_key, proxy):
url = f'https://www.googleapis.com/youtube/v3/videos'
params = {
'part': 'snippet,statistics',
'id': video_id,
'key': api_key
}
response = requests.get(url, params=params, proxies=proxy, timeout=10)
return response.json()
# Para analizar subtítulos a través de proxy
class ProxiedTranscriptApi:
def __init__(self, proxy):
self.proxy = proxy
def get_transcript(self, video_id, languages=['en']):
# Crear una sesión personalizada con proxy
session = requests.Session()
session.proxies = self.proxy
# Usar la sesión para las solicitudes
fetcher = TranscriptListFetcher(session)
transcript_list = fetcher.fetch(video_id)
# Obtener el idioma deseado
for lang in languages:
try:
transcript = transcript_list.find_transcript([lang])
return transcript.fetch()
except:
continue
raise Exception(f"Subtítulos no encontrados para los idiomas: {languages}")
# Uso
api = ProxiedTranscriptApi(PROXY)
transcript = api.get_transcript('dQw4w9WgXcQ', languages=['ru', 'en'])
print(f"Se obtuvieron {len(transcript)} segmentos de subtítulos")
Rotación de proxies para escalabilidad
Al recolectar datos de miles de videos, es importante distribuir la carga entre varios proxies:
import random
import time
class ProxyRotator:
def __init__(self, proxy_list):
self.proxies = proxy_list
self.current_index = 0
def get_next_proxy(self):
"""Rotación secuencial"""
proxy = self.proxies[self.current_index]
self.current_index = (self.current_index + 1) % len(self.proxies)
return proxy
def get_random_proxy(self):
"""Rotación aleatoria"""
return random.choice(self.proxies)
# Lista de proxies
PROXY_LIST = [
{'http': 'http://usuario:contraseña@proxy1:puerto', 'https': 'http://usuario:contraseña@proxy1:puerto'},
{'http': 'http://usuario:contraseña@proxy2:puerto', 'https': 'http://usuario:contraseña@proxy2:puerto'},
{'http': 'http://usuario:contraseña@proxy3:puerto', 'https': 'http://usuario:contraseña@proxy3:puerto'},
]
rotator = ProxyRotator(PROXY_LIST)
def collect_data_with_rotation(video_ids):
results = []
for video_id in video_ids:
proxy = rotator.get_next_proxy()
try:
# Obtener metadatos
metadata = get_video_details_with_proxy(video_id, API_KEY, proxy)
# Obtener subtítulos
api = ProxiedTranscriptApi(proxy)
transcript = api.get_transcript(video_id)
results.append({
'video_id': video_id,
'metadata': metadata,
'transcript': transcript
})
# Retraso entre solicitudes
time.sleep(1)
except Exception as e:
print(f"Error para {video_id}: {e}")
continue
return results
# Uso
video_ids = ['video1', 'video2', 'video3', 'video4', 'video5']
data = collect_data_with_rotation(video_ids)
print(f"Se recolectaron datos para {len(data)} videos")
Procesamiento y preparación de datos para RAG
Después de recolectar los datos, es necesario procesarlos y estructurarlos para el funcionamiento efectivo de los sistemas RAG.
Creación de embeddings vectoriales
Los sistemas RAG utilizan búsqueda vectorial para encontrar fragmentos relevantes. Es necesario convertir el texto en embeddings:
from sentence_transformers import SentenceTransformer
import numpy as np
# Carga del modelo para crear embeddings
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
def create_embeddings_from_transcript(transcript_chunks):
"""Creación de embeddings para fragmentos de subtítulos"""
embeddings = []
for chunk in transcript_chunks:
# Combinamos el texto con los metadatos para mejor contexto
text_with_context = f"{chunk['title']} | {chunk['text']}"
# Creamos el embedding
embedding = model.encode(text_with_context)
embeddings.append({
'video_id': chunk['video_id'],
'timestamp': chunk['timestamp'],
'text': chunk['text'],
'embedding': embedding.tolist(),
'metadata': {
'title': chunk['title'],
'channel': chunk['channel'],
'views': chunk['views']
}
})
return embeddings
# Preparación de datos
def prepare_rag_data(video_data):
"""Preparación de todos los datos para RAG"""
all_chunks = []
for video in video_data:
metadata = video['metadata']
transcript = video['transcript']
# Dividimos los subtítulos en fragmentos
chunks = create_chunks_with_timestamps(transcript)
# Agregamos metadatos a cada fragmento
for chunk in chunks:
chunk['title'] = metadata['title']
chunk['channel'] = metadata['channel_title']
chunk['views'] = metadata['view_count']
all_chunks.append(chunk)
# Creamos embeddings
embeddings = create_embeddings_from_transcript(all_chunks)
return embeddings
# Uso
rag_data = prepare_rag_data(collected_videos)
print(f"Preparados {len(rag_data)} fragmentos para RAG")
Almacenamiento en base de datos vectorial
Para una búsqueda efectiva, los embeddings se almacenan en bases de datos especializadas. Opciones populares: Pinecone, Weaviate, Qdrant, ChromaDB.
import chromadb
from chromadb.config import Settings
# Inicialización de ChromaDB (base de datos vectorial local)
client = chromadb.Client(Settings(
chroma_db_impl="duckdb+parquet",
persist_directory="./youtube_rag_db"
))
# Creación de colección
collection = client.create_collection(
name="youtube_transcripts",
metadata={"description": "Transcripciones de videos de YouTube para RAG"}
)
def store_in_vector_db(embeddings_data, collection):
"""Almacenamiento de embeddings en base de datos vectorial"""
ids = []
embeddings = []
documents = []
metadatas = []
for i, item in enumerate(embeddings_data):
ids.append(f"{item['video_id']}_{i}")
embeddings.append(item['embedding'])
documents.append(item['text'])
metadatas.append({
'video_id': item['video_id'],
'timestamp': item['timestamp'],
'title': item['metadata']['title'],
'channel': item['metadata']['channel'],
'views': str(item['metadata']['views']),
'youtube_url': f"https://youtube.com/watch?v={item['video_id']}&t={int(float(item['timestamp'].split(':')[0])*60 + float(item['timestamp'].split(':')[1]))}s"
})
# Adición a la colección
collection.add(
ids=ids,
embeddings=embeddings,
documents=documents,
metadatas=metadatas
)
print(f"Almacenados {len(ids)} embeddings en la base de datos vectorial")
# Uso
store_in_vector_db(rag_data, collection)
Búsqueda y generación de respuestas
El paso final es implementar la búsqueda RAG y la generación de respuestas:
def search_youtube_knowledge(query, collection, model, top_k=3):
"""Búsqueda de fragmentos relevantes de YouTube"""
# Creamos el embedding de la consulta
query_embedding = model.encode(query).tolist()
# Búsqueda en la base de datos vectorial
results = collection.query(
query_embeddings=[query_embedding],
n_results=top_k
)
# Formateo de resultados
sources = []
for i in range(len(results['ids'][0])):
sources.append({
'text': results['documents'][0][i],
'metadata': results['metadatas'][0][i],
'distance': results['distances'][0][i] if 'distances' in results else None
})
return sources
def generate_rag_answer(query, sources, llm_api_key):
"""Generación de respuesta basada en las fuentes encontradas"""
# Formamos el contexto a partir de las fuentes encontradas
context = "\n\n".join([
f"Fuente: {s['metadata']['title']} ({s['metadata']['timestamp']})\n{s['text']}"
for s in sources
])
# Prompt para LLM
prompt = f"""Basado en los siguientes fragmentos de videos de YouTube, responde a la pregunta del usuario.
Asegúrate de indicar las fuentes con marcas de tiempo.
Contexto:
{context}
Pregunta: {query}
Respuesta:"""
# Aquí se llamaría a tu LLM (OpenAI, Claude, modelo local)
# Ejemplo con OpenAI:
# response = openai.ChatCompletion.create(
# model="gpt-4",
# messages=[{"role": "user", "content": prompt}]
# )
# answer = response.choices[0].message.content
# Para el ejemplo, retornamos el prompt
return {
'answer': 'Aquí estará la respuesta de LLM',
'sources': sources
}
# Uso
query = "¿Cómo configurar un proxy en Python?"
sources = search_youtube_knowledge(query, collection, model, top_k=3)
print("Fuentes encontradas:")
for source in sources:
print(f"\n{source['metadata']['title']}")
print(f"Tiempo: {source['metadata']['timestamp']}")
print(f"Enlace: {source['metadata']['youtube_url']}")
print(f"Texto: {source['text'][:200]}...")
Optimización de la calidad RAG
Algunos consejos para mejorar la calidad del sistema RAG en datos de YouTube:
- Filtra contenido de baja calidad — utiliza métricas de vistas, me gusta, antigüedad de publicación
- Mantén el contexto — agrega el título del video y del canal a cada fragmento de texto
- Optimiza el tamaño de los fragmentos — para contenido técnico, 300-500 palabras es óptimo
- Utiliza metadatos para clasificar — contenido más fresco y popular puede tener prioridad
- Agrega comentarios — a menudo contienen aclaraciones importantes y preguntas frecuentes
- Verifica la disponibilidad del video — algunos videos pueden ser eliminados o hacerse privados
Consejo: Para la recolección masiva de datos de YouTube, se recomienda utilizar una combinación de la API oficial (para metadatos) y el análisis a través de proxies (para subtítulos). Esto permite eludir los límites y obtener la máxima información.
Conclusión
La recolección de datos de YouTube para sistemas RAG es un proceso de múltiples etapas que incluye trabajar con la API, analizar subtítulos, procesar metadatos y crear embeddings vectoriales. Puntos clave:
- YouTube Data API v3 proporciona metadatos, estadísticas y comentarios con un límite de 10,000 cuotas por día
- Los subtítulos se analizan a través de la biblioteca youtube-transcript-api o solicitudes directas
- Las marcas de tiempo son críticas para crear enlaces precisos a las fuentes
- Los metadatos (vistas, me gusta, fecha) ayudan a evaluar la calidad y relevancia del contenido
- Los comentarios añaden contexto y a menudo contienen preguntas frecuentes
- Los proxies son necesarios para escalar y eludir límites
- Los embeddings vectoriales y las bases de datos especializadas permiten una búsqueda semántica rápida
Con la configuración adecuada del proceso, se pueden recolectar decenas de miles de fragmentos de contenido de calidad al día, creando una poderosa base de conocimientos para sistemas RAG en cualquier área temática.
Si planeas una recolección masiva de datos de YouTube eludiendo límites y bloqueos, te recomendamos utilizar proxies residenciales — ofrecen estabilidad al analizar miles de videos y minimizan el riesgo de bloqueos por parte de YouTube.