A fully automated system for creating and publishing shorts/reels. It generates video content from a JSON data source, creates pixel-perfect visuals, edits them into videos with FFmpeg, and uploads them to YouTube and Facebook.
- Zero-Touch Automation: Runs purely on code (GitHub Actions or Local Cron).
- Single Source of Truth: All data (captions, hashtags, questions) lives in
questions.json. - Cross-Platform: Supports Windows and Linux.
- Smart Tracking: Never repeats questions; tracks history in
used_questions.log.
- Prerequisites
- Installation
- Configuration
- Running Locally
- GitHub Actions Automation
- Data Format
- Troubleshooting
- Python: 3.10 or higher
- FFmpeg: Must be installed and added to your system PATH.
- Windows:
winget install ffmpegor download from ffmpeg.org. - Linux:
sudo apt install ffmpeg
- Windows:
- API Credentials:
- Google/YouTube Data API (OAuth 2.0 Client ID)
- Facebook Graph API (Page Access Token)
- Telegram Bot API (Token & Chat ID)
git clone https://github.com/yourusername/educational-video-automation.git
cd educational-video-automationWindows:
python -m venv venv
.\venv\Scripts\activateLinux/Mac:
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txtCreate a .env file in the root directory:
# Facebook
FACEBOOK_PAGE_ID=your_page_id
FACEBOOK_ACCESS_TOKEN=your_token
# YouTube (Client ID/Secret needed for local auth flow)
YOUTUBE_CLIENT_ID=your_client_id
YOUTUBE_CLIENT_SECRET=your_secret
# Telegram
TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_idTo add background music to your videos:
- Place an MP3 file in the
assets/music/directory. - The system will automatically detect the first
.mp3file found and loop it as background music.- Effect: The audio loops infinitely to match the video duration.
- Attribution: The system automatically appends the required Creative Commons license to the video description.
- Note: If no file is found, the video will be created without background music.
The first time you run the script locally, it will open a browser to authenticate with YouTube. This generates client_secrets.json (input) and youtube_credentials.json (output session).
To run the pipeline manually:
# Ensure venv is active
python main.py- Selects Question: Picks the first unused question from
data/questions.json. - Generates Assets: Creates images (
assets/temp/) and video. - Uploads: Pushes to YouTube Shorts and Facebook Reels.
- Notifies: Sends a Telegram message with status.
- Updates Log: Marks question as used in
data/used_questions.log.
This project includes a workflow (.github/workflows/daily_video.yml) to run the pipeline automatically twice a day (Manual trigger also available).
Since GitHub Actions cannot open a browser for YouTube login, you must encode your local credential files and save them as Secrets.
-
Run the Secret Generator:
# Run this locally after you have successfully authenticated once python generate_secrets.py -
Copy the Output: The script will print Base64 strings for your files.
-
Add to GitHub Repository Secrets (Settings > Secrets and variables > Actions):
CLIENT_SECRETS_BASE64: (Content from generate_secrets.py)YOUTUBE_CREDENTIALS_BASE64: (Content from generate_secrets.py)FACEBOOK_PAGE_IDFACEBOOK_ACCESS_TOKENTELEGRAM_BOT_TOKENTELEGRAM_CHAT_ID
Follow these steps to generate a Facebook Page Access Token for the automation system.
- Go to: https://developers.facebook.com/tools/explorer/
- Log in with the Facebook account that manages the page.
- In the Meta App dropdown, select Business Store.
- In User or Page, select User Token.
- Click Generate Access Token.
Enable the following permissions:
business_management
pages_show_list
pages_manage_metadata
pages_manage_posts
pages_manage_engagement
pages_read_engagement
pages_read_user_content
instagram_basic
instagram_content_publish
Then confirm the permissions.
- In the API endpoint field, run:
GET /me/accounts
- Click Submit.
The response will include the Page Access Token for each page.
Example response:
{
"data": [
{
"name": "Page Name",
"id": "PAGE_ID",
"access_token": "PAGE_ACCESS_TOKEN"
}
]
}Copy the access_token corresponding to the page used for automation.
Paste the token into your .env file:
FACEBOOK_ACCESS_TOKEN=PAGE_ACCESS_TOKEN
FACEBOOK_PAGE_ID=YOUR_PAGE_ID
Run:
GET /{PAGE_ID}?fields=instagram_business_account
Expected response:
{
"instagram_business_account": {
"id": "INSTAGRAM_BUSINESS_ID"
}
}If this field is present, Instagram cross-posting will work correctly.
- Never commit access tokens to the repository.
- Store tokens only in environment variables or secret managers.
The system relies on data/questions.json. Each entry is self-contained.
[
{
"id": 1001,
"difficulty": "Easy",
"question": "What is the capital of France?",
"options": ["Berlin", "Madrid", "Paris", "Rome"],
"answer": "C",
"explanation": "Paris is the capital and most populous city of France.",
"captions": ["Generic Caption 1 π«π·", "Test Your Knowledge! π"],
"descriptions": ["Answer: C\n\nExplanation: Paris is the capital..."],
"hashtags": ["#geography", "#quiz", "#shorts"]
}
]1. ffmpeg not found or ImageMagick errors
- Ensure FFmpeg is installed and accessible in your system PATH.
- Run
ffmpeg -versionto verify.
2. YouTube Upload Fails (400/401)
- Your
youtube_credentials.jsonmight be expired. - Delete
youtube_credentials.json, runpython main.pylocally to re-authenticate, then update your GitHub Secrets.
3. "Invalid video description"
- Ensure your
descriptionsfield in JSON doesn't contain forbidden characters (like<or>).
Legacy Note: If you are upgrading from the older multi-file version.
Version 2.0 replaces the scattered captions.json, hashtags.json, etc., with a single questions.json.
- Old Structure: Separate files for every metadata type.
- New Structure: Everything lives inside the Question object.
To migrate, use the included scripts or manually merge your data into the new JSON format shown above.
This project is licensed under the MIT License - see the LICENSE file for details.
Developed by Ankit (or your name/organization).
- GitHub: Ankit Kumar
- LinkedIn: ankit59
For support, questions, or collaboration:
- Email: ankitkumar81919895@gmail.com
- Issues: GitHub Issues
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request