Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: MLSAKIIT/ForgeTube
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: MLSAKIIT/ForgeTube
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: flask-frontend
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 2 commits
  • 14 files changed
  • 1 contributor

Commits on Mar 10, 2025

  1. Copy the full SHA
    977e839 View commit details
  2. .

    sohambuilds committed Mar 10, 2025
    Copy the full SHA
    cfb1967 View commit details
Showing with 1,821 additions and 0 deletions.
  1. +8 −0 .env.example
  2. +186 −0 app.py
  3. +50 −0 config.py
  4. +95 −0 flask_frontend_README.md
  5. +10 −0 requirements.txt
  6. +145 −0 static/css/landing.css
  7. +426 −0 static/css/style.css
  8. +182 −0 static/js/main.js
  9. +95 −0 templates/create.html
  10. +23 −0 templates/error.html
  11. +312 −0 templates/index.html
  12. +93 −0 templates/layout.html
  13. +130 −0 templates/progress.html
  14. +66 −0 templates/refine.html
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Flask Configuration
FLASK_APP=app.py
FLASK_ENV=development
SECRET_KEY=your-secret-key-here

# ForgeTube API Keys
GEMINI_API_KEY=your-gemini-api-key-here
SERP_API_KEY=your-serp-api-key-here
186 changes: 186 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
from flask import Flask, render_template, request, redirect, url_for, jsonify, session, send_from_directory
import os
import json
import uuid
from werkzeug.utils import secure_filename
import time
import threading
from datetime import datetime


app = Flask(__name__)
app.secret_key = os.urandom(24)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max upload size
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['RESULTS_FOLDER'] = 'results'

# Ensure upload and results directories exist
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['RESULTS_FOLDER'], exist_ok=True)

# Task tracking storage
tasks = {}

# Custom Jinja2 filters
@app.template_filter('timestamp_to_datetime')
def timestamp_to_datetime(timestamp):
"""Convert Unix timestamp to formatted datetime string"""
return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')

# Helper functions
def create_or_check_folder(folder_path):
"""
Creates a folder if it doesn't exist.
If folder exists, checks for files and returns error message if any are found.
Args:
folder_path (str): Path to the folder
Returns:
tuple: (success, message)
"""
if not os.path.exists(folder_path):
os.makedirs(folder_path)
return True, f"Created Folder: {folder_path}"
else:
if any(os.listdir(folder_path)):
return False, f"Folder '{folder_path}' already exists and contains files. Please remove them or use a different folder."
return True, f"Folder '{folder_path}' exists but is empty."

def generate_video_task(task_id, topic, duration, key_points, api_keys):
"""
Background task to generate video
"""
task = tasks[task_id]
task['status'] = 'Generating script...'
time.sleep(2) # Simulate script generation

# TODO: Replace with actual script generation
# generator = VideoScriptGenerator(api_key=api_keys['gemini'], serp_api_key=api_keys['serp'])
# script = generator.generate_script(topic, duration, key_points)

script = {"topic": topic, "audio_script": [{"text": "This is a test script"}]}
task['script'] = script
task['status'] = 'Script generated'

task['status'] = 'Generating images...'
time.sleep(3) # Simulate image generation

task['status'] = 'Generating audio...'
time.sleep(2) # Simulate audio generation

task['status'] = 'Assembling video...'
time.sleep(3) # Simulate video assembly

task['status'] = 'Completed'
task['result_url'] = f"/results/{task_id}.mp4"

# Routes
@app.route('/')
def index():
"""Home page"""
return render_template('index.html')

@app.route('/create', methods=['GET', 'POST'])
def create():
"""Create new video page"""
if request.method == 'POST':
# Get form data
topic = request.form.get('topic', '')
duration = int(request.form.get('duration', 60))
key_points_text = request.form.get('key_points', '')
key_points = [point.strip() for point in key_points_text.split(',') if point.strip()]

# Get API keys
gemini_api = request.form.get('gemini_api', '')
serp_api = request.form.get('serp_api', '')

# Validate inputs
if not topic:
return render_template('create.html', error="Topic is required")

if not gemini_api or not serp_api:
return render_template('create.html',
error="API keys are required. Get your Gemini API key at https://aistudio.google.com/apikey and Serp API key at https://serpapi.com")

# Create task
task_id = str(uuid.uuid4())
task = {
'id': task_id,
'topic': topic,
'duration': duration,
'key_points': key_points,
'status': 'Queued',
'created_at': time.time(),
'api_keys': {
'gemini': gemini_api,
'serp': serp_api
}
}
tasks[task_id] = task

# Start task in background
threading.Thread(
target=generate_video_task,
args=(task_id, topic, duration, key_points, task['api_keys'])
).start()

# Redirect to task progress page
return redirect(url_for('task_progress', task_id=task_id))

return render_template('create.html')

@app.route('/task/<task_id>')
def task_progress(task_id):
"""Task progress page"""
task = tasks.get(task_id)
if not task:
return render_template('error.html', message="Task not found"), 404

return render_template('progress.html', task=task)

@app.route('/api/task/<task_id>')
def task_status(task_id):
"""API endpoint to get task status"""
task = tasks.get(task_id)
if not task:
return jsonify({"error": "Task not found"}), 404

# Return task data without API keys for security
safe_task = {**task}
if 'api_keys' in safe_task:
del safe_task['api_keys']

return jsonify(safe_task)

@app.route('/refine/<task_id>', methods=['GET', 'POST'])
def refine_script(task_id):
"""Refine script page"""
task = tasks.get(task_id)
if not task:
return render_template('error.html', message="Task not found"), 404

if request.method == 'POST':
feedback = request.form.get('feedback', '')
if feedback:
# TODO: Implement script refinement with API
# generator = VideoScriptGenerator(api_key=task['api_keys']['gemini'],
# serp_api_key=task['api_keys']['serp'])
# refined_script = generator.refine_script(task['script'], feedback)
# task['script'] = refined_script

# For now, just acknowledge the feedback
task['feedback'] = feedback
task['status'] = 'Script refined, ready to generate'

return redirect(url_for('task_progress', task_id=task_id))

return render_template('refine.html', task=task)

@app.route('/results/<path:filename>')
def get_result(filename):
"""Serve result files"""
return send_from_directory(app.config['RESULTS_FOLDER'], filename)

if __name__ == '__main__':
app.run(debug=True)
50 changes: 50 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os

class Config:
"""Base configuration"""
SECRET_KEY = os.environ.get('SECRET_KEY') or os.urandom(24)
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB max upload size
UPLOAD_FOLDER = 'uploads'
RESULTS_FOLDER = 'results'

# ForgeTube resources paths
SCRIPTS_PATH = "resources/scripts/"
IMAGES_PATH = "resources/images/"
AUDIO_PATH = "resources/audio/"
FONT_PATH = "resources/font/font.ttf"

# Default video settings
DEFAULT_DURATION = 60 # in seconds
MAX_DURATION = 300 # 5 minutes max

# UI Settings
ACCENT_COLOR = "#6366F1" # Indigo
DARK_BG = "#121212"
DARKER_BG = "#0A0A0A"
TEXT_COLOR = "#E5E7EB"

class DevelopmentConfig(Config):
"""Development configuration"""
DEBUG = True
TESTING = False

class TestingConfig(Config):
"""Testing configuration"""
DEBUG = False
TESTING = True

class ProductionConfig(Config):
"""Production configuration"""
DEBUG = False
TESTING = False

config_by_name = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig
}

def get_config():
"""Return the appropriate configuration object based on environment variable"""
env = os.environ.get('FLASK_ENV', 'development')
return config_by_name[env]
95 changes: 95 additions & 0 deletions flask_frontend_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ForgeTube Web Frontend

A modern, dark-themed web interface for ForgeTube, an AI-powered video generation system.

## Overview

This Flask application provides an intuitive web interface for interacting with ForgeTube's automated video generation capabilities. It allows users to:

1. Input topics, durations, and key points for video generation
2. Review and refine AI-generated scripts
3. Track the progress of video generation
4. Preview and download the final videos

## Features

- **Modern, Dark UI**: Sleek, minimalistic interface with a dark color scheme
- **Responsive Design**: Works well on desktop and mobile devices
- **Real-time Progress Tracking**: Live updates on video generation status
- **Script Refinement**: Interactive script review and feedback system
- **Secure API Key Management**: User-provided API keys used securely for content generation

## Installation

1. Clone the repository:

```bash
git clone https://github.com/MLSAKIIT/ForgeTube.git
cd ForgeTube
```

2. Create and activate a virtual environment:

```bash
python -m venv venv
# On Windows
venv\Scripts\activate
# On macOS/Linux
source venv/bin/activate
```

3. Install dependencies:

```bash
pip install -r requirements.txt
```

4. Create a `.env` file based on `.env.example`:
```bash
cp .env.example .env
```
Then edit the `.env` file with your API keys.

## Usage

1. Start the Flask development server:

```bash
flask run
```

2. Open your browser and navigate to:

```
http://127.0.0.1:5000/
```

3. Follow the on-screen instructions to create your first video.

## Requirements

- Python 3.8 or higher
- Gemini API key (from Google AI Studio)
- SERP API key (from serpapi.com)
- FFmpeg (for video processing)

## Integration with ForgeTube Core

This frontend is designed to work with ForgeTube's core modules:

- `diffusion/scripts/generate_script.py`: For script generation
- `diffusion/scripts/generate_image_local.py`: For image generation
- `tts/scripts/generate_audio.py`: For audio generation
- `assembly/scripts/assembly_video.py`: For final video assembly

## Development

To contribute to this frontend:

1. Create a new branch for your feature or bug fix
2. Make your changes
3. Submit a pull request

## License

This project is licensed under the same terms as the main ForgeTube project.
10 changes: 10 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
flask==2.3.3
google-generativeai==0.3.1
serpapi==0.1.0
pysrt==1.1.2
moviepy==1.0.3
werkzeug==2.3.7
jinja2==3.1.2
itsdangerous==2.1.2
gunicorn==21.2.0
python-dotenv==1.0.0
Loading