clipwise: video largo -> Shorts verticales
Todo se ejecuta localmente (CPU es suficiente; CUDA se usa para transcripción cuando está presente).
SKILL_DIR debajo significa la carpeta donde se encuentra este archivo. Todos los comandos son
python3 SKILL_DIR/scripts/run.py ...; los scripts cambian al venv de clipwise automáticamente.
Los trabajos se escriben en ~/clipwise-work/<job>/ ($CLIPWISE_WORK), o en --workdir DIR.
0. Verificación de configuración (cada sesión, una vez)
python3 SKILL_DIR/scripts/run.py check
Debe terminar con ready. Si no, dile al usuario que clipwise necesita una configuración única (aproximadamente
2 GB: paquetes de Python más el modelo whisper), pídele que lea SKILL_DIR/setup.sh, y
ejecute bash SKILL_DIR/setup.sh una vez que esté de acuerdo. Si falta ffmpeg o Python 3.10+: setup.sh imprime
el comando de instalación para su sistema operativo; no instales paquetes del sistema sin preguntar.
Flujo de trabajo
- Preparación (obtener + transcribir, un comando):
Salida en la carpeta del trabajo:python3 SKILL_DIR/scripts/run.py prep "<ruta o enlace>" --job <nombre> [--start S --max-seconds N] [--cookies cookies.txt] [--model large-v3-turbo] [--language xx]source.mp4(primer video + flujo de audio, SDR, CFR 30 cuando se recodifica),probe.json,transcript.txt(una línea[inicio-fin] (wN) textopor segmento, en segundos de la fuente),transcript.json,words.tsv. Para videos largos usa--start/--max-secondsen la parte que vale la pena recortar; la transcripción es aproximadamente 0.6-1x en tiempo real en CPU. - Elige los momentos tú mismo. Lee
transcript.txt(y cualquier línea# WARNINGal inicio) conSKILL_DIR/references/viral-rubric.md. Escribe<job>/picks.json: cada selección de 10-50 s, gancho primero, final limpio. Cuántas: consulta la regla abajo. - Obtén aprobación antes de renderizar. Muestra una línea por selección: marcas de tiempo, gancho, título, explicación de una línea. Renderizar cuesta aproximadamente 1-2 minutos por clip en una CPU pequeña. Si escribiste texto de subtítulos a mano (discurso no inglés o mixto), muestra esas líneas también.
- Renderiza:
Por selección enpython3 SKILL_DIR/scripts/run.py render --job <nombre> [--fast] [--only 2] [--music bed.mp3]<job>/out/:clip_<id>.mp4,clip_<id>.txt(título, descripción, comentario fijado, hashtags, por qué),clip_<id>.json(números de sonda, diseño, cobertura facial, SFX, tiempos),clip_<id>_cutmap.json,clip_<id>_sheet.png.--fast= calidad de previsualización. - Revisa cada
clip_<id>_sheet.pngcon tu herramienta de imagen/visión (10 fotogramas; línea roja = y 1620, interfaz de plataforma debajo). Verifica: cara en el encuadre, subtítulos legibles, subtítulos no sobre la cara, nada importante debajo de la línea roja, color no desteñido. Corrige (selecciones, anulaciones de subtítulos,--layout,--font-size) y vuelve a renderizar con--only <id>. - Entrega las rutas MP4 y el contenido de
.txt. Ofrecerun.py clean --job <nombre>(eliminasource.mp4y directorios temporales, conservaout/).
Cuántos Shorts por video
-
El usuario especificó un número ("Haz 5 Shorts desde "): haz exactamente esa cantidad. Si el video no tiene suficientes momentos sólidos, dilo antes de renderizar y propón el número honesto ("Encontré 3 momentos que pasan la lista de verificación; los otros 2 serían débiles").
-
No se dio número: escala según la duración de la fuente (o de la ventana transcrita):
duración de la fuente Shorts menos de 5 min 1-2 5-15 min 3-5 15-45 min 5-8 45 min+ (podcast, charla) 8-15 -
Solo cuentan los momentos que pasan la lista de verificación de la rúbrica. Nunca añadas clips débiles para alcanzar un número.
picks.json (mínimo)
[{"id": "1", "start": 65.5, "end": 110.3, "title": "¿Cada inundación es causada por el cambio climático?",
"hook_start": 74.85, "hook_end": 80.1, "payoff_start": 102.0,
"why": "Afirmación inesperada primero, la resuelve al final.", "comment_bait": "¿Sabías esto?",
"description": "...", "hashtags": ["#shorts", "#climate"],
"caption_overrides": [{"w": 219, "text": ""}, {"start": 90.1, "end": 92.4, "text": "palabras exactas aquí"}]}]
Requerido: id, start, end (segundos de la fuente). hook_start/hook_end mueve una línea de 2-3 s al
principio ("hook_mode": "repeat" la mantiene también en el cuerpo). payoff_start coloca el golpe bajo.
caption_overrides: {"w": N, "text": ""} edita/elimina la palabra N ((wN) en
transcript.txt, i en words.tsv); {"start", "end", "text"} reemplaza todas las palabras en ese intervalo.
Esquema completo y puntuación: references/viral-rubric.md.
Banderas de renderizado
| bandera | efecto |
|---|---|
--fast | x264 ultrafast CRF 24, muestreo facial de 4 fps (previsualización). Predeterminado: preset faster, CRF 20 |
--only ID | renderiza una selección (repetible) |
| `--layout auto | crop |
--music FILE | música de fondo proporcionada por el usuario, aproximadamente 17 LU por debajo de la voz, con reducción por compresión sidechain. --music-db 20 = más silenciosa |
--sfx-dir DIR | usa tus propios whoosh_fast, whoosh_soft, thud_low, pop, tick (.wav/.mp3/.flac/.ogg) en lugar de los sintetizados |
--no-sfx, --no-silence-cut | desactiva esas opciones |
--font "Lato Black", --font-size 84, `--highlight yellow | green, --no-upper` |
--preset, --crf, --keep-tmp | anulaciones del codificador; conserva los wav de voz/mezcla y captions.ass para depuración |
Variables de entorno: CLIPWISE_HOME (por defecto ~/.clipwise), CLIPWISE_VENV, CLIPWISE_WORK,
CLIPWISE_MODEL (por defecto large-v3-turbo), CLIPWISE_DEVICE (auto|cpu|cuda).
Lo que hace el renderizado por selección
El gancho se mueve al principio, los silencios > 0.35 s se cortan (umbral basado en los niveles de habla/ruido propios del clip), las piezas restantes se ajustan a la cuadrícula de 30 fps para que las muestras de audio igualen los fotogramas. Seguimiento facial con YuNet en los fotogramas que sobreviven al corte: cara dominante, pegajoso (una nueva cara debe ser 1.6x más grande durante 1.2 s para tomar el control), cámara suave con zona muerta, ajustes solo en cortes. Zoom de acercamiento 1.0/1.12 cada 2-4 s. Subtítulos ASS palabra por palabra (máximo 4 palabras, palabra activa resaltada) colocados debajo de la barbilla y por encima de y 1620. Limpieza de voz, SFX sintetizados, música opcional con reducción, dos pasadas de loudnorm a -14 LUFS / -1.5 dBTP. H.264 + AAC 48 kHz, 1080x1920, 30 fps. Se verifican las duraciones finales de los flujos A/V.
Tiempos medidos (CPU de 2 núcleos, sin GPU)
| paso | medido |
|---|---|
| fetch: descarga web de 85 MB 1080p VP9 + ventana de 3 min recodificación a H.264 | 7.7 min total (descarga dominante, aproximadamente 5 min) |
| fetch: clip iPhone de 20 s 10-bit HDR (tone-map + CFR) | 45 s (HDR cuesta aproximadamente 2.3x la duración) |
| transcribir large-v3-turbo, 3 min en inglés | 110 s ASR (0.61x tiempo real) + 19 s carga del modelo |
| renderizar predeterminado, clip de 40.6 s | 85 s |
renderizar --fast, clip de 26.4 s / clip pad de 17.1 s | 32 s / 30 s |
Errores comunes
- Muro de bots de YouTube ("Inicia sesión para confirmar que no eres un bot"): intermitente, dependiente de la IP.
fetch sale con código 3. Pide al usuario
--cookies cookies.txt(exportado desde su navegador) o el archivo mismo / un enlace de Drive o Dropbox. No iteres sobre clientes de reproductor o proxies de yt-dlp. Los enlaces privados de Drive salen con código 2: pide compartir con "cualquiera que tenga el enlace" o un archivo local. - La sincronía A/V es una regla estricta. Las duraciones de los flujos de audio y video de cada salida deben coincidir
dentro de 0.1 s (el renderizado lo verifica). Nunca recortes con copia de flujo en un inicio no cero, nunca
cortes audio con
aselect; usa los scripts. - La receta ASR es fija: normaliza el audio primero, detecta automáticamente el idioma, sin VAD, sin
initial_prompt(filtra en la transcripción). Mantén large-v3-turbo;smallitera y alucina en habla con acento o mixta (la transcripción advierte sobre iteraciones). - El habla no inglesa puede venir traducida. Para muchos idiomas escritos en una
escritura no latina (y para habla mixta) whisper devuelve inglés. La transcripción entonces
es solo una guía de tiempos y significado: escribe las líneas de subtítulos en el idioma y escritura propios del hablante
con
caption_overridesen intervalos{"start", "end", "text"}, y muéstralos al usuario antes de renderizar. Los títulos y hashtags también siguen el idioma del hablante. - Subtítulos: nunca sobre la cara, y por encima de la parte inferior ~300 px (interfaz de plataforma). Si la
hoja muestra un conflicto, acorta la selección, usa
--layout pad, o baja--font-size. - El rastreador sigue la cara más grande, no al hablante. Para dos personas hablando en una
toma amplia, usa
--layout pad, o elige una ventana donde hable una sola persona. - Escalado: una fuente 1080p 16:9 se recorta a 608x1080 y se escala 1.8x; las fuentes 720p se escalan 2.7x y se ven suaves. Prefiere descargas de 1080p+.
- CPUs pequeñas: nunca ejecutes dos codificaciones, o transcripción y una codificación, al mismo tiempo; renderiza las selecciones una tras otra (run.py ya lo hace).