Skip to content

Instantly share code, notes, and snippets.

@lucasgrow
Created February 25, 2026 18:36
Show Gist options
  • Select an option

  • Save lucasgrow/b340c5082088804fccf2aecb42187491 to your computer and use it in GitHub Desktop.

Select an option

Save lucasgrow/b340c5082088804fccf2aecb42187491 to your computer and use it in GitHub Desktop.
🎬 Reels Playbook Generator - 100% bash, zero Python (OpenRouter + Gemini + Groq)
# API Keys para Reels Playbook Generator
# Groq (transcrição com Whisper) - https://console.groq.com/
GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxx
# OpenRouter (vision e texto) - https://openrouter.ai/
OPENROUTER_API_KEY=sk-or-xxxxxxxxxxxxxxxxxxxxx
# HikerAPI (fallback para Instagram) - https://hikerapi.com/
HIKERAPI_KEY=xxxxxxxxxxxxxxxxxxxxx
# Modelos (opcional - defaults para Gemini Flash)
VISION_MODEL=google/gemini-2.5-flash-preview
TEXT_MODEL=google/gemini-2.5-flash-preview
#!/bin/bash
# Uso: ./01-download.sh "https://instagram.com/reel/xxx" [output_dir]
URL="$1"
OUTPUT_DIR="${2:-/tmp/reels-workdir}"
mkdir -p "$OUTPUT_DIR"
cd "$OUTPUT_DIR"
echo "Trying yt-dlp..."
yt-dlp "$URL" \
--format "best[height<=1080]" \
--output "video.%(ext)s" \
--write-info-json \
--no-playlist 2>/dev/null
# Converter para mp4 se necessário
if [ -f video.webm ]; then
ffmpeg -i video.webm -c copy video.mp4 -y
rm video.webm
fi
# Se yt-dlp falhou, tentar hikerapi (Instagram)
if [ ! -f video.mp4 ]; then
echo "yt-dlp failed, trying hikerapi..."
# Extrair shortcode do URL do Instagram
SHORTCODE=$(echo "$URL" | grep -oP '(?<=reel/|p/)[^/?]+')
if [ -n "$SHORTCODE" ] && [ -n "$HIKERAPI_KEY" ]; then
# Buscar info do post
RESPONSE=$(curl -s "https://api.hikerapi.com/v1/instagram/media/by/shortcode?shortcode=$SHORTCODE" \
-H "x-access-key: $HIKERAPI_KEY")
# Extrair URL do vídeo
VIDEO_URL=$(echo "$RESPONSE" | jq -r '.video_url // .video_versions[0].url // empty')
if [ -n "$VIDEO_URL" ]; then
echo "Downloading from hikerapi..."
curl -sL "$VIDEO_URL" -o video.mp4
# Salvar metadata
echo "$RESPONSE" | jq '{
title: .caption.text,
duration: .video_duration,
webpage_url: "https://instagram.com/reel/'"$SHORTCODE"'",
extractor: "hikerapi"
}' > video.info.json
fi
fi
fi
if [ -f video.mp4 ]; then
echo "Downloaded to: $OUTPUT_DIR/video.mp4"
else
echo "ERROR: Failed to download video"
exit 1
fi
#!/bin/bash
# Uso: ./02-extract-frames.sh [fps] [workdir]
FPS="${1:-2}"
WORKDIR="${2:-/tmp/reels-workdir}"
cd "$WORKDIR"
mkdir -p frames
ffmpeg -i video.mp4 \
-vf "fps=$FPS,scale=720:-1" \
-q:v 2 \
frames/frame_%04d.jpg -y
FRAME_COUNT=$(ls frames/*.jpg 2>/dev/null | wc -l)
DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 video.mp4)
echo "Extracted $FRAME_COUNT frames at ${FPS}fps"
echo "Video duration: ${DURATION}s"
#!/bin/bash
# Uso: ./03-transcribe.sh [workdir]
WORKDIR="${1:-/tmp/reels-workdir}"
cd "$WORKDIR"
# Extrair áudio
ffmpeg -i video.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 audio.wav -y
# Transcrever com Groq
curl -s "https://api.groq.com/openai/v1/audio/transcriptions" \
-H "Authorization: Bearer $GROQ_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F file="@audio.wav" \
-F model="whisper-large-v3-turbo" \
-F response_format="verbose_json" \
-F language="pt" \
> transcript.json
jq -r '.text' transcript.json > transcript.txt
jq -r '.segments[] | "\(.start | floor)s: \(.text)"' transcript.json > transcript_timed.txt
echo "Transcription:"
cat transcript.txt
#!/bin/bash
# Analisa frames usando Gemini via OpenRouter
# Uso: ./04-analyze-frames.sh [workdir]
WORKDIR="${1:-/tmp/reels-workdir}"
FRAMES_DIR="$WORKDIR/frames"
OUTPUT_FILE="$WORKDIR/frame_analysis.json"
MODEL="${VISION_MODEL:-google/gemini-2.5-flash-preview}"
# Contar frames
FRAME_COUNT=$(ls "$FRAMES_DIR"/*.jpg 2>/dev/null | wc -l)
echo "Found $FRAME_COUNT frames to analyze"
# Processar em batches de 10
BATCH_SIZE=10
ALL_RESULTS="[]"
for ((i=1; i<=FRAME_COUNT; i+=BATCH_SIZE)); do
END=$((i + BATCH_SIZE - 1))
if [ $END -gt $FRAME_COUNT ]; then END=$FRAME_COUNT; fi
echo "Analyzing frames $i-$END..."
# Construir array de imagens para o request
IMAGES_JSON="["
FIRST=true
for ((j=i; j<=END; j++)); do
FRAME_FILE=$(printf "$FRAMES_DIR/frame_%04d.jpg" $j)
if [ -f "$FRAME_FILE" ]; then
BASE64_IMG=$(base64 -w0 "$FRAME_FILE")
if [ "$FIRST" = true ]; then
FIRST=false
else
IMAGES_JSON+=","
fi
IMAGES_JSON+="{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/jpeg;base64,$BASE64_IMG\"}}"
fi
done
IMAGES_JSON+="]"
# Prompt
PROMPT='Analise estes frames sequenciais de um vídeo viral.
Para CADA frame, identifique:
1. Shot: tipo de enquadramento (close, medium, wide, POV)
2. Cena: descrição breve
3. Overlay: texto na tela (se houver)
4. Transição: se houve corte em relação ao frame anterior
5. Elementos: props, produtos, efeitos
Retorne APENAS um JSON array (sem markdown):
[{"frame":1,"shot":"close-up","scene":"descrição","overlay":{"text":"TEXTO","position":"top"},"transition":"none","elements":["item1"]}]'
# Construir request body
REQUEST_BODY=$(jq -n \
--arg model "$MODEL" \
--argjson images "$IMAGES_JSON" \
--arg prompt "$PROMPT" \
'{
model: $model,
max_tokens: 4096,
messages: [{
role: "user",
content: ($images + [{type: "text", text: $prompt}])
}]
}')
# Fazer request
RESPONSE=$(curl -s "https://openrouter.ai/api/v1/chat/completions" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d "$REQUEST_BODY")
# Extrair conteúdo
CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content // empty')
# Tentar extrair JSON array do conteúdo
BATCH_JSON=$(echo "$CONTENT" | grep -oP '\[[\s\S]*\]' | head -1)
if [ -n "$BATCH_JSON" ]; then
# Ajustar números dos frames
ADJUSTED=$(echo "$BATCH_JSON" | jq --argjson offset $((i-1)) '[.[] | .frame = .frame + $offset]')
ALL_RESULTS=$(echo "$ALL_RESULTS" "$ADJUSTED" | jq -s 'add')
fi
sleep 1 # Rate limiting
done
# Salvar resultado
echo "$ALL_RESULTS" | jq '.' > "$OUTPUT_FILE"
echo "Analysis saved to $OUTPUT_FILE"
#!/bin/bash
# Gera PLAYBOOK.md a partir das análises
# Uso: ./05-generate-playbook.sh [workdir]
WORKDIR="${1:-/tmp/reels-workdir}"
OUTPUT_FILE="$WORKDIR/PLAYBOOK.md"
MODEL="${TEXT_MODEL:-google/gemini-2.5-flash-preview}"
echo "Loading data..."
# Carregar dados
FRAMES=$(cat "$WORKDIR/frame_analysis.json" 2>/dev/null | head -c 15000)
TRANSCRIPT=$(cat "$WORKDIR/transcript.txt" 2>/dev/null)
TIMED_TRANSCRIPT=$(cat "$WORKDIR/transcript_timed.txt" 2>/dev/null)
# Metadata
TITLE="Desconhecido"
DURATION="N/A"
URL="N/A"
INFO_FILE=$(ls "$WORKDIR"/*.info.json 2>/dev/null | head -1)
if [ -f "$INFO_FILE" ]; then
TITLE=$(jq -r '.title // "Desconhecido"' "$INFO_FILE")
DURATION=$(jq -r '.duration // "N/A"' "$INFO_FILE")
URL=$(jq -r '.webpage_url // "N/A"' "$INFO_FILE")
fi
echo "Generating playbook..."
# Construir prompt
PROMPT="Você é um especialista em produção de vídeos virais.
Com base na análise abaixo, gere um PLAYBOOK detalhado de produção.
## DADOS DO VÍDEO
**Título:** $TITLE
**Duração:** ${DURATION}s
**URL:** $URL
## TRANSCRIÇÃO
$TRANSCRIPT
## TRANSCRIÇÃO COM TIMESTAMPS
$TIMED_TRANSCRIPT
## ANÁLISE DE FRAMES
$FRAMES
---
Gere um PLAYBOOK.md completo com:
1. **MÉTRICAS DE EDIÇÃO** - cortes/segundo, total de overlays, estilo
2. **ESTRUTURA GERAL** - tabela com seções (Hook, Setup, Conteúdo, CTA)
3. **DECUPAGEM DETALHADA** - cada seção com visual, áudio, texto, edição
4. **ELEMENTOS DE PRODUÇÃO** - paleta, tipografia, transições, trilha
5. **FÓRMULA REPLICÁVEL** - template com timestamps
6. **CHECKLIST DE PRODUÇÃO** - pré-produção, gravação, edição
7. **INSIGHTS** - 3+ insights para replicar
Seja detalhista. Capture texto exato dos overlays.
Retorne APENAS o markdown do playbook, sem code blocks."
# Fazer request
RESPONSE=$(curl -s "https://openrouter.ai/api/v1/chat/completions" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg model "$MODEL" \
--arg prompt "$PROMPT" \
'{
model: $model,
max_tokens: 8000,
messages: [{role: "user", content: $prompt}]
}')")
# Extrair conteúdo
CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content // empty')
if [ -z "$CONTENT" ]; then
echo "ERROR: Failed to generate playbook"
echo "$RESPONSE" | jq .
exit 1
fi
# Limpar markdown code blocks se houver
CONTENT=$(echo "$CONTENT" | sed '/^```markdown$/d' | sed '/^```$/d')
# Salvar
echo "$CONTENT" > "$OUTPUT_FILE"
echo "Playbook saved to $OUTPUT_FILE"

🎬 Reels Playbook Generator

Pipeline 100% bash para análise de vídeos virais e geração de playbooks de produção.

Zero Python. Zero venv. Só bash + curl.

O que faz

  1. Baixa o vídeo (yt-dlp ou HikerAPI fallback)
  2. Extrai frames em alta densidade (2fps)
  3. Transcreve o áudio com Whisper (via Groq)
  4. Analisa cada frame com Gemini Vision
  5. Gera um PLAYBOOK.md detalhado

Dependências

sudo apt install ffmpeg jq curl
pip install -U yt-dlp

Quick Start

# 1. Configurar API keys
cp .env.example .env
# Editar .env:
# - GROQ_API_KEY (transcrição)
# - OPENROUTER_API_KEY (vision + texto)
# - HIKERAPI_KEY (fallback Instagram - opcional)

# 2. Tornar executável
chmod +x *.sh

# 3. Carregar variáveis
source .env

# 4. Processar um Reels
./generate-playbook.sh "https://www.instagram.com/reel/XXXXX/"

Estrutura do Output

/tmp/reels-XXXXX/
├── video.mp4           # Vídeo original
├── audio.wav           # Áudio extraído
├── transcript.txt      # Transcrição
├── transcript_timed.txt # Com timestamps
├── frame_analysis.json # Análise de cada frame
├── PLAYBOOK.md         # Playbook final
└── frames/
    └── frame_XXXX.jpg  # Frames extraídos

Custo Estimado

Componente Custo/vídeo
Groq Whisper ~$0.00 (free tier)
Gemini Flash (vision) ~$0.01-0.05
Gemini Flash (playbook) ~$0.01-0.02
Total ~$0.02-0.07

Modelos (via OpenRouter)

Configurar em .env:

VISION_MODEL=google/gemini-2.5-flash-preview  # default
TEXT_MODEL=google/gemini-2.5-flash-preview    # default

Alternativas:

  • google/gemini-2.5-pro-preview (melhor qualidade)
  • anthropic/claude-sonnet-4
  • openai/gpt-4o

Scripts

Script Função
generate-playbook.sh Orquestrador principal
01-download.sh Baixa vídeo (yt-dlp + HikerAPI)
02-extract-frames.sh Extrai frames (ffmpeg)
03-transcribe.sh Transcreve (Groq Whisper)
04-analyze-frames.sh Analisa frames (Gemini)
05-generate-playbook.sh Gera PLAYBOOK.md

Batch Processing

# Criar arquivo com URLs
cat > urls.txt << 'URLS'
https://www.instagram.com/reel/ABC123/
https://www.instagram.com/reel/DEF456/
URLS

# Processar todos
source .env
for url in $(cat urls.txt); do
  ./generate-playbook.sh "$url"
done
#!/bin/bash
# REELS PLAYBOOK GENERATOR
# Uso: ./generate-playbook.sh "https://instagram.com/reel/xxx" [output_dir]
set -e
URL="$1"
OUTPUT_DIR="${2:-/tmp/reels-$(date +%s)}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
if [ -z "$URL" ]; then
echo "Uso: $0 <url> [output_dir]"
echo "Exemplo: $0 'https://www.instagram.com/reel/ABC123/'"
exit 1
fi
# Carregar variáveis de ambiente
if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
fi
echo "========================================"
echo "🎬 REELS PLAYBOOK GENERATOR"
echo "========================================"
echo "URL: $URL"
echo "Output: $OUTPUT_DIR"
echo ""
mkdir -p "$OUTPUT_DIR"
# Passo 1: Download
echo "[1/5] 📥 Downloading video..."
"$SCRIPT_DIR/01-download.sh" "$URL" "$OUTPUT_DIR"
# Passo 2: Extrair frames
echo ""
echo "[2/5] 🖼️ Extracting frames (2fps)..."
"$SCRIPT_DIR/02-extract-frames.sh" 2 "$OUTPUT_DIR"
# Passo 3: Transcrever
echo ""
echo "[3/5] 🎤 Transcribing audio..."
"$SCRIPT_DIR/03-transcribe.sh" "$OUTPUT_DIR"
# Passo 4: Analisar frames
echo ""
echo "[4/5] 👁️ Analyzing frames with vision..."
"$SCRIPT_DIR/04-analyze-frames.sh" "$OUTPUT_DIR"
# Passo 5: Gerar playbook
echo ""
echo "[5/5] 📝 Generating playbook..."
"$SCRIPT_DIR/05-generate-playbook.sh" "$OUTPUT_DIR"
echo ""
echo "========================================"
echo "✅ DONE!"
echo "========================================"
echo ""
echo "📁 Files:"
echo " Video: $OUTPUT_DIR/video.mp4"
echo " Frames: $OUTPUT_DIR/frames/"
echo " Transcript: $OUTPUT_DIR/transcript.txt"
echo " Analysis: $OUTPUT_DIR/frame_analysis.json"
echo " Playbook: $OUTPUT_DIR/PLAYBOOK.md"
echo ""
echo "📖 Preview:"
head -50 "$OUTPUT_DIR/PLAYBOOK.md"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment