diff --git a/.gitignore b/.gitignore index cc6bd18..f089da1 100644 --- a/.gitignore +++ b/.gitignore @@ -246,3 +246,8 @@ video_creation/data/envvars.txt config.toml *.exe +.agents + +# Manual pipeline +manual_posts/ +manual_results/ diff --git a/BRAINSTORM_manual_screenshot_flow.md b/BRAINSTORM_manual_screenshot_flow.md new file mode 100644 index 0000000..c048f21 --- /dev/null +++ b/BRAINSTORM_manual_screenshot_flow.md @@ -0,0 +1,235 @@ +# 🧠 Brainstorming: Manual Screenshot → Video Pipeline + +> **Bối cảnh**: Không thể sử dụng Reddit API. Cần workflow mới cho phép user tự chụp screenshot từ **Reddit, Threads (Meta), X (Twitter)** rồi hệ thống tự động tạo video. +> +> **Trạng thái**: ✅ **ĐÃ IMPLEMENT** — Phase 1 hoàn tất. + +--- + +## 1. Phân Tích Vấn Đề Cốt Lõi + +### Flow hiện tại đang phụ thuộc Reddit API ở đâu? + +| Bước | Phụ thuộc API? | Chi tiết | +|------|:---:|----------| +| Lấy thread + comments | ✅ **YES** | `reddit/subreddit.py` — PRAW login, fetch post, filter comments | +| **Text cho TTS** | ✅ **YES** | `TTS/engine_wrapper.py` — lấy text từ `reddit_object["comments"]` | +| **Screenshot** | ✅ **YES** | `screenshot_downloader.py` — Playwright login Reddit, navigate, capture | +| Background video/audio | ❌ NO | `background.py` — chỉ dùng YouTube, không liên quan Reddit | +| Final video assembly | ❌ NO | `final_video.py` — chỉ dùng FFmpeg, nhưng cần `reddit_obj` dict | +| Video tracking | ❌ NO | `videos.json` — chỉ lưu metadata | + +**Kết luận**: Cần thay thế hoàn toàn **3 bước đầu** (fetch → TTS text → screenshot) bằng flow thủ công. + +--- + +## 2. Phương Án Đã Chọn: **.mp3 ưu tiên, .txt fallback** + +User cung cấp **file audio (.mp3) trực tiếp** + screenshots. TTS chỉ là fallback nếu chỉ có file `.txt`. + +``` +User chụp screenshot + cung cấp audio .mp3 → Video + (hoặc .txt fallback → TTS → Video) +``` + +### Ưu tiên audio: + +``` +Có .mp3? ──YES──▶ Dùng .mp3 trực tiếp (bỏ qua TTS) + │ + NO + │ +Có .txt? ──YES──▶ TTS sinh .mp3 từ text (fallback) + │ + NO + │ + ▼ + ⚠ SKIP (screenshot không có audio) +``` + +--- + +## 3. Cấu Trúc Đã Implement + +### 3.1 Thư mục + +``` +RedditVideoMakerBot/ +├── main.py # Flow cũ (giữ nguyên, không sửa) +├── manual_main.py # 🆕 Entry point cho flow mới +│ +├── manual/ # 🆕 Module flow mới (tách biệt hoàn toàn) +│ ├── __init__.py # Module docstring +│ ├── scanner.py # Quét folder, validate (.png + .mp3 + .txt) +│ ├── tts_processor.py # Audio processor (.mp3 ưu tiên, TTS fallback) +│ └── video_builder.py # FFmpeg pipeline (libx264 CPU) +│ +├── manual_posts/ # 🆕 Thư mục input +│ └── post_001/ +│ ├── meta.json # (optional) metadata +│ ├── 0_title.png # Screenshot bài đăng +│ ├── 0_title.mp3 # Audio (pre-recorded) +│ ├── 1_comment.png # Screenshot comment +│ └── 1_comment.mp3 # Audio comment +│ +├── manual_results/ # 🆕 Thư mục output +│ └── post_001.mp4 +│ +├── reddit/ # Flow cũ (giữ nguyên) +├── TTS/ # Shared — dùng chung TTS engines (fallback) +├── video_creation/ # Flow cũ (giữ nguyên) +└── utils/ # Shared — dùng chung utilities +``` + +### 3.2 Quy Tắc Đặt Tên File + +``` +_. +``` + +| Pattern | Ý nghĩa | Bắt buộc? | +|---------|----------|-----------| +| `0_title.png` | Screenshot bài đăng chính | ✅ Bắt buộc | +| `0_title.mp3` | Audio pre-recorded | ✅ (hoặc .txt) | +| `0_title.txt` | Text TTS fallback | Fallback | +| `1_comment.png` | Screenshot comment 1 | Optional | +| `1_comment.mp3` | Audio comment 1 | ✅ (hoặc .txt) | +| `meta.json` | Metadata | Optional | + +### 3.3 `post_object` — Data Structure + +```python +post_object = { + "post_id": "post_001", + "platform": "reddit", # reddit | threads | x | other + "title": "What's the most...", + "author": "u/example_user", + "url": "https://...", + "post_dir": "manual_posts/post_001", + + "screenshots": [ + { + "index": 0, + "type": "title", + "image_path": "manual_posts/post_001/0_title.png", + "text": "", # Từ .txt (nếu có) + "audio_path": "manual_posts/post_001/0_title.mp3", # Từ .mp3 + "audio_duration": 3.5, # Đo sau khi process + }, + { + "index": 1, + "type": "comment", + "image_path": "manual_posts/post_001/1_comment.png", + "text": "", + "audio_path": "manual_posts/post_001/1_comment.mp3", + "audio_duration": 5.2, + }, + ], + + "total_duration": 8.7, + "output_path": "manual_results/post_001.mp4", +} +``` + +### 3.4 Flow Xử Lý + +```mermaid +flowchart TD + A["manual_main.py"] --> B{"Command?"} + + B -->|"render"| G["Quét manual_posts/"] + G --> H["Validate: có ảnh + audio/text?"] + H --> I["Build post_object từ files"] + I --> J{"Có .mp3?"} + J -->|"YES"| K["Dùng .mp3 trực tiếp"] + J -->|"NO, có .txt"| L["TTS: text → .mp3"] + K --> M["Random pick background video + audio"] + L --> M + M --> N["FFmpeg: ghép ảnh + audio + background"] + N --> O["Output → manual_results/"] + + B -->|"render --all"| P["Loop qua tất cả folders"] + P --> G + + B -->|"init"| Q["Tạo folder + meta.json"] + B -->|"list"| R["Liệt kê posts + trạng thái"] +``` + +--- + +## 4. So Sánh Flow Cũ vs Flow Mới + +| Aspect | Flow Cũ (`main.py`) | Flow Mới (`manual_main.py`) | +|--------|---------------------|---------------------------| +| **Data source** | Reddit API (PRAW) | Manual screenshots + audio files | +| **Screenshot** | Playwright auto-capture | User tự chụp | +| **Audio source** | TTS từ comment text | **User cung cấp .mp3** (hoặc .txt → TTS) | +| **Platform** | Chỉ Reddit | Reddit + Threads + X + any | +| **TTS engines** | Required | Optional (chỉ là fallback cho .txt) | +| **Background** | Hardcoded YouTube list | **Random từ local folder** (YouTube fallback) | +| **Encoder** | `h264_nvenc` (GPU) | `libx264` (CPU) | +| **Config** | `config.toml` (template-based) | `config.toml` `[manual]` section + built-in defaults | +| **Output** | `results//` | `manual_results/` | +| **Tracking** | `videos.json` | `videos.json` (shared) | + +--- + +## 5. Config + +```toml +[manual] +input_dir = "manual_posts" +output_dir = "manual_results" +encoder = "libx264" +resolution_w = 1080 +resolution_h = 1920 +opacity = 0.9 +background_video = "random" # "random" hoặc tên cụ thể (e.g. "minecraft") +background_audio = "random" # "random" hoặc tên cụ thể (e.g. "lofi") +background_video_dir = "assets/backgrounds/video" # Thư mục chứa video nền local +background_audio_dir = "assets/backgrounds/audio" # Thư mục chứa nhạc nền local +background_audio_volume = 0.15 +max_video_length = 120 +``` + +**Lưu ý**: Config `[manual]` là optional. Nếu không có, dùng built-in defaults. + +### Background: Random từ local folder + +Bỏ file video/audio nền vào thư mục → hệ thống random chọn mỗi lần render: +``` +assets/backgrounds/video/ ← Bỏ file .mp4/.mkv/.webm/.avi/.mov vào đây +assets/backgrounds/audio/ ← Bỏ file .mp3/.wav/.ogg/.m4a/.flac vào đây +``` +- **Có file local** → random chọn 1 +- **Không có file local** → fallback tải từ YouTube (danh sách cũ) + +TTS fallback dùng settings từ `[settings.tts]` (mặc định: GoogleTranslate, không cần API key). + +--- + +## 6. Decisions Log + +| Câu hỏi | Quyết định | +|----------|------------| +| Audio source | **.mp3 ưu tiên**, .txt fallback sang TTS | +| Background | **Random từ local folder**, YouTube fallback | +| Encoder | `libx264` (CPU) — không có GPU NVIDIA | +| Config | Section `[manual]` trong `config.toml` | +| Thumbnail | Bỏ qua | +| Video tracking | Chung file `videos.json` | +| OCR (Phase 2) | EN + VI, dùng EasyOCR | + +--- + +## 7. Phases + +| Phase | Trạng thái | Mô tả | +|-------|:---:|--------| +| **Phase 1: Core** | ✅ Done | .png + .mp3 → Video (+ .txt TTS fallback) | +| Phase 2: OCR | ⏳ Planned | Auto-read text từ screenshots (EN + VI) | +| Phase 3: GUI | ⏳ Planned | Flask web interface cho manual flow | + +--- + +> 📝 **Tóm tắt**: Module `manual/` tách biệt hoàn toàn. Input chính: screenshots (.png) + audio (.mp3). TTS chỉ là fallback khi dùng .txt. Reuse background functions từ code cũ. Output video vào `manual_results/`. Platform-agnostic. diff --git a/MANUAL_PIPELINE_GUIDE.md b/MANUAL_PIPELINE_GUIDE.md new file mode 100644 index 0000000..e92e6da --- /dev/null +++ b/MANUAL_PIPELINE_GUIDE.md @@ -0,0 +1,139 @@ +# 📖 Hướng Dẫn Sử Dụng Manual Pipeline + +> **Tóm tắt**: Tạo video từ screenshots chụp tay (Reddit, Threads, X) mà không cần API. + +--- + +## 🚀 Quick Start (3 bước) + +### Bước 1: Tạo folder cho post mới +```bash +cd /home/minhvu/projects/RedditVideoMakerBot +python manual_main.py init my_first_post --platform reddit +``` + +Kết quả: +``` +manual_posts/my_first_post/ +├── meta.json ← (optional) metadata +├── 0_title.txt ← Chỉnh text cho TTS ở đây +└── 1_comment.txt ← Chỉnh text comment ở đây +``` + +### Bước 2: Thêm screenshots + text + +1. **Chụp screenshot** bài đăng → lưu thành `0_title.png` +2. **Chụp screenshot** comments → lưu thành `1_comment.png`, `2_comment.png`, ... +3. **Sửa file `.txt`** tương ứng — nhập nội dung text mà bot sẽ đọc thành giọng nói + +``` +manual_posts/my_first_post/ +├── meta.json +├── 0_title.png ← Screenshot bài đăng +├── 0_title.txt ← "What's the most underrated life hack?" +├── 1_comment.png ← Screenshot comment 1 +├── 1_comment.txt ← "I always put my phone on airplane mode..." +├── 2_comment.png ← Screenshot comment 2 +└── 2_comment.txt ← "Using a binder clip as a phone stand..." +``` + +> [!IMPORTANT] +> Mỗi file `.png` **bắt buộc** phải có file `.txt` cùng số thứ tự. Số `0` luôn là title/bài đăng chính. + +### Bước 3: Render video +```bash +python manual_main.py render my_first_post +``` + +Video sẽ được lưu tại: `manual_results/my_first_post.mp4` + +--- + +## 📋 Tất Cả Commands + +| Command | Mô tả | +|---------|--------| +| `python manual_main.py init ` | Tạo folder mới với template files | +| `python manual_main.py init --platform threads` | Tạo folder cho Threads post | +| `python manual_main.py render ` | Render 1 post thành video | +| `python manual_main.py render --all` | Render tất cả posts chưa render | +| `python manual_main.py render --force` | Re-render (dù đã render trước đó) | +| `python manual_main.py list` | Liệt kê tất cả posts + trạng thái | + +--- + +## 📁 Quy Tắc Đặt Tên File + +``` +_. +``` + +| File | Ý nghĩa | +|------|----------| +| `0_title.png` | Screenshot bài đăng chính (bắt buộc) | +| `0_title.txt` | Text TTS cho bài đăng (bắt buộc) | +| `1_comment.png` | Screenshot comment 1 | +| `1_comment.txt` | Text TTS cho comment 1 | +| `N_comment.png/txt` | Comment thứ N | +| `meta.json` | Metadata (optional) | + +> [!TIP] +> File `.txt` hỗ trợ dòng comment bắt đầu bằng `#` — những dòng này sẽ bị bỏ qua khi TTS. + +--- + +## ⚙️ Cấu Hình + +Thêm section `[manual]` vào `config.toml` (hoặc để trống — bot sẽ dùng defaults): + +```toml +[manual] +input_dir = "manual_posts" # Thư mục input +output_dir = "manual_results" # Thư mục output +encoder = "libx264" # CPU encoder (hoặc h264_nvenc nếu có GPU) +resolution_w = 1080 # Width video +resolution_h = 1920 # Height video (1080x1920 = portrait) +opacity = 0.9 # Độ trong suốt screenshot overlay +background_video = "minecraft" # Video nền +background_audio = "lofi" # Audio nền +background_audio_volume = 0.15 # Âm lượng audio nền (0 = tắt) +max_video_length = 120 # Max thời lượng video (giây) +``` + +TTS engine được lấy từ section `[settings.tts]` trong `config.toml`. Mặc định dùng **GoogleTranslate** (không cần API key). + +--- + +## 🏗️ Kiến Trúc Module + +``` +manual/ +├── __init__.py # Module docstring +├── scanner.py # Quét folders, validate, build post_object +├── tts_processor.py # TTS: text → MP3 (reuse TTS/ engines) +└── video_builder.py # FFmpeg: screenshots + audio → video + +manual_main.py # CLI entry point (init, render, list) +``` + +**Hoàn toàn tách biệt** với flow cũ (`main.py`). Không sửa bất kỳ file nào của flow cũ. + +### Files đã tạo/sửa + +| File | Action | Mô tả | +|------|--------|--------| +| [manual/__init__.py](file:///home/minhvu/projects/RedditVideoMakerBot/manual/__init__.py) | 🆕 Created | Module init | +| [manual/scanner.py](file:///home/minhvu/projects/RedditVideoMakerBot/manual/scanner.py) | 🆕 Created | Folder scanner & validator | +| [manual/tts_processor.py](file:///home/minhvu/projects/RedditVideoMakerBot/manual/tts_processor.py) | 🆕 Created | TTS processor | +| [manual/video_builder.py](file:///home/minhvu/projects/RedditVideoMakerBot/manual/video_builder.py) | 🆕 Created | Video assembler | +| [manual_main.py](file:///home/minhvu/projects/RedditVideoMakerBot/manual_main.py) | 🆕 Created | CLI entry point | +| [.gitignore](file:///home/minhvu/projects/RedditVideoMakerBot/.gitignore) | ✏️ Updated | Thêm `manual_posts/`, `manual_results/` | + +--- + +## ⚠️ Lưu Ý + +1. **FFmpeg** phải được cài sẵn trên hệ thống +2. **Background video** sẽ tự động tải từ YouTube lần đầu (cần internet) +3. Config.toml có thể trống — bot dùng built-in defaults (GoogleTranslate TTS) +4. Encoder mặc định là `libx264` (CPU) — phù hợp máy không có GPU NVIDIA diff --git a/PROJECT_INIT.md b/PROJECT_INIT.md new file mode 100644 index 0000000..f53faff --- /dev/null +++ b/PROJECT_INIT.md @@ -0,0 +1,483 @@ +# 📦 RedditVideoMakerBot — Project Init Documentation + +> **Version**: 3.4.0 +> **Author gốc**: Lewis Menelaws & [TMRRW](https://tmrrwinc.ca) +> **License**: GPL + Roboto Fonts (Apache 2.0) +> **Python**: 3.10 / 3.11 / 3.12 + +--- + +## 1. Tổng Quan + +RedditVideoMakerBot là một công cụ tự động hóa việc tạo video ngắn (TikTok/YouTube Shorts/Instagram Reels) từ các bài đăng trên Reddit. Bot sẽ: + +1. **Lấy bài đăng** từ subreddit (qua Reddit API / PRAW) +2. **Chuyển text thành giọng nói** (TTS — 7 engine khác nhau) +3. **Chụp screenshot** bài đăng/comments bằng Playwright +4. **Tải & cắt video/audio nền** từ YouTube +5. **Ghép tất cả** thành video hoàn chỉnh bằng FFmpeg + +Kết quả cuối cùng: file `.mp4` trong thư mục `results//`. + +--- + +## 2. Cấu Trúc Thư Mục + +``` +RedditVideoMakerBot/ +├── main.py # 🚀 Entry point chính +├── GUI.py # 🖥️ Web GUI (Flask, port 4000) +├── config.toml # ⚙️ File cấu hình (user-generated) +├── ptt.py # 🔊 Helper script để liệt kê system voices +├── requirements.txt # 📦 Python dependencies +├── Dockerfile # 🐳 Docker support (python:3.10-slim) +├── build.sh / run.sh / run.bat # 📜 Scripts chạy nhanh +├── install.sh # 📜 Auto-installer (Linux/macOS) +│ +├── reddit/ # 📡 Module lấy dữ liệu từ Reddit +│ └── subreddit.py # Đăng nhập Reddit, lấy threads & comments +│ +├── TTS/ # 🗣️ Module Text-to-Speech (7 engines) +│ ├── engine_wrapper.py # TTSEngine — wrapper chung cho tất cả TTS +│ ├── TikTok.py # TikTok TTS API +│ ├── aws_polly.py # AWS Polly (boto3) +│ ├── elevenlabs.py # ElevenLabs API +│ ├── openai_tts.py # OpenAI TTS API +│ ├── GTTS.py # Google Translate TTS (gTTS) +│ ├── pyttsx.py # pyttsx3 (offline, system voices) +│ └── streamlabs_polly.py # Streamlabs Polly +│ +├── video_creation/ # 🎬 Module tạo video +│ ├── voices.py # Orchestrator — chọn TTS provider & chạy +│ ├── screenshot_downloader.py # Chụp screenshot Reddit bằng Playwright +│ ├── background.py # Tải & cắt background video/audio (yt-dlp) +│ ├── final_video.py # Ghép tất cả thành video (FFmpeg pipeline) +│ └── data/ # Cookie files + videos.json (tracking) +│ ├── cookie-dark-mode.json +│ ├── cookie-light-mode.json +│ └── videos.json +│ +├── utils/ # 🛠️ Utilities +│ ├── settings.py # Đọc/validate config.toml theo template +│ ├── .config.template.toml # Template cấu hình (định nghĩa tất cả fields) +│ ├── console.py # Rich console helpers (print_step, handle_input...) +│ ├── ai_methods.py # AI similarity sorting (sentence-transformers) +│ ├── subreddit.py # Logic chọn post chưa làm + bộ lọc +│ ├── voice.py # sanitize_text(), rate limit, sleep_until() +│ ├── videos.py # check_done(), save_data() — tracking +│ ├── cleanup.py # Xóa temp files +│ ├── ffmpeg_install.py # Tự động cài FFmpeg nếu chưa có +│ ├── imagenarator.py # Render ảnh cho storymode method 1 +│ ├── thumbnail.py # Tạo thumbnail cho video +│ ├── fonts.py # Font size helpers +│ ├── id.py # extract_id() — sanitize reddit thread ID +│ ├── posttextparser.py # Phân tách post text thành các đoạn +│ ├── playwright.py # Helper clear cookies +│ ├── version.py # Check version mới trên GitHub +│ ├── gui_utils.py # Utils cho Flask GUI +│ ├── background_videos.json # Danh sách background videos (YouTube URLs) +│ └── background_audios.json # Danh sách background audios (YouTube URLs) +│ +├── GUI/ # 🌐 Flask Templates (HTML) +│ ├── layout.html # Base template +│ ├── index.html # Trang chủ — danh sách videos đã tạo +│ ├── settings.html # Trang cấu hình +│ ├── backgrounds.html # Quản lý backgrounds +│ └── voices/ # Voice sample files +│ +├── fonts/ # 🔤 Roboto font files +│ ├── Roboto-Regular.ttf +│ ├── Roboto-Bold.ttf +│ ├── Roboto-Medium.ttf +│ ├── Roboto-Black.ttf +│ └── LICENSE.txt +│ +├── assets/ # 🎨 Static assets +│ ├── title_template.png # Template ảnh cho fancy thumbnail +│ └── backgrounds/ # Downloaded background files (video/audio) +│ +├── results/ # 📁 Output videos (auto-created) +│ └── / +│ ├──