Building a YouTube to Blog Converter: A Codebase Deep Dive

Johnny Chan
5 min readNov 24, 2024

--

Hey fellow developers! 👋 Today, I would like to walk you through a nifty open-source application that transforms YouTube videos into well-structured blog posts using the power of AI. The codes are available in our github. This app was inspired by the Youtube Summarizer (another amazing open-source project). Some of its’ libraries are utilized to build my blog converter. Let’s dive into the main orchestrator of this application

The Core Components

Our application is built using Streamlit, a fantastic Python framework for creating web applications, and leverages OpenAI’s GPT model for content generation. Here’s how it all comes together.

Setting Up the Stage

First, let’s look at the initial setup in app.py:

import streamlit as st
import os
from src.video_info import GetVideo
from src.model import Model
from src.prompt import Prompt
from src.misc import Misc
from src.db_handler import DatabaseHandler
from st_copy_to_clipboard import st_copy_to_clipboard

st.set_page_config(
page_title="YouTube to Blog by HAZL",
layout="wide",
)

hide_st_style = """
<style>
#MainMenu {visibility: hidden;}
.stDeployButton {
visibility: hidden;
}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_st_style, unsafe_allow_html=True)

This section configures our Streamlit page and adds some custom CSS to hide default Streamlit elements. It’s like setting up our stage before the main performance! 🎭

The Star of the Show: YouTubeToBlog Class

The main functionality is encapsulated in the YouTubeToBlog class. Think of it as our show director, orchestrating all the moving parts. Here’s what makes it tick:

1. Initialization

class YouTubeToBlog:
def __init__(self):
self.youtubeUrl = None
self.videoId = None
self.videoTitle = None
self.videoTranscript = None
self.blogPost = None
self.col1 = None
self.col2 = None
self.db = DatabaseHandler()

if 'openai_api_key' not in st.session_state:
apiKey = self.db.get_api_key()
if apiKey:
st.session_state['openai_api_key'] = apiKey

The __init__ method sets up our stage props — initializing variables for the YouTube URL, video details, and blog post content. It also creates a connection to our database handler for storing API keys.

2. API Key Management

The app needs an OpenAI API key to work its magic. We’ve got two methods handling this:

    def setup_sidebar(self):
with st.sidebar:
st.title("Settings")
apiKey = st.text_input("Enter OpenAI API Key",
value=st.session_state.get('openai_api_key', ''),
type="password")

if st.button("Save API Key"):
self.db.save_api_key(apiKey)
st.session_state['openai_api_key'] = apiKey
st.success("API key saved successfully!")

def check_api_key(self):
if 'openai_api_key' not in st.session_state or not st.session_state['openai_api_key']:
st.warning("Please enter your OpenAI API key in the sidebar.", icon="⚠️")
return False
return True

This creates a sleek sidebar where users can input and save their API keys securely. The keys are stored in a SQLite database (pretty neat, right? 🔐).

3. YouTube Video Processing

    def get_youtube_info(self):
self.youtubeUrl = st.text_input("Enter YouTube Video Link")

if self.youtubeUrl:
self.videoId = GetVideo.Id(self.youtubeUrl)
if self.videoId is None:
st.write("**Error**")
st.image("https://i.imgur.com/KWFtgxB.png", use_column_width=True)
st.stop()
self.videoTitle = GetVideo.title(self.youtubeUrl)
st.write(f"**{self.videoTitle}**")
st.image(f"http://img.youtube.com/vi/{self.videoId}/0.jpg", use_column_width=True)

This section handles the YouTube video input. It:

  • Takes a YouTube URL
  • Extracts the video ID
  • Fetches the video title
  • Displays the thumbnail

If something goes wrong, it shows a friendly error message with a meme (because who doesn’t love memes? 😄).

4. The Magic Sauce: Blog Post Generation

    def generate_blog_post(self):
if not self.check_api_key():
return

if st.button(":rainbow[**Generate Blog Post**]"):
self.videoTranscript = GetVideo.transcript(self.youtubeUrl)
blogPrompt = """Create a well-structured blog post from this video transcript.
The blog post should:
1. Have an engaging title
2. Include an introduction
3. Break down the main points into sections with subheadings
4. Include a conclusion
5. Use proper formatting with markdown
6. Maintain a professional yet conversational tone
7. Include relevant quotes from the video where appropriate

Format the blog post in markdown."""

self.blogPost = Model.openai_chatgpt(
transcript=self.videoTranscript,
prompt=blogPrompt
)

st.markdown("## Generated Blog Post:")
st.markdown(self.blogPost)

# Download and copy options
st.download_button(
label="Download Blog Post",
data=self.blogPost,
file_name=f"Blog-{self.videoTitle}.md"
)
st_copy_to_clipboard(self.blogPost)

This is where the real magic happens! The method:

  • Fetches the video transcript
  • Sends it to OpenAI with a well-crafted prompt
  • Generates a structured blog post
  • Provides options to download or copy the generated content

Putting It All Together

The run method ties everything together in a clean, two-column layout:

    def run(self):
st.title("YouTube to Blog Converter")

self.setup_sidebar()
self.col1, padding_col, self.col2 = st.columns([1, 0.1, 1])

with self.col1:
self.get_youtube_info()

ranLoader = Misc.loaderx()
n, loader = ranLoader[0], ranLoader[1]

with self.col2:
with st.spinner(loader[n]):
self.generate_blog_post()

st.write(Misc.footer(), unsafe_allow_html=True)

Cool Features You Might Miss

  • Random Loading Messages: The app uses different loading messages to keep things interesting (check out src/misc.py).
  • Clipboard Integration: Easy one-click copying of the generated blog post.
  • Markdown Support: The generated blog posts come formatted in Markdown, ready for platforms like Medium or dev.to.
  • Error Handling: Graceful handling of invalid URLs and API issues.

Under the Hood

The application uses several helper classes (found in the src directory):

  • GetVideo: Handles YouTube video information extraction
  • Model: Manages OpenAI API interactions
  • DatabaseHandler: Handles API key storage
  • Misc: Contains utility functions

Running the App

Thanks to the included Dockerfile, getting started is as simple as:

docker build -t youtube-to-blog .
docker run -p 8501:8501 youtube-to-blogb

This is what the UI looks like after running a video as a sample:

Final Thoughts

This app is a perfect example of combining different technologies (Streamlit, OpenAI, YouTube API) to create something useful. It’s also a great starting point for anyone looking to build their own AI-powered content tools.

Want to contribute or check out the code? The project is MIT licensed, so feel free to fork, modify, and make it your own! 🚀

Oh… One More Thing 😊

HAZL APP GALLERY IS ALMOST READY!! We are working very hard to roll out the first beta version of our platform. We will load all the apps we have built to the gallery and make them public and free! Stay tuned by signing up for early access at hazl.ca. Cheers!!!

--

--

Johnny Chan
Johnny Chan

Written by Johnny Chan

Co-founder of Hazl AI -- a platform for your one-stop AI and cloud services. Visit us at hazl.ca

No responses yet