- Video detail (done videos): added 'Download audio' button; removed the
manual 'Thumbnail' button (thumbnails auto-download now, so it was redundant).
- New 'GET /api/videos/{id}/audio' endpoint (also serves HEAD for probing),
serving data/audio/<video_id>.mp3. Audio job outtmpl switched to %(id)s so
files are addressable per video.
- Integrated <audio> player appears in the detail view once the MP3 is present
(probed via HEAD on openVideo; polled after a download job until ready).
- Synced transcript follower: as audio plays, the matching segment is
highlighted (seg-active) and auto-scrolled into view like a karaoke/lyrics
tracker. Clicking any segment timestamp or chapter seeks the audio to that
point (falls back to scroll when no audio). Playback indicator pulses while
playing.
1 line
8.3 KiB
JSON
1 line
8.3 KiB
JSON
{"nodes": [{"id": "docs_superpowers_specs_2026_07_26_platform_design", "label": "Platform Design Spec", "file_type": "document", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_monorepo_architecture", "label": "Architecture: Monorepo in-package webapp (Approach A)", "file_type": "rationale", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a73", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "FastAPI app lives inside src/yt_scraper/webapp/ and reuses Store + pipeline modules directly; one process serves SPA, JSON API, and SSE. Rejected: separate top-level package (doubles plumbing), separate processes sharing only DB (duplicates query logic, breaks the one-platform feel)."}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_no_ai_scope", "label": "Scope rule: No AI features", "file_type": "rationale", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a71, \u00a714", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Data-mining + content focus only. Explicitly excluded: LLM summaries, Q&A/RAG, NER (spaCy), speaker diarization (pyannote). CLI stats/clip/thumbnails/translation also dropped; aggregate queries still exist internally to feed the dashboard."}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_dark_command_center", "label": "Design language: dark data command center", "file_type": "concept", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a77.2", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Near-black canvas (zinc-950), glassy cards (backdrop-blur), red->rose accent gradient as a creator-content nod, monospace data accents, smooth Alpine x-transitions. Charts via Chart.js with theme-matched grid/text colors."}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5", "label": "transcript_segments + FTS5 external-content table", "file_type": "concept", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a75.2", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "FTS5 external-content table over transcript_segments(text). Manual populate_fts (delete+insert) after store_segments rather than triggers - simpler and idempotent. Queries via MATCH + join. Populated during scrape AND by one-time backfill from .md."}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner", "label": "Single-threaded scrape job runner + SSE event bus", "file_type": "concept", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a77.1 (jobs.py)", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "queue.Queue worker runs scrape jobs sequentially to avoid concurrent yt-dlp hammering. Emits SSE events (progress, log, done, error). Persisted in scrape_jobs table. Active cookie from vault is auto-passed as cookies_file to every job."}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux", "label": "Cookie drag-and-drop vault UX", "file_type": "concept", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a78", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Drop zone accepts multiple .txt files or pasted Netscape text. parse_netscape validates, extracts earliest expiry, detects session cookies (SID, SAPISID, __Secure-3PSID, LOGIN_INFO). Exactly one cookie active globally; path passed to yt-dlp as cookiefile."}, {"id": "docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix", "label": "cli.py cookies scope bug fix", "file_type": "rationale", "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a72, \u00a76.2 (cli.py:228-229)", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "_process_one() references cookies/cookies_from_browser local to main() - out of scope. Fix: thread both through _process_one signature; when neither flag given, fall back to active vault cookie via cookies.resolve_active_path() so the webapp selection also works for CLI."}], "edges": [{"source": "docs_superpowers_specs_2026_07_26_platform_design", "target": "opportunities", "relation": "cites", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a71", "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design", "target": "docs_superpowers_specs_2026_07_26_platform_design_monorepo_architecture", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a73", "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design", "target": "docs_superpowers_specs_2026_07_26_platform_design_no_ai_scope", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a71, \u00a714", "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design_no_ai_scope", "target": "opportunities_llm_summaries", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a714", "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design_no_ai_scope", "target": "opportunities_rag_qa", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a714", "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design", "target": "docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": "\u00a72, \u00a76.2", "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5", "target": "docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": null, "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux", "target": "docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": null, "weight": 1.0}, {"source": "docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix", "target": "docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "fts5_search_flow", "label": "FTS5 transcript search flow (proposal -> spec -> SPA view)", "nodes": ["opportunities_search_fts5", "docs_superpowers_specs_2026_07_26_platform_design_transcript_fts5", "src_yt_scraper_webapp_static_index"], "relation": "form", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md"}, {"id": "cookie_auth_chain", "label": "Cookie auth chain (vault -> resolve_active_path -> scrape job)", "nodes": ["docs_superpowers_specs_2026_07_26_platform_design_cookie_vault_ux", "docs_superpowers_specs_2026_07_26_platform_design_sse_job_runner", "docs_superpowers_specs_2026_07_26_platform_design_cookies_bug_fix", "src_yt_scraper_webapp_static_index"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/superpowers/specs/2026-07-26-platform-design.md"}]} |