Skip to content

Wave 2: Script quality and other changes - #1

Merged
mdev34-lab merged 23 commits into
masterfrom
fix/script-quality
May 26, 2026
Merged

Wave 2: Script quality and other changes#1
mdev34-lab merged 23 commits into
masterfrom
fix/script-quality

Conversation

@mdev34-lab

Copy link
Copy Markdown
Owner

PR: fix/script-quality

Summary

20 commits focused on script quality, data sanity, and pipeline robustness for explainer videos.

Changes

🎬 Script Generation (script_generator.py)

  • No more hyperboles: Replaced "dramatic/scandalous" tone with "curiosity-driven/narrative". Explicitly banned exaggerations like "designed by a god", "shocking truth".
  • Hook in the first 2 seconds: First sentence now drops the viewer straight into the action (the goal, the controversy). No "Get ready", "Did you know", rhetorical questions.
  • Broken hallucination loop: Search queries are now generated independently (not derived from the draft), followed by post-generation fact verification.
  • Validated titles: Checks for hashtags (min 3), length (max 100 chars), auto-lowercases uppercase hashtags. Retries with feedback if validation fails.
  • Paragraph repair: Instead of discarding scripts with filler, attempts repair via API.
  • Fact verification retry: If the API returns fewer than 3 paragraphs during verification, retries with explicit corrective feedback.

🔧 Robustness

  • _make_json_api_call: Added isinstance(result, dict) guard — API could return an array and crash all .get() callers.
  • _validate_paragraphs: Added isinstance(p, str) and filter — LLM sometimes returns dicts instead of strings.
  • video_background.py: Fixed .lower() crash on None title from yt-dlp. Changed r["href"]r.get("href") to prevent KeyError.
  • web_search.py: Changed r["snippet"]r.get("snippet") to prevent KeyError.
  • tts_system.py: Added try/except with fallback for float("") crash when ffprobe fails.
  • explainer.py: Sanitized output filenames (?, :, ", etc) — Windows FFmpeg crashed on invalid characters.

🖼️ Image Searcher

  • NSFW filter: Blocked domains (crossdresser, hentai, porn, onlyfans, etc) and keywords in DDGS image titles/URLs.

🧪 CLI

  • --batch: Now accepts a single string with semicolon-separated topics instead of list[str].

🧹 Type Safety

  • Mypy: 14 → 0 real errors (stubs ignored). Ruff clean.

Files Changed

13 files, +814/−227

mdev34-lab added 23 commits May 24, 2026 11:39
… FFmpeg 0-byte read at EOF

Adiciona _ensure_duration() que faz loop dos clips fonte com
concatenate_videoclips() para garantir que cubram todo o
target_duration. Aplica em _create_with_overlay_mode (blurred
bg e fg) e _create_simple_mode.

Antes: FFMPEG_VideoReader devolvia 0 bytes ao ler frames além
do fim do arquivo -> MoviePy silenciava com 'using last valid
frame' -> output congelado e render acelerava artificialmente
sem fazer decode real.
The Resize effect changes pixel dimensions but leaves clips at the default
top-left (0,0) position, making the zoom appear anchored to the corner.
Adding with_position(('center', 'center')) centers the clip dynamically
at each frame, so the zoom emerges from the center.
- Remove FALLBACK_PARAGRAPHS ('No final fica uma licao...') entirely
- Remove 'Do NOT fact-check yourself' from the draft prompt
- Add _is_filler() and _validate_paragraphs() to detect/reject vague paragraphs
- All prompts now require: verifiable fact per paragraph, factual conclusion,
  correct date calculation, explicit ban on 'fica uma licao'
- Pipeline now fails early (return False) if generated script has <3 paragraphs
- Search queries with more specific terms (fundacao, dados, estatisticas)
…t-generation fact verification

- Replace draft-derived LLM queries with _generate_search_queries(): a separate
  LLM call with a neutral prompt that has never seen the draft, eliminating the
  circular 'draft -> queries confirming draft -> more draft' loop
- Add _verify_factual_claims(): extracts all years from the generated script,
  searches each year + subject via DDGS, then calls the LLM as a strict
  fact-checker to cross-reference every claim against web sources
- Add _generate_title_from_script(): generates title from final script instead of draft
- Update all tests for the new 3-call flow (queries -> script -> title)
…language

Every prompt now includes TONE (dramatic/scandalous), FIRST SENTENCE (hook, not dry date), STRUCTURE (Hook -> Context -> Drama -> Ending), and FORBIDDEN (Ltda, S.A., addresses, corporate speak). _is_filler() expanded to catch legal/corporate patterns. Paragraphs shortened to 1-2 punchy sentences.
The old prompt forced terms like 'explicado', 'documentario', 'reportagem', 'historia' into every query, causing YouTube to return generic explainer videos (e.g. FNAF explainers) instead of subject-specific content. Removed those keywords and the 'family-friendly educational' framing. Now the LLM generates specific queries with concrete names and events.
…inst subject

- _repair_paragraphs(): generate only missing paragraphs via LLM instead of full draft regeneration

- _is_suitable_video(): reject videos whose title lacks subject keywords

- _generate_title_from_script: PT-BR prompt to avoid mixed-language titles

- _verify_factual_claims: extract scores, tabus, and date contexts alongside years

- Consolidate all prompts to use _tone_instructions() - remove duplicated tone rules
@mdev34-lab
mdev34-lab merged commit bd76690 into master May 26, 2026
0 of 3 checks passed
@mdev34-lab
mdev34-lab deleted the fix/script-quality branch June 6, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant