gemini-youtube-automation: A Cron-Driven Pipeline That Writes, Renders and Uploads Its Own Lessons
A fully autonomous AI Agent/Python pipeline that utilizes Large Language Models (LLMs) like Gemini to generate content, produce videos, and automatically upload educational videos to YouTube.
At a glance
- What is it?
- The repository wires Gemini 2.5 Flash, gTTS, MoviePy and the YouTube Data API into a GitHub Actions job that ships one long-form lesson and one Short per day. It is a working reference for unattended publishing, not a general-purpose video framework.
- Who is it for?
- Adopt this if you want to study or fork a complete unattended publishing loop where the scheduler, the renderer and the uploader all live in one repository. Do not adopt it if you need editorial control over what gets published, if your videos depend on footage you own, or if you want per-video analytics driving the next topic.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Gap It Fills: Publishing Without a Human in the Loop
Most video generation demos stop at a rendered file. This repository carries the process through to the upload call, which is the part that normally keeps a human in the loop. The README describes the target state plainly: a bot that runs on GitHub Actions at 7:00 AM UTC, reads a content plan, writes a script, produces a long-form lesson and a vertical Short, generates thumbnails, uploads both, and commits the updated plan back to the repository. The audience is narrow. It suits a solo developer who wants a channel that publishes on a schedule without owning a server, and it suits anyone who wants to read a complete Python implementation of the script-to-upload chain rather than a notebook fragment. It does not suit a team that needs approval gates before publication, and it does not suit anyone whose videos depend on licensed footage they supply themselves, because the imagery path is Pexels stock search.
The Daily Loop: content_plan.json as the Only Durable State
The architecture in the README is a straight line with one piece of persistent state. The GitHub Actions scheduler fires, the pipeline opens content_plan.json and selects the next lesson marked pending, and Gemini 2.5 Flash produces a seven to eight slide script plus a one-sentence Short script and hashtags. From there the renderer takes over: gTTS generates narration per slide, Pexels supplies background images matched to each slide topic, background music is mixed in, and MoviePy with FFmpeg produces a 1920x1080 long-form file and a 1080x1920 Short from the same lesson. Each format gets its own thumbnail. The YouTube Data API v3 receives both uploads with titles, descriptions and hashtags. The final step commits content_plan.json back to the repository with the lesson marked complete. That commit is the checkpoint. If the job dies before it, the next run picks the same lesson again; if it dies after the upload but before the commit, the same lesson can be uploaded twice. Nothing in the README describes an idempotency key or a deduplication check against already-uploaded video IDs, so the ordering of the upload and the commit is the whole safety mechanism.
Running It: Secrets, Base64 Credentials and One Entry Point
The setup path is short. You clone the repository, run pip install -r requirements.txt, and add four repository secrets under Settings, then Secrets and variables, then Actions. GOOGLE_API_KEY comes from Google AI Studio. PEXELS_API_KEY comes from Pexels. The other two are the awkward ones: CLIENT_SECRET_B64 and CREDENTIALS_B64 are the YouTube OAuth client_secrets.json and credentials.json files encoded in base64, because GitHub Actions secrets hold strings, not files. The pipeline decodes them at runtime. Local execution is a single command, python main.py, which assumes the same environment variables are present in your shell. Python 3.11 is the documented version. The workflow itself lives at .github/workflows/main.yml, and the README shows a badge for it, so the cron expression and the job steps are inspectable there rather than described in prose. There are no releases retrieved for this repository, so pinning to a tag is not an option the material supports; you would be tracking main.
Where the Pipeline Breaks or Should Not Be Used
The failure modes cluster around the parts that touch external services. gTTS is a network call to Google Translate's speech endpoint, and it is not an authenticated API with a published quota, so a run can fail for reasons the pipeline cannot control or retry intelligently. Pexels image search is also a live dependency, and the README does not describe a fallback when a topic returns no usable image, so a slide with no match is an open question. The OAuth credentials deserve particular attention: a refresh token that expires or is revoked turns every subsequent scheduled run into a failed upload after the render has already been paid for in runner minutes. Quota is the other hard ceiling. The YouTube Data API charges uploads against a daily quota, and this pipeline performs two video uploads plus thumbnail sets per run, so a project with a low default quota will hit the wall before the renderer does. The wrong-tool case is editorial. If your channel has a voice, a review step, or a claim you have to stand behind, an unattended generator that publishes whatever Gemini produces is the wrong instrument, regardless of how clean the code is.
Compared With a Human-Edited Editing Workflow
The obvious alternative is the conventional route: write the script yourself or with an assistant, record narration, cut in an editor such as DaVinci Resolve or Premiere, export, and upload through YouTube Studio. The difference is not quality in the abstract, it is where the human sits. In the conventional route the human sits between script and render, which is where corrections are cheap. Here the human sits in content_plan.json, before the script exists, and after that the lesson is committed. That makes the plan file the real editorial surface. Editing a topic line in content_plan.json changes what tomorrow's run produces; editing the script does not, because the script is regenerated each run and never persisted as a reviewed artifact in the flow the README describes. A second alternative is a hosted automation service that connects a model to an upload endpoint through a visual builder. Those trade repository access for a UI, which means you cannot diff the pipeline, cannot run it locally with python main.py, and cannot inspect the render logic when a slide comes out wrong. If you want to read and change the code that produces your videos, this repository is the more legible starting point.
Maintenance Surface and the Licence Contradiction
Maintenance cost here is dominated by three moving parts rather than by the Python itself. Gemini model names change and deprecate, so the string that selects Gemini 2.5 Flash will need updating on Google's schedule, not yours. The YouTube Data API version and its OAuth scopes are stable but not frozen, and the base64-encoded credential secrets will need regeneration whenever the OAuth client is rotated. MoviePy and FFmpeg version drift affects rendering output, particularly around codec defaults, and the README pins no versions beyond Python 3.11. On licensing, the material contradicts itself. The README's badge and its License section both state MIT, and it points to a LICENSE file, while the repository metadata supplied for this review reports the licence as unknown. That is a discrepancy to resolve by opening the LICENSE file directly before you build anything commercial on top of the code. Nothing here is legal advice, but a repository with no detected licence is not the same as a repository with an MIT file, and the difference matters if you plan to redistribute a fork.
Self-Extending Curriculum and What It Implies
One design choice deserves separate scrutiny. The README lists AI-generated curriculum as a feature: Gemini creates and extends the course plan automatically, and the bot is currently working through an AI for Developers series covering generative AI, LLMs, prompt engineering, RAG, vector databases, LangGraph, fine-tuning and computer vision. The progress tracker is content_plan.json. This is the most interesting part of the project and also the least specified. The README does not say how new lessons are appended, whether the model sees the existing plan before extending it, or what stops the series from drifting or repeating a topic. Since the plan is committed back to the repository after each run, the git history of content_plan.json is the audit trail for that behaviour, and reading a few weeks of that file's diffs would tell you more about curriculum quality than any description could. If you fork this, that file is where your editorial judgement has to go, because it is the only input a human can shape without touching Python.
Editorial conclusion
Adopt this if you want to study or fork a complete unattended publishing loop where the scheduler, the renderer and the uploader all live in one repository. Do not adopt it if you need editorial control over what gets published, if your videos depend on footage you own, or if you want per-video analytics driving the next topic. Before running it against a live channel, verify the licence situation, since the README states MIT and the repository metadata reports no licence; confirm the OAuth token refresh behaviour, because the workflow depends on base64-encoded credentials surviving between runs; and check that your YouTube API project has the quota headroom for two uploads plus two thumbnail sets per day.
Community notes