¿Qué hace youtube-publish?
Cargador de la API de datos v3 de YouTube sin dependencia de SDK (usando fetch simple, carga reanudable por fragmentos). Construido para lotes: privado por defecto, un registro SHA256 para que una re-ejecución nunca duplique publicaciones, validación de metadatos, simulación en seco y control de cuota.
Configuración única (la realiza el usuario, no el agente)
- Consola de Google Cloud: crea un proyecto, habilita la API de datos v3 de YouTube, crea un ID de cliente OAuth de tipo Aplicación de escritorio.
- Proporciona el cliente a los scripts sin versionarlo:
export YOUTUBE_CLIENT_ID=... YOUTUBE_CLIENT_SECRET=...(o guarda el JSON descargado fuera del repositorio y pasa--client-secrets). - Autoriza el canal una vez:
Abre la página de consentimiento, captura la redirección en 127.0.0.1 (PKCE + verificación de estado), almacena el token de actualización con modo 600. El token nunca se imprime.node scripts/auth.mjs --token-file .youtube-token.json
Flujo de trabajo
# 1. Simulación en seco: valida metadatos, hashea archivos, muestra plan de subida/saltos y costo de cuota
node scripts/upload.mjs --jobs jobs.json --dry-run
# 2. Subida (privada por defecto)
node scripts/upload.mjs --jobs jobs.json --token-file .youtube-token.json
# Archivo único
node scripts/upload.mjs --file publish/short.mp4 --title "Cómo automaticé mis ediciones" --tags shorts,automation --privacy unlisted
jobs.json:
[
{ "file": "publish/short-01.mp4", "title": "...", "description": "...", "tags": ["shorts"], "privacy": "private" },
{ "file": "publish/short-02.mp4", "title": "...", "privacy": "private", "publishAt": "2026-11-01T17:00:00Z" }
]
Las rutas de archivo relativas se resuelven contra la carpeta del archivo de trabajos.
Reglas
- Solo subir archivos que hayan pasado
render-qcy hayan sido aprobados por el usuario. - La privacidad por defecto es
private.publices rechazado a menos que el usuario lo solicite explícitamente y pases--allow-public. Los vídeos programados (publishAt) deben serprivate; YouTube los cambia a público en ese momento. - Siempre ejecuta
--dry-runprimero y muestra el plan al usuario. - Nunca imprimas, registres o subas tokens, secretos de cliente, archivos
.env*o el registro. El.gitignoredel repositorio cubre*token*.json,*credentials*.json,*client_secret*.json,.env*y*ledger*.json. - El registro (
.youtube-upload-ledger.json) es la fuente de verdad de lo que se ha publicado. Se guarda después de cada subida individual. No lo elimines para "reintentar"; usa--force-duplicatesolo si el usuario realmente quiere una segunda copia. - Cuota: un proyecto obtiene 10.000 unidades/día por defecto y una subida históricamente ha costado 1.600 unidades (unas 6 subidas/día).
--max-uploads(por defecto 6) detiene una ejecución antes de agotar la cuota;--units-per-uploadajusta la estimación si Google cambia el costo. En caso dequotaExceeded, la ejecución se detiene y los trabajos restantes pueden re-ejecutarse al día siguiente (el registro salta los ya realizados). - Títulos: sin marcadores de posición (TODO, sin título,
{{...}}), máximo 100 caracteres, sin<o>. Las etiquetas tienen un máximo total de 500 caracteres. La validación lo exige. - Los proyectos de API no verificados pueden forzar las subidas a privado hasta que Google audite la aplicación; informa al usuario si cada subida resulta privada.
Verificar
Cada resultado tiene un videoId (abre https://youtu.be/<id> mientras aún sea privado) o una razón skipped. node scripts/upload.mjs --check-auth prueba las credenciales sin subir.