Skip to main content
The YouTube Shorts automation feature enables fully automated video creation and publishing for your YouTube channel. Generate scripts, create visuals, add voiceovers, and upload—all through the CLI.

Overview

MoneyPrinter V2 automates the entire YouTube Shorts creation pipeline:
1

Topic Generation

AI generates a specific video idea based on your channel’s niche
2

Script Writing

Creates an engaging script tailored to YouTube Shorts format
3

Metadata Creation

Generates optimized title, description, and hashtags
4

Visual Generation

AI creates custom images based on the script content
5

Voice Synthesis

Converts script to natural-sounding speech using TTS
6

Video Assembly

Combines images, audio, subtitles, and background music
7

Automated Upload

Publishes directly to your YouTube channel

Setup Requirements

Firefox Profile Configuration

You need a Firefox profile logged into your YouTube account:
  1. Create a dedicated Firefox profile for automation
  2. Log into YouTube Studio with your target channel
  3. Note the profile path (usually ~/.mozilla/firefox/xxxxxxxx.profile-name)

Configuration Settings

In your config.json, configure these YouTube-specific settings:
{
  "script_sentence_length": 10,
  "is_for_kids": false,
  "headless": false,
  "threads": 4,
  "stt_provider": "local_whisper",
  "whisper_model": "base",
  "whisper_device": "cpu",
  "whisper_compute_type": "int8"
}

API Keys Required

  • Nano Banana 2 API (Gemini image generation): Set nanobanana2_api_key
  • AssemblyAI (optional, for cloud STT): Set assemblyai_api_key

Account Management

Creating a YouTube Account

From the main menu, select YouTube Shorts Automater and create a new account:
=> Generated ID: 550e8400-e29b-41d4-a716-446655440000
=> Enter a nickname for this account: TechShorts
=> Enter the path to the Firefox profile: /home/user/.mozilla/firefox/abc123.default
=> Enter the account niche: Technology Tips and Tricks
=> Enter the account language: English

Account Properties

Niche

The content focus of your channel (e.g., “Motivational Quotes”, “Life Hacks”, “Tech Reviews”)

Language

The language for script generation and TTS output

Firefox Profile

Path to a Firefox profile authenticated with your YouTube channel

Video Generation Workflow

Manual Generation

Select Generate and Upload a Video from the YouTube menu:
def generate_video(self, tts_instance: TTS) -> str:
    # Generate the Topic
    self.generate_topic()

    # Generate the Script
    self.generate_script()

    # Generate the Metadata
    self.generate_metadata()

    # Generate the Image Prompts
    self.generate_prompts()

    # Generate the Images
    for prompt in self.image_prompts:
        self.generate_image(prompt)

    # Generate the TTS
    self.generate_script_to_speech(tts_instance)

    # Combine everything
    path = self.combine()

    return path
The system will:
  1. Generate a topic based on your niche
  2. Write a script (length configured by script_sentence_length)
  3. Create title and description
  4. Generate AI images for visual content
  5. Convert script to speech
  6. Combine everything into a vertical video (1080x1920)
  7. Add subtitles automatically
  8. Mix in background music at reduced volume
After generation completes, you’ll be prompted to upload:
Do you want to upload this video to YouTube? (Yes/No):

Script Generation

Scripts are created with specific constraints:
def generate_script(self) -> str:
    sentence_length = get_script_sentence_length()
    prompt = f"""
    Generate a script for a video in {sentence_length} sentences, depending on the subject of the video.

    The script is to be returned as a string with the specified number of paragraphs.

    Here is an example of a string:
    "This is an example string."

    Do not under any circumstance reference this prompt in your response.

    Get straight to the point, don't start with unnecessary things like, "welcome to this video".

    Obviously, the script should be related to the subject of the video.
    
    YOU MUST NOT EXCEED THE {sentence_length} SENTENCES LIMIT. MAKE SURE THE {sentence_length} SENTENCES ARE SHORT.
    YOU MUST NOT INCLUDE ANY TYPE OF MARKDOWN OR FORMATTING IN THE SCRIPT, NEVER USE A TITLE.
    YOU MUST WRITE THE SCRIPT IN THE LANGUAGE SPECIFIED IN [LANGUAGE].
    
    Subject: {self.subject}
    Language: {self.language}
    """
    completion = self.generate_response(prompt)
    return completion

Video Assembly

Image Processing

Images are automatically resized to 9:16 aspect ratio (YouTube Shorts format):
def combine(self) -> str:
    combined_image_path = os.path.join(ROOT_DIR, ".mp", str(uuid4()) + ".mp4")
    threads = get_threads()
    tts_clip = AudioFileClip(self.tts_path)
    max_duration = tts_clip.duration
    req_dur = max_duration / len(self.images)

    # Make a generator that returns a TextClip when called
    generator = lambda txt: TextClip(
        txt,
        font=os.path.join(get_fonts_dir(), get_font()),
        fontsize=100,
        color="#FFFF00",
        stroke_color="black",
        stroke_width=5,
        size=(1080, 1920),
        method="caption",
    )

Subtitle Generation

Subtitles are generated using either:
  • Local Whisper (faster-whisper): Runs on your machine (default)
  • AssemblyAI: Cloud-based transcription (requires API key)
def generate_subtitles(self, audio_path: str) -> str:
    provider = str(get_stt_provider() or "local_whisper").lower()

    if provider == "local_whisper":
        return self.generate_subtitles_local_whisper(audio_path)

    if provider == "third_party_assemblyai":
        return self.generate_subtitles_assemblyai(audio_path)

Automated Uploading

The upload process uses Selenium to automate YouTube Studio:
def upload_video(self) -> bool:
    try:
        self.get_channel_id()

        driver = self.browser

        # Go to youtube.com/upload
        driver.get("https://www.youtube.com/upload")

        # Set video file
        FILE_PICKER_TAG = "ytcp-uploads-file-picker"
        file_picker = driver.find_element(By.TAG_NAME, FILE_PICKER_TAG)
        INPUT_TAG = "input"
        file_input = file_picker.find_element(By.TAG_NAME, INPUT_TAG)
        file_input.send_keys(self.video_path)

        # Wait for upload to finish
        time.sleep(5)

        # Set title
        textboxes = driver.find_elements(By.ID, YOUTUBE_TEXTBOX_ID)

        title_el = textboxes[0]
        description_el = textboxes[-1]

        title_el.click()
        time.sleep(1)
        title_el.clear()
        title_el.send_keys(self.metadata["title"])

        # Set description
        time.sleep(10)
        description_el.click()
        time.sleep(0.5)
        description_el.clear()
        description_el.send_keys(self.metadata["description"])
Videos are uploaded as Unlisted by default. You can change visibility manually in YouTube Studio.

CRON Scheduling

Automate video uploads on a schedule:

Schedule Options

Once Daily

Upload one video per day automatically

Twice Daily

Upload at 10:00 AM and 4:00 PM

Setting Up CRON Jobs

From the YouTube menu, select Setup a CRON Job:
user_input = int(question("Select an Option: "))

cron_script_path = os.path.join(ROOT_DIR, "src", "cron.py")
command = ["python", cron_script_path, "youtube", selected_account['id'], get_active_model()]

def job():
    subprocess.run(command)

if user_input == 1:
    # Upload Once
    schedule.every(1).day.do(job)
    success("Set up CRON Job.")
elif user_input == 2:
    # Upload Twice a day
    schedule.every().day.at("10:00").do(job)
    schedule.every().day.at("16:00").do(job)
    success("Set up CRON Job.")
The CRON job will continue running as long as the script is active. For production use, consider setting up a system-level cron job or systemd service.

Video History

View all uploaded videos by selecting View Uploaded Videos from the YouTube menu:
+----+---------------------+--------------------------------------------------------------+
| ID | Date                | Title                                                        |
+----+---------------------+--------------------------------------------------------------+
| 1  | 2026-03-01 14:23:45 | 10 Mind-Blowing Tech Gadgets You Need in 2026 #TechReview..|
| 2  | 2026-03-02 10:15:22 | How AI Will Change Everything in 2026 #FutureTech #AI...   |
+----+---------------------+--------------------------------------------------------------+
Video metadata is cached locally in .mp/cache/youtube_cache.json.

Troubleshooting

Ensure your Firefox profile is properly logged into YouTube Studio. Visit https://studio.youtube.com in the profile and verify authentication.
Check your nanobanana2_api_key in config.json. Verify the API key is valid and has sufficient quota.
If using local_whisper, ensure faster-whisper is installed: pip install faster-whisper. For AssemblyAI, verify your API key.
Increase threads in config.json for faster video rendering. Ensure you have sufficient RAM and CPU resources.

Best Practices

Content Quality

Use specific, engaging niches. Generic topics produce lower-quality content.

Upload Schedule

Maintain consistent upload times for better algorithm performance.

Script Length

Keep scripts between 8-12 sentences for optimal Short duration (30-60 seconds).

Review Before Upload

Preview generated videos before uploading to ensure quality meets your standards.

Source Code Reference

  • Main class implementation: src/classes/YouTube.py
  • CRON automation: src/cron.py
  • Menu interface: src/main.py:67-215

Build docs developers (and LLMs) love