├── .cursorrules ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── front.png └── youtube.png ├── demo.ipynb ├── docs └── design.md ├── examples ├── Competition_is_for_Losers_with_Peter_Thiel.html ├── DeepSeek_China_OpenAI_NVIDIA_xAI_TSMC_Stargate_and_AI_Megaclusters__Lex_Fridman_Podcast_459.html ├── Demis_Hassabis_-_Scaling_Superhuman_AIs_AlphaZero_atop_LLMs_AlphaFold.html ├── Elon_Musk_War_AI_Aliens_Politics_Physics_Video_Games_and_Humanity__Lex_Fridman_Podcast_400.html ├── Full_interview_Godfather_of_artificial_intelligence_talks_impact_and_potential_of_AI.html ├── In_conversation_with_Elon_Musk_Twitters_bot_problem_SpaceXs_grand_plan_Tesla_stories__more.html ├── In_conversation_with_President_Trump.html ├── In_conversation_with_Tucker_Carlson_plus_OpenAI_chaos_explained.html ├── Jeff_Dean__Noam_Shazeer_-_25_years_at_Google_from_PageRank_to_AGI.html ├── Jonathan_Ross_Founder__CEO__Groq_NVIDIA_vs_Groq_-_The_Future_of_Training_vs_Inference__E1260.html ├── MrBeast_Shares_His_Most_Controversial_Business_Advice.html ├── NVIDIA_CEO_Jensen_Huangs_Vision_for_the_Future.html ├── Sarah_C._M._Paine_-_Why_Dictators_Keep_Making_the_Same_Fatal_Mistake.html ├── Satya_Nadella_-_Microsofts_AGI_Plan__Quantum_Breakthrough.html ├── The_Future_Mark_Zuckerberg_Is_Trying_To_Build.html ├── The_Stablecoin_Future_Mileis_Memecoin_DOGE_for_the_DoD_Grok_3_Why_Stripe_Stays_Private.html ├── Tucker_Carlson_Putin_Navalny_Trump_CIA_NSA_War_Politics__Freedom__Lex_Fridman_Podcast_414.html └── Volodymyr_Zelenskyy_Ukraine_War_Peace_Putin_Trump_NATO_and_Freedom__Lex_Fridman_Podcast_456.html ├── flow.py ├── main.py ├── requirements.txt └── utils ├── __init__.py ├── call_llm.py ├── html_generator.py └── youtube_processor.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | vendor/ 4 | .pnp/ 5 | .pnp.js 6 | 7 | # Build outputs 8 | dist/ 9 | build/ 10 | out/ 11 | *.pyc 12 | __pycache__/ 13 | 14 | # Environment files 15 | .env 16 | .env.local 17 | .env.*.local 18 | .env.development 19 | .env.test 20 | .env.production 21 | 22 | # IDE - VSCode 23 | .vscode/* 24 | !.vscode/settings.json 25 | !.vscode/tasks.json 26 | !.vscode/launch.json 27 | !.vscode/extensions.json 28 | 29 | # IDE - JetBrains 30 | .idea/ 31 | *.iml 32 | *.iws 33 | *.ipr 34 | 35 | # IDE - Eclipse 36 | .project 37 | .classpath 38 | .settings/ 39 | 40 | # Logs 41 | logs/ 42 | *.log 43 | npm-debug.log* 44 | yarn-debug.log* 45 | yarn-error.log* 46 | 47 | # Operating System 48 | .DS_Store 49 | Thumbs.db 50 | *.swp 51 | *.swo 52 | 53 | # Testing 54 | coverage/ 55 | .nyc_output/ 56 | 57 | # Temporary files 58 | *.tmp 59 | *.temp 60 | .cache/ 61 | 62 | # Compiled files 63 | *.com 64 | *.class 65 | *.dll 66 | *.exe 67 | *.o 68 | *.so 69 | 70 | # Package files 71 | *.7z 72 | *.dmg 73 | *.gz 74 | *.iso 75 | *.jar 76 | *.rar 77 | *.tar 78 | *.zip 79 | 80 | # Database 81 | *.sqlite 82 | *.sqlite3 83 | *.db 84 | 85 | # Optional npm cache directory 86 | .npm 87 | 88 | # Optional eslint cache 89 | .eslintcache 90 | 91 | # Optional REPL history 92 | .node_repl_history -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Zachary Huang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Explain Youtube Video To Me Like I'm 5

2 | 3 | ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg) 4 | 5 | Have a 5-hour YouTube video but no time to watch it? This LLM application pulls the main topics and explains to you like you are 5, so you can catch up in just minutes. 6 | 7 |
8 | 9 |
10 | 11 | Design Doc: [docs/design.md](docs/design.md), Flow Source Code: [flow.py](flow.py) 12 | 13 | Try running the code in your browser using the [demo notebook](https://colab.research.google.com/github/The-Pocket/Tutorial-Youtube-Made-Simple/blob/main/demo.ipynb). 14 | 15 | 16 | 17 | ## Example Outputs 18 | 19 | | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/NVIDIA_CEO_Jensen_Huangs_Vision_for_the_Future.html)
**NVIDIA CEO Jensen Huang's Vision for the Future** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/DeepSeek_China_OpenAI_NVIDIA_xAI_TSMC_Stargate_and_AI_Megaclusters__Lex_Fridman_Podcast_459.html)
DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Demis_Hassabis_-_Scaling_Superhuman_AIs_AlphaZero_atop_LLMs_AlphaFold.html)
Demis Hassabis – Scaling, Superhuman AIs, AlphaZero atop LLMs, AlphaFold | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Elon_Musk_War_AI_Aliens_Politics_Physics_Video_Games_and_Humanity__Lex_Fridman_Podcast_400.html)
Elon Musk: War, AI, Aliens, Politics, Physics, Video Games, and Humanity | 20 | | :-------------: | :-------------: | :-------------: | :-------------: | 21 | |[ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/In_conversation_with_Elon_Musk_Twitters_bot_problem_SpaceXs_grand_plan_Tesla_stories__more.html)
**In conversation with Elon Musk: Twitter's bot problem, SpaceX's grand plan, Tesla stories & more** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/In_conversation_with_President_Trump.html)
**In conversation with President Trump** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Jeff_Dean__Noam_Shazeer_-_25_years_at_Google_from_PageRank_to_AGI.html)
**Jeff Dean & Noam Shazeer – 25 years at Google: from PageRank to AGI** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/In_conversation_with_Tucker_Carlson_plus_OpenAI_chaos_explained.html)
**In conversation with Tucker Carlson, plus OpenAI chaos explained** | 22 | |[ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Jonathan_Ross_Founder__CEO__Groq_NVIDIA_vs_Groq_-_The_Future_of_Training_vs_Inference__E1260.html)
**Jonathan Ross, Founder & CEO @ Groq: NVIDIA vs Groq - The Future of Training vs Inference** | [](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Volodymyr_Zelenskyy_Ukraine_War_Peace_Putin_Trump_NATO_and_Freedom__Lex_Fridman_Podcast_456.html)
**Volodymyr Zelenskyy: Ukraine, War, Peace, Putin, Trump, NATO, and Freedom** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Sarah_C._M._Paine_-_Why_Dictators_Keep_Making_the_Same_Fatal_Mistake.html)
**Sarah C. M. Paine - Why Dictators Keep Making the Same Fatal Mistake** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Satya_Nadella_-_Microsofts_AGI_Plan__Quantum_Breakthrough.html)
**Satya Nadella – Microsoft's AGI Plan & Quantum Breakthrough** | 23 | |[ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Full_interview_Godfather_of_artificial_intelligence_talks_impact_and_potential_of_AI.html)
**Full interview: "Godfather of artificial intelligence" talks impact and potential of AI** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/The_Stablecoin_Future_Mileis_Memecoin_DOGE_for_the_DoD_Grok_3_Why_Stripe_Stays_Private.html)
**The Stablecoin Future, Milei's Memecoin, DOGE for the DoD, Grok 3, Why Stripe Stays Private** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/The_Future_Mark_Zuckerberg_Is_Trying_To_Build.html)
**The Future Mark Zuckerberg Is Trying To Build** | [ ](https://the-pocket.github.io/Tutorial-Youtube-Made-Simple/examples/Tucker_Carlson_Putin_Navalny_Trump_CIA_NSA_War_Politics__Freedom__Lex_Fridman_Podcast_414.html)
**Tucker Carlson: Putin, Navalny, Trump, CIA, NSA, War, Politics & Freedom** | 24 | 25 | ## How to Run 26 | 27 | 1. Set up LLM in [`utils/call_llm.py`](./utils/call_llm.py) by providing credentials. 28 | 29 | You can refer to [LLM Wrappers](https://the-pocket.github.io/PocketFlow/utility_function/llm.html) for example implementations. 30 | 31 | You can verify that it is correctly set up by running: 32 | ```bash 33 | python utils/call_llm.py 34 | ``` 35 | 36 | 4. Install the dependencies and run the program: 37 | ```bash 38 | pip install -r requirements.txt 39 | python main.py --url "https://www.youtube.com/watch?v=example" 40 | ``` 41 | 42 | 3. When it's done, open output.html (created in the project folder) to see the results. 43 | 44 | ## I built this in just an hour, and you can, too. 45 | 46 | - Built With [Pocket Flow](https://github.com/The-Pocket/PocketFlow), a 100-line LLM framework that lets LLM Agents (e.g., Cursor AI) build Apps for you 47 | 48 | - **Check out the Step-by-Step YouTube Tutorial:** 49 | 50 |
51 |
52 | 53 | IMAGE ALT TEXT 54 | 55 |
56 |
57 | -------------------------------------------------------------------------------- /assets/front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Pocket/PocketFlow-Tutorial-Youtube-Made-Simple/9c222f875a71377259033704c86c01d554d1fe8c/assets/front.png -------------------------------------------------------------------------------- /assets/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Pocket/PocketFlow-Tutorial-Youtube-Made-Simple/9c222f875a71377259033704c86c01d554d1fe8c/assets/youtube.png -------------------------------------------------------------------------------- /docs/design.md: -------------------------------------------------------------------------------- 1 | # Explain Youtube Podcast To Me Like I'm 5 2 | 3 | ## Project Requirements 4 | This project takes a YouTube podcast URL, extracts the transcript, identifies key topics and Q&A pairs, simplifies them for children, and generates an HTML report with the results. 5 | 6 | ## Utility Functions 7 | 8 | 1. **LLM Calls** (`utils/call_llm.py`) 9 | 10 | 2. **YouTube Processing** (`utils/youtube_processor.py`) 11 | - Get video title, transcript and thumbnail 12 | 13 | 3. **HTML Generator** (`utils/html_generator.py`) 14 | - Create formatted report with topics, Q&As and simple explanations 15 | 16 | ## Flow Design 17 | 18 | The application flow consists of several key steps organized in a directed graph: 19 | 20 | 1. **Video Processing**: Extract transcript and metadata from YouTube URL 21 | 2. **Topic Extraction**: Identify the most interesting topics (max 5) 22 | 3. **Question Generation**: For each topic, generate interesting questions (3 per topic) 23 | 4. **Topic Processing**: Batch process each topic to: 24 | - Rephrase the topic title for clarity 25 | - Rephrase the questions 26 | - Generate ELI5 answers 27 | 5. **HTML Generation**: Create final HTML output 28 | 29 | ### Flow Diagram 30 | 31 | ```mermaid 32 | flowchart TD 33 | videoProcess[Process YouTube URL] --> topicsQuestions[Extract Topics & Questions] 34 | topicsQuestions --> contentBatch[Content Processing] 35 | contentBatch --> htmlGen[Generate HTML] 36 | 37 | subgraph contentBatch[Content Processing] 38 | topicProcess[Process Topic] 39 | end 40 | ``` 41 | 42 | ## Data Structure 43 | 44 | The shared memory structure will be organized as follows: 45 | 46 | ```python 47 | shared = { 48 | "video_info": { 49 | "url": str, # YouTube URL 50 | "title": str, # Video title 51 | "transcript": str, # Full transcript 52 | "thumbnail_url": str, # Thumbnail image URL 53 | "video_id": str # YouTube video ID 54 | }, 55 | "topics": [ 56 | { 57 | "title": str, # Original topic title 58 | "rephrased_title": str, # Clarified topic title 59 | "questions": [ 60 | { 61 | "original": str, # Original question 62 | "rephrased": str, # Clarified question 63 | "answer": str # ELI5 answer 64 | }, 65 | # ... more questions 66 | ] 67 | }, 68 | # ... more topics 69 | ], 70 | "html_output": str # Final HTML content 71 | } 72 | ``` 73 | 74 | ## Node Designs 75 | 76 | ### 1. ProcessYouTubeURL 77 | - **Purpose**: Process YouTube URL to extract video information 78 | - **Design**: Regular Node (no batch/async) 79 | - **Data Access**: 80 | - Read: URL from shared store 81 | - Write: Video information to shared store 82 | 83 | ### 2. ExtractTopicsAndQuestions 84 | - **Purpose**: Extract interesting topics from transcript and generate questions for each topic 85 | - **Design**: Regular Node (no batch/async) 86 | - **Data Access**: 87 | - Read: Transcript from shared store 88 | - Write: Topics with questions to shared store 89 | - **Implementation Details**: 90 | - First extracts up to 5 interesting topics from the transcript 91 | - For each topic, immediately generates 3 relevant questions 92 | - Returns a combined structure with topics and their associated questions 93 | 94 | ### 3. ProcessTopic 95 | - **Purpose**: Batch process each topic for rephrasing and answering 96 | - **Design**: BatchNode (process each topic) 97 | - **Data Access**: 98 | - Read: Topics and questions from shared store 99 | - Write: Rephrased content and answers to shared store 100 | 101 | ### 4. GenerateHTML 102 | - **Purpose**: Create final HTML output 103 | - **Design**: Regular Node (no batch/async) 104 | - **Data Access**: 105 | - Read: Processed content from shared store 106 | - Write: HTML output to shared store 107 | 108 | -------------------------------------------------------------------------------- /examples/Competition_is_for_Losers_with_Peter_Thiel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

Competition is for Losers with Peter Thiel (How to Start a Startup 2014: 5)

62 | 63 | Placeholder image 68 |

Monopolies vs. Competition: Why Some Businesses Win Big 69 |

70 | 116 |

Creating Value vs. Making Money: The X and Y Balance 117 |

118 | 166 |

How Small Markets Help Create Big Companies 167 |

168 | 211 |

Last Mover Companies Win Big: Better Than Being First! 212 |

213 | 257 |

Why Being Different Beats Competing with Everyone Else 258 |

259 | 287 |
288 | 289 | -------------------------------------------------------------------------------- /examples/Demis_Hassabis_-_Scaling_Superhuman_AIs_AlphaZero_atop_LLMs_AlphaFold.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

Demis Hassabis – Scaling, Superhuman AIs, AlphaZero atop LLMs, AlphaFold

62 | 63 | Placeholder image 68 |

How Smart Computers and Human Brains Work Together 69 |

70 | 115 |

How Computers Get Smarter: Building Bigger AI Models 116 |

117 | 162 |

How AI Can Plan Better: Combining Chess Computers with Smart Chatbots 163 |

164 | 210 |

Making Super Smart AI Safe for Kids to Understand 211 |

212 | 254 |

Keeping Super-Smart AI Safe and Under Control 255 |

256 | 293 |
294 | 295 | -------------------------------------------------------------------------------- /examples/Elon_Musk_War_AI_Aliens_Politics_Physics_Video_Games_and_Humanity__Lex_Fridman_Podcast_400.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

Elon Musk: War, AI, Aliens, Politics, Physics, Video Games, and Humanity | Lex Fridman Podcast #400

62 | 63 | Placeholder image 68 |

War and Peace: Can Being Kind Stop Fighting? 69 |

70 | 115 |

How Smart Computers Are Growing Up and What's Next 116 |

117 | 163 |

Big Dangers That Could End Humanity: What Should We Worry About? 164 |

165 | 210 |

Social Media and AI: Making Online Time Better for Kids 211 |

212 | 261 |

How to Think Like a Leader and Stay Curious 262 |

263 | 296 |
297 | 298 | -------------------------------------------------------------------------------- /examples/Full_interview_Godfather_of_artificial_intelligence_talks_impact_and_potential_of_AI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

Full interview: "Godfather of artificial intelligence" talks impact and potential of AI

62 | 63 | Placeholder image 68 |

How Smart Computers Learn to Think Like Brains 69 |

70 | 109 |

How Smart Are AI Language Models and How Do They Work? 110 |

111 | 155 |

How Do We Make Sure Super-Smart Computers Stay Good? 156 |

157 | 194 |

Friendly Robots: How Smart Computers Might Change Our World 195 |

196 | 242 |

Robot Weapons and Smart Computers That Fight Wars 243 |

244 | 275 |
276 | 277 | -------------------------------------------------------------------------------- /examples/In_conversation_with_Elon_Musk_Twitters_bot_problem_SpaceXs_grand_plan_Tesla_stories__more.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

In conversation with Elon Musk: Twitter's bot problem, SpaceX's grand plan, Tesla stories & more

62 | 63 | Placeholder image 68 |

Elon Musk, Twitter, and the Bot Problem 69 |

70 | 111 |

SpaceX: Building a Home on Mars for Humans 112 |

113 | 156 |

Energy and Cars: How Tesla Grew and Why It Matters 157 |

158 | 204 |

How Talent from Other Countries Helps America Stay Strong 205 |

206 | 251 |

When Money Gets Tight: Understanding Economic Downturns for Kids 252 |

253 | 287 |
288 | 289 | -------------------------------------------------------------------------------- /examples/In_conversation_with_President_Trump.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

In conversation with President Trump

62 | 63 | Placeholder image 68 |

How Presidents Make Money Decisions That Affect Everyone 69 |

70 | 117 |

Peace, War, and Friends: How Countries Get Along 118 |

119 | 157 |

College Graduates, Green Cards, and America's Future Workers 158 |

159 | 215 |

Government Secrets: Why We Should Know What Happened 216 |

217 | 267 |

Who Gets to Decide About Babies? States or the Country? 268 |

269 | 300 |
301 | 302 | -------------------------------------------------------------------------------- /examples/Jonathan_Ross_Founder__CEO__Groq_NVIDIA_vs_Groq_-_The_Future_of_Training_vs_Inference__E1260.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 |

Jonathan Ross, Founder & CEO @ Groq: NVIDIA vs Groq - The Future of Training vs Inference | E1260

61 | 62 | Placeholder image 67 |

How AI Gets Smarter and Faster: Computer Brains Explained 68 |

69 | 113 |

AI Thinking vs AI Working: What's the Difference? 114 |

115 | 167 |

Computer Brains: How LPUs and GPUs Power AI Differently 168 |

169 | 216 |

Who Will Win the AI Race: USA, China, or Europe? 217 |

218 | 264 |

How Groq Makes Money: Computer Chips for AI Helpers 265 |

266 | 303 |
304 | 305 | -------------------------------------------------------------------------------- /examples/MrBeast_Shares_His_Most_Controversial_Business_Advice.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

MrBeast Shares His Most Controversial Business Advice

62 | 63 | Placeholder image 68 |

"Never Give Up: Taking Risks to Follow Your Dreams" 69 |

70 | 117 |

The Rule of 100: Getting Better One Step at a Time 118 |

119 | 164 |

Learning to Be Like the Boss: The MrBeast Way 165 |

166 | 214 |

"Making Impossible Things Happen: MrBeast's Success Secrets" 215 |

216 | 269 |

MrBeast Makes Ethical Chocolate: A Kid-Friendly Explanation 270 |

271 | 297 |
298 | 299 | -------------------------------------------------------------------------------- /examples/NVIDIA_CEO_Jensen_Huangs_Vision_for_the_Future.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 |

NVIDIA CEO Jensen Huang's Vision for the Future

61 | 62 | Placeholder image 67 |

From One Thing at a Time to Many: How Computers Got Smarter 68 |

69 | 126 |

Robots, AI, and How They'll Change Our Future World 127 |

128 | 169 |

How AI Works and Why We Need to Keep It Safe 170 |

171 | 209 |

How Computers That Think Help People Do Amazing Things 210 |

211 | 255 |

How AI Will Change Our Future in Amazing Ways 256 |

257 | 287 |
288 | 289 | -------------------------------------------------------------------------------- /examples/Satya_Nadella_-_Microsofts_AGI_Plan__Quantum_Breakthrough.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

Satya Nadella – Microsoft’s AGI Plan & Quantum Breakthrough

62 | 63 | Placeholder image 68 |

How Microsoft Plans to Win the AI Race 69 |

70 | 106 |

Quantum Superpowers: How Special Computer Chips Help Make Magical Machines 107 |

108 | 152 |

How AI Makes Video Games and Could Change Our World 153 |

154 | 201 |

How Robots Will Help Us Do Smart Work 202 |

203 | 242 |

How Big Companies Think Far Into the Future 243 |

244 | 271 |
272 | 273 | -------------------------------------------------------------------------------- /examples/The_Stablecoin_Future_Mileis_Memecoin_DOGE_for_the_DoD_Grok_3_Why_Stripe_Stays_Private.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

The Stablecoin Future, Milei's Memecoin, DOGE for the DoD, Grok 3, Why Stripe Stays Private

62 | 63 | Placeholder image 68 |

Digital Money Magic: How Stablecoins Help People Around the World 69 |

70 | 116 |

Remote Work: How It Affects Jobs and Company Teamwork 117 |

118 | 166 |

How Military Spending Is Changing With New Technology 167 |

168 | 214 |

How Science and New Funding Models Can Help Find Cures 215 |

216 | 262 |

Public vs Private Companies: Which Is Better for Business? 263 |

264 | 292 |
293 | 294 | -------------------------------------------------------------------------------- /examples/Tucker_Carlson_Putin_Navalny_Trump_CIA_NSA_War_Politics__Freedom__Lex_Fridman_Podcast_414.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Youtube Made Simple 7 | 8 | 12 | 13 | 14 | 18 | 48 | 49 | 50 |
51 | 52 |
53 | Generated by 54 | 56 | Youtube Made Simple 57 | 58 |
59 | 60 | 61 |

Tucker Carlson: Putin, Navalny, Trump, CIA, NSA, War, Politics & Freedom | Lex Fridman Podcast #414

62 | 63 | Placeholder image 68 |

Putin and Russia: What Tucker Carlson Learned in Moscow 69 |

70 | 112 |

Free Speech, Spying, and Talking to World Leaders 113 |

114 | 157 |

Understanding the Ukraine War: Who's Really Fighting Who? 158 |

159 | 203 |

How Screens and Internet Change What We Learn 204 |

205 | 253 |

Technology: Is It Always Good for People? 254 |

255 | 285 |
286 | 287 | -------------------------------------------------------------------------------- /flow.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict, Any, Tuple 2 | import yaml 3 | import logging 4 | from pocketflow import Node, BatchNode, Flow 5 | from utils.call_llm import call_llm 6 | from utils.youtube_processor import get_video_info 7 | from utils.html_generator import html_generator 8 | 9 | # Set up logging 10 | logging.basicConfig( 11 | level=logging.INFO, 12 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' 13 | ) 14 | logger = logging.getLogger(__name__) 15 | 16 | # Define the specific nodes for the YouTube Content Processor 17 | 18 | class ProcessYouTubeURL(Node): 19 | """Process YouTube URL to extract video information""" 20 | def prep(self, shared): 21 | """Get URL from shared""" 22 | return shared.get("url", "") 23 | 24 | def exec(self, url): 25 | """Extract video information""" 26 | if not url: 27 | raise ValueError("No YouTube URL provided") 28 | 29 | logger.info(f"Processing YouTube URL: {url}") 30 | video_info = get_video_info(url) 31 | 32 | if "error" in video_info: 33 | raise ValueError(f"Error processing video: {video_info['error']}") 34 | 35 | return video_info 36 | 37 | def post(self, shared, prep_res, exec_res): 38 | """Store video information in shared""" 39 | shared["video_info"] = exec_res 40 | logger.info(f"Video title: {exec_res.get('title')}") 41 | logger.info(f"Transcript length: {len(exec_res.get('transcript', ''))}") 42 | return "default" 43 | 44 | class ExtractTopicsAndQuestions(Node): 45 | """Extract interesting topics and generate questions from the video transcript""" 46 | def prep(self, shared): 47 | """Get transcript and title from video_info""" 48 | video_info = shared.get("video_info", {}) 49 | transcript = video_info.get("transcript", "") 50 | title = video_info.get("title", "") 51 | return {"transcript": transcript, "title": title} 52 | 53 | def exec(self, data): 54 | """Extract topics and generate questions using LLM""" 55 | transcript = data["transcript"] 56 | title = data["title"] 57 | 58 | # Single prompt to extract topics and questions together 59 | prompt = f""" 60 | You are an expert content analyzer. Given a YouTube video transcript, identify at most 5 most interesting topics discussed and generate at most 3 most thought-provoking questions for each topic. 61 | These questions don't need to be directly asked in the video. It's good to have clarification questions. 62 | 63 | VIDEO TITLE: {title} 64 | 65 | TRANSCRIPT: 66 | {transcript} 67 | 68 | Format your response in YAML: 69 | 70 | ```yaml 71 | topics: 72 | - title: | 73 | First Topic Title 74 | questions: 75 | - | 76 | Question 1 about first topic? 77 | - | 78 | Question 2 ... 79 | - title: | 80 | Second Topic Title 81 | questions: 82 | ... 83 | ``` 84 | """ 85 | 86 | response = call_llm(prompt) 87 | 88 | # Extract YAML content 89 | yaml_content = response.split("```yaml")[1].split("```")[0].strip() if "```yaml" in response else response 90 | 91 | 92 | parsed = yaml.safe_load(yaml_content) 93 | raw_topics = parsed.get("topics", []) 94 | 95 | # Ensure we have at most 5 topics 96 | raw_topics = raw_topics[:5] 97 | 98 | # Format the topics and questions for our data structure 99 | result_topics = [] 100 | for topic in raw_topics: 101 | topic_title = topic.get("title", "") 102 | raw_questions = topic.get("questions", []) 103 | 104 | # Create a complete topic with questions 105 | result_topics.append({ 106 | "title": topic_title, 107 | "questions": [ 108 | { 109 | "original": q, 110 | "rephrased": "", 111 | "answer": "" 112 | } 113 | for q in raw_questions 114 | ] 115 | }) 116 | 117 | return result_topics 118 | 119 | def post(self, shared, prep_res, exec_res): 120 | """Store topics with questions in shared""" 121 | shared["topics"] = exec_res 122 | 123 | # Count total questions 124 | total_questions = sum(len(topic.get("questions", [])) for topic in exec_res) 125 | 126 | logger.info(f"Extracted {len(exec_res)} topics with {total_questions} questions") 127 | return "default" 128 | 129 | class ProcessContent(BatchNode): 130 | """Process each topic for rephrasing and answering""" 131 | def prep(self, shared): 132 | """Return list of topics for batch processing""" 133 | topics = shared.get("topics", []) 134 | video_info = shared.get("video_info", {}) 135 | transcript = video_info.get("transcript", "") 136 | 137 | batch_items = [] 138 | for topic in topics: 139 | batch_items.append({ 140 | "topic": topic, 141 | "transcript": transcript 142 | }) 143 | 144 | return batch_items 145 | 146 | def exec(self, item): 147 | """Process a topic using LLM""" 148 | topic = item["topic"] 149 | transcript = item["transcript"] 150 | 151 | topic_title = topic["title"] 152 | questions = [q["original"] for q in topic["questions"]] 153 | 154 | prompt = f"""You are a content simplifier for children. Given a topic and questions from a YouTube video, rephrase the topic title and questions to be clearer, and provide simple ELI5 (Explain Like I'm 5) answers. 155 | 156 | TOPIC: {topic_title} 157 | 158 | QUESTIONS: 159 | {chr(10).join([f"- {q}" for q in questions])} 160 | 161 | TRANSCRIPT EXCERPT: 162 | {transcript} 163 | 164 | For topic title and questions: 165 | 1. Keep them catchy and interesting, but short 166 | 167 | For your answers: 168 | 1. Format them using HTML with and tags for highlighting. 169 | 2. Prefer lists with
    and
  1. tags. Ideally,
  2. followed by for the key points. 170 | 3. Quote important keywords but explain them in easy-to-understand language (e.g., "Quantum computing is like having a super-fast magical calculator") 171 | 4. Keep answers interesting but short 172 | 173 | Format your response in YAML: 174 | 175 | ```yaml 176 | rephrased_title: | 177 | Interesting topic title in 10 words 178 | questions: 179 | - original: | 180 | {questions[0] if len(questions) > 0 else ''} 181 | rephrased: | 182 | Interesting question in 15 words 183 | answer: | 184 | Simple answer that a 5-year-old could understand in 100 words 185 | - original: | 186 | {questions[1] if len(questions) > 1 else ''} 187 | ... 188 | ``` 189 | """ 190 | 191 | response = call_llm(prompt) 192 | 193 | # Extract YAML content 194 | yaml_content = response.split("```yaml")[1].split("```")[0].strip() if "```yaml" in response else response 195 | 196 | parsed = yaml.safe_load(yaml_content) 197 | rephrased_title = parsed.get("rephrased_title", topic_title) 198 | processed_questions = parsed.get("questions", []) 199 | 200 | result = { 201 | "title": topic_title, 202 | "rephrased_title": rephrased_title, 203 | "questions": processed_questions 204 | } 205 | 206 | return result 207 | 208 | 209 | def post(self, shared, prep_res, exec_res_list): 210 | """Update topics with processed content in shared""" 211 | topics = shared.get("topics", []) 212 | 213 | # Map of original topic title to processed content 214 | title_to_processed = { 215 | result["title"]: result 216 | for result in exec_res_list 217 | } 218 | 219 | # Update the topics with processed content 220 | for topic in topics: 221 | topic_title = topic["title"] 222 | if topic_title in title_to_processed: 223 | processed = title_to_processed[topic_title] 224 | 225 | # Update topic with rephrased title 226 | topic["rephrased_title"] = processed["rephrased_title"] 227 | 228 | # Map of original question to processed question 229 | orig_to_processed = { 230 | q["original"]: q 231 | for q in processed["questions"] 232 | } 233 | 234 | # Update each question 235 | for q in topic["questions"]: 236 | original = q["original"] 237 | if original in orig_to_processed: 238 | processed_q = orig_to_processed[original] 239 | q["rephrased"] = processed_q.get("rephrased", original) 240 | q["answer"] = processed_q.get("answer", "") 241 | 242 | # Update shared with modified topics 243 | shared["topics"] = topics 244 | 245 | logger.info(f"Processed content for {len(exec_res_list)} topics") 246 | return "default" 247 | 248 | class GenerateHTML(Node): 249 | """Generate HTML output from processed content""" 250 | def prep(self, shared): 251 | """Get video info and topics from shared""" 252 | video_info = shared.get("video_info", {}) 253 | topics = shared.get("topics", []) 254 | 255 | return { 256 | "video_info": video_info, 257 | "topics": topics 258 | } 259 | 260 | def exec(self, data): 261 | """Generate HTML using html_generator""" 262 | video_info = data["video_info"] 263 | topics = data["topics"] 264 | 265 | title = video_info.get("title", "YouTube Video Summary") 266 | thumbnail_url = video_info.get("thumbnail_url", "") 267 | 268 | # Prepare sections for HTML 269 | sections = [] 270 | for topic in topics: 271 | # Skip topics without questions 272 | if not topic.get("questions"): 273 | continue 274 | 275 | # Use rephrased_title if available, otherwise use original title 276 | section_title = topic.get("rephrased_title", topic.get("title", "")) 277 | 278 | # Prepare bullets for this section 279 | bullets = [] 280 | for question in topic.get("questions", []): 281 | # Use rephrased question if available, otherwise use original 282 | q = question.get("rephrased", question.get("original", "")) 283 | a = question.get("answer", "") 284 | 285 | # Only add bullets if both question and answer have content 286 | if q.strip() and a.strip(): 287 | bullets.append((q, a)) 288 | 289 | # Only include section if it has bullets 290 | if bullets: 291 | sections.append({ 292 | "title": section_title, 293 | "bullets": bullets 294 | }) 295 | 296 | # Generate HTML 297 | html_content = html_generator(title, thumbnail_url, sections) 298 | return html_content 299 | 300 | def post(self, shared, prep_res, exec_res): 301 | """Store HTML output in shared""" 302 | shared["html_output"] = exec_res 303 | 304 | # Write HTML to file 305 | with open("output.html", "w") as f: 306 | f.write(exec_res) 307 | 308 | logger.info("Generated HTML output and saved to output.html") 309 | return "default" 310 | 311 | # Create the flow 312 | def create_youtube_processor_flow(): 313 | """Create and connect the nodes for the YouTube processor flow""" 314 | # Create nodes 315 | process_url = ProcessYouTubeURL(max_retries=2, wait=10) 316 | extract_topics_and_questions = ExtractTopicsAndQuestions(max_retries=2, wait=10) 317 | process_content = ProcessContent(max_retries=2, wait=10) 318 | generate_html = GenerateHTML(max_retries=2, wait=10) 319 | 320 | # Connect nodes 321 | process_url >> extract_topics_and_questions >> process_content >> generate_html 322 | 323 | # Create flow 324 | flow = Flow(start=process_url) 325 | 326 | return flow 327 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import logging 3 | import sys 4 | import os 5 | from flow import create_youtube_processor_flow 6 | 7 | # Set up logging 8 | logging.basicConfig( 9 | level=logging.INFO, 10 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 11 | handlers=[ 12 | logging.StreamHandler(), 13 | logging.FileHandler("youtube_processor.log") 14 | ] 15 | ) 16 | logger = logging.getLogger(__name__) 17 | 18 | def main(): 19 | """Main function to run the YouTube content processor.""" 20 | 21 | # Parse command line arguments 22 | parser = argparse.ArgumentParser( 23 | description="Process a YouTube video to extract topics, questions, and generate ELI5 answers." 24 | ) 25 | parser.add_argument( 26 | "--url", 27 | type=str, 28 | help="YouTube video URL to process", 29 | required=False 30 | ) 31 | args = parser.parse_args() 32 | 33 | # Get YouTube URL from arguments or prompt user 34 | url = args.url 35 | if not url: 36 | url = input("Enter YouTube URL to process: ") 37 | 38 | logger.info(f"Starting YouTube content processor for URL: {url}") 39 | 40 | # Create flow 41 | flow = create_youtube_processor_flow() 42 | 43 | # Initialize shared memory 44 | shared = { 45 | "url": url 46 | } 47 | 48 | # Run the flow 49 | flow.run(shared) 50 | 51 | # Report success and output file location 52 | print("\n" + "=" * 50) 53 | print("Processing completed successfully!") 54 | print(f"Output HTML file: {os.path.abspath('output.html')}") 55 | print("=" * 50 + "\n") 56 | 57 | return 0 58 | 59 | if __name__ == "__main__": 60 | sys.exit(main()) 61 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pocketflow>=0.0.1 2 | requests>=2.28.0 3 | beautifulsoup4>=4.11.0 4 | youtube-transcript-api>=0.6.0 5 | openai>=1.0.0 6 | pyyaml>=6.0 7 | anthropic>=0.5.0 -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Pocket/PocketFlow-Tutorial-Youtube-Made-Simple/9c222f875a71377259033704c86c01d554d1fe8c/utils/__init__.py -------------------------------------------------------------------------------- /utils/call_llm.py: -------------------------------------------------------------------------------- 1 | from anthropic import AnthropicVertex 2 | import os 3 | 4 | def call_llm(prompt: str) -> str: 5 | client = AnthropicVertex( 6 | region=os.getenv("ANTHROPIC_REGION", "us-east5"), 7 | project_id=os.getenv("ANTHROPIC_PROJECT_ID", "") 8 | ) 9 | response = client.messages.create( 10 | max_tokens=1024, 11 | messages=[{"role": "user", "content": prompt}], 12 | model="claude-3-7-sonnet@20250219" 13 | ) 14 | return response.content[0].text 15 | 16 | if __name__ == "__main__": 17 | test_prompt = "Hello, how are you?" 18 | response = call_llm(test_prompt) 19 | print(f"Test successful. Response: {response}") 20 | -------------------------------------------------------------------------------- /utils/html_generator.py: -------------------------------------------------------------------------------- 1 | def html_generator(title, image_url, sections): 2 | """ 3 | Generates an HTML string with a handwriting style using Tailwind CSS. 4 | 5 | :param title: Main title for the page ("Title 1"). 6 | :param image_url: URL of the image to be placed below the main title. 7 | :param sections: A list of dictionaries, each containing: 8 | { 9 | "title": str (Title for the section e.g. "Title 2"), 10 | "bullets": [ 11 | ("bold_text", "regular_text"), 12 | ("bold_text_2", "regular_text_2"), 13 | ... 14 | ] 15 | } 16 | :return: A string of HTML content. 17 | """ 18 | # Start building the HTML 19 | html_template = f""" 20 | 21 | 22 | 23 | 24 | Youtube Made Simple 25 | 26 | 30 | 31 | 32 | 36 | 66 | 67 | 68 |
    69 | 70 |
    71 | Generated by 72 | 74 | Youtube Made Simple 75 | 76 |
    77 | 78 | 79 |

    {title}

    80 | 81 | \"Placeholder""" 86 | 87 | # For each section, add a sub-title (Title 2, etc.) and bullet points. 88 | for section in sections: 89 | section_title = section.get("title", "") 90 | bullets = section.get("bullets", []) 91 | 92 | # Add the section's title (Title 2, Title 3, etc.) 93 | html_template += f""" 94 |

    {section_title}

    95 |
      """ 96 | 97 | # Create list items for each bullet pair 98 | for bold_text, normal_text in bullets: 99 | html_template += f""" 100 |
    • 101 | {bold_text}
      102 |
      {normal_text}
      103 |
    • """ 104 | 105 | html_template += "\n
    " 106 | 107 | # Close the main container and body 108 | html_template += """ 109 |
    110 | 111 | """ 112 | 113 | return html_template 114 | 115 | if __name__ == "__main__": 116 | sections_data = [ 117 | { 118 | "title": "Title 2", 119 | "bullets": [ 120 | ("First line of bullet 1", "Additional normal text."), 121 | ("First line of bullet 2", "Another detail in normal weight."), 122 | ] 123 | }, 124 | { 125 | "title": "Title 3", 126 | "bullets": [ 127 | ("First line of bullet 3", "More text in normal weight for bullet 3.
    1. 1
    2. 2
    3. 3
    "), 128 | ] 129 | } 130 | ] 131 | html_content = html_generator("Title 1", "https://picsum.photos/600/300?grayscale", sections_data) 132 | with open("output.html", "w") as file: 133 | file.write(html_content) 134 | -------------------------------------------------------------------------------- /utils/youtube_processor.py: -------------------------------------------------------------------------------- 1 | import re 2 | import requests 3 | from bs4 import BeautifulSoup 4 | from youtube_transcript_api import YouTubeTranscriptApi 5 | 6 | def extract_video_id(url): 7 | """Extract YouTube video ID from URL""" 8 | pattern = r'(?:v=|\/)([0-9A-Za-z_-]{11})' 9 | match = re.search(pattern, url) 10 | return match.group(1) if match else None 11 | 12 | def get_video_info(url): 13 | """Get video title, transcript and thumbnail""" 14 | video_id = extract_video_id(url) 15 | if not video_id: 16 | return {"error": "Invalid YouTube URL"} 17 | 18 | try: 19 | # Get title using BeautifulSoup 20 | response = requests.get(url) 21 | soup = BeautifulSoup(response.text, 'html.parser') 22 | title_tag = soup.find('title') 23 | title = title_tag.text.replace(" - YouTube", "") 24 | 25 | # Get thumbnail 26 | thumbnail_url = f"https://img.youtube.com/vi/{video_id}/maxresdefault.jpg" 27 | 28 | # Get transcript 29 | transcript_list = YouTubeTranscriptApi.get_transcript(video_id) 30 | transcript = " ".join([entry["text"] for entry in transcript_list]) 31 | 32 | return { 33 | "title": title, 34 | "transcript": transcript, 35 | "thumbnail_url": thumbnail_url, 36 | "video_id": video_id 37 | } 38 | except Exception as e: 39 | return {"error": str(e)} 40 | 41 | if __name__ == "__main__": 42 | test_url = "https://www.youtube.com/watch?v=_1f-o0nqpEI&t" 43 | result = get_video_info(test_url) 44 | print(f"Title: {result.get('title')}") 45 | print(f"Transcript: {result.get('transcript', '')[:150]}...") 46 | print(f"Thumbnail URL: {result.get('thumbnail_url')}") 47 | print(f"Video ID: {result.get('video_id')}") --------------------------------------------------------------------------------