feat: youtube handler analizeaza cu Claude; nota Grantham completă
- dashboard/handlers/youtube.py: după descărcare transcriere, cheamă `claude -p` cu un prompt structurat care generează TL;DR + puncte cheie + citate + idei acționabile + secțiuni tematice în proze. Fallback la transcriptul brut dacă Claude eșuează. - nota Grantham: format complet — TL;DR, puncte cheie, citate, idei acționabile, secțiuni tematice în proze curgătoare. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,49 @@ def _extract_relevant_description(description):
|
||||
return '\n'.join(result_lines)
|
||||
|
||||
|
||||
ANALYSIS_PROMPT = """\
|
||||
Ai primit transcriptul unui video YouTube și descrierea lui. Scrie o notiță KB în română, format Markdown.
|
||||
|
||||
Structura notei (în ordine):
|
||||
1. ## TL;DR — un paragraf de 3-5 rânduri care surprinde esența
|
||||
2. ## Puncte cheie — 6-10 puncte concise (pot fi bullets, dar scurte și dense)
|
||||
3. ## Quote-uri memorabile — 4-6 citate directe din transcript, în limba originală, între ghilimele
|
||||
4. ## Idei acționabile — 4-8 lucruri concrete pe care cititorul le poate face
|
||||
5. Secțiuni tematice cu ## heading — câte teme apar natural, în proze curgătoare (NU bullets), fiecare cu conținut real din transcript: cifre, exemple, mecanisme, argumente
|
||||
|
||||
Nu scrie metadate (titlu, url, tags, dată) — vor fi adăugate separat.
|
||||
Nu scrie fraze introductive despre tine sau despre video. Începe direct cu ## TL;DR.
|
||||
Scrie în română. Citatele rămân în engleză dacă sursa e engleză.
|
||||
"""
|
||||
|
||||
|
||||
def _analyze_with_claude(title, description, transcript):
|
||||
"""Call claude -p to generate rich analysis of the video."""
|
||||
claude_bin = os.path.expanduser('~/.local/bin/claude')
|
||||
if not os.path.exists(claude_bin):
|
||||
claude_bin = 'claude'
|
||||
|
||||
desc_section = ""
|
||||
if description:
|
||||
desc_section = f"DESCRIERE VIDEO:\n{description[:3000]}\n\n"
|
||||
|
||||
prompt = (
|
||||
f"{ANALYSIS_PROMPT}\n\n"
|
||||
f"TITLU: {title}\n\n"
|
||||
f"{desc_section}"
|
||||
f"TRANSCRIPT (primele 40000 caractere):\n{transcript[:40000]}"
|
||||
)
|
||||
|
||||
result = subprocess.run(
|
||||
[claude_bin, '-p', prompt],
|
||||
capture_output=True, text=True, timeout=300,
|
||||
)
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
return result.stdout.strip()
|
||||
log.warning("Claude analysis failed: %s", result.stderr[:300])
|
||||
return None
|
||||
|
||||
|
||||
def _process_youtube(url):
|
||||
"""Download subtitles, save note."""
|
||||
yt_dlp = os.path.expanduser('~/.local/bin/yt-dlp')
|
||||
@@ -123,14 +166,32 @@ def _process_youtube(url):
|
||||
slug = re.sub(r'[^\w\s-]', '', title.lower())[:50].strip().replace(' ', '-')
|
||||
filename = f"{date_str}_{slug}.md"
|
||||
|
||||
# Build optional description block
|
||||
# Description block
|
||||
desc_block = ""
|
||||
if _is_description_about_video(description):
|
||||
relevant_desc = _extract_relevant_description(description)
|
||||
if relevant_desc:
|
||||
desc_block = f"\n## Descriere / Index\n\n{relevant_desc}\n\n---\n"
|
||||
|
||||
note_content = f"""# {title}
|
||||
# Claude analysis: TL;DR + puncte cheie + citate + teme în proze
|
||||
print("Running Claude analysis...")
|
||||
analysis = _analyze_with_claude(title, description, transcript)
|
||||
|
||||
if analysis:
|
||||
note_content = f"""# {title}
|
||||
|
||||
**Video:** {url}
|
||||
**Duration:** {duration // 60}:{duration % 60:02d}
|
||||
**Saved:** {date_str}
|
||||
**Tags:** #youtube
|
||||
|
||||
---
|
||||
{desc_block}
|
||||
{analysis}
|
||||
"""
|
||||
else:
|
||||
# Fallback: save raw transcript if Claude fails
|
||||
note_content = f"""# {title}
|
||||
|
||||
**Video:** {url}
|
||||
**Duration:** {duration // 60}:{duration % 60:02d}
|
||||
@@ -142,10 +203,6 @@ def _process_youtube(url):
|
||||
## Transcript
|
||||
|
||||
{transcript[:15000]}
|
||||
|
||||
---
|
||||
|
||||
*Notă: Sumarizarea va fi adăugată de Echo.*
|
||||
"""
|
||||
|
||||
constants.NOTES_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user