Browser‑Based Video Editor Mini‑Clone

A lightweight Python/Flask prototype inspired by video‑use

Welcome to another official UVU IT build guide. In the next 45 minutes you’ll spin up a tiny web app that lets you upload raw footage, trigger a simple ffmpeg trim, and download the edited result – a stripped‑down echo of the video‑use project.

We’ll use Python 3, Flask, SQLite (for a tiny metadata store), and free‑tier ffmpeg binaries. No paid APIs, no AI – just the core upload‑process‑download loop you can extend later.

Before you start

Minimal Video‑Edit Architecture
LOCAL STACK store metadata process video Flask Web Server SQLite DB ffmpeg CLI
1

Phase 1: Scaffold the project

First we create an isolated Python environment so our dependencies don’t clash with any global packages. Then we install Flask, the lightweight web framework that will serve our upload page and API endpoints. Finally we lay out a simple folder structure that keeps code, templates, and static assets tidy.

The scaffold gives us a predictable entry point (run.py) and a place (app/) for all future modules. Keeping everything inside the virtual environment also makes the later ffmpeg calls reproducible on any machine that meets the prerequisites.

python3 -m venv venv
source venv/bin/activate
pip install Flask
mkdir -p app/templates app/static app/models
touch run.py app/__init__.py
2

Phase 2: Define the data model

We need a minimal way to remember which files a user has uploaded and where the trimmed output lives. SQLite is perfect for this because it requires no separate server and stores a single file on disk.

The models.py module creates a videos table with columns for the original filename, the path to the stored upload, and the path to the processed clip. Flask can later import this module to query or insert records as part of the upload workflow.

app/models.py

import sqlite3
import os

DB_PATH = os.path.join(os.path.dirname(__file__), '..', 'videos.db')

def get_connection():
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn

def init_db():
    with get_connection() as conn:
        conn.execute('''
            CREATE TABLE IF NOT EXISTS videos (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                original_name TEXT NOT NULL,
                upload_path TEXT NOT NULL,
                output_path TEXT
            )
        ''')
        conn.commit()

# Initialize the DB when this module is imported
init_db()
3

Phase 3: Build the Flask API & UI

In this step we create a tiny Flask server that serves a single HTML page and handles file uploads. When a user posts a video, the server runs an ffmpeg command to cut the first 10 seconds and stores the result in a temporary folder. The trimmed file is then sent back to the browser as a downloadable attachment. Keeping everything in one file makes the prototype easy to read and extend.

app/main.py

import os
from flask import Flask, request, send_from_directory, render_template, redirect, url_for
import subprocess

app = Flask(__name__)
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'uploads')
TRIMMED_FOLDER = os.path.join(BASE_DIR, 'trimmed')
for folder in (UPLOAD_FOLDER, TRIMMED_FOLDER):
    os.makedirs(folder, exist_ok=True)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/trim', methods=['POST'])
def trim():
    file = request.files.get('video')
    if not file:
        return redirect(url_for('index'))
    src_path = os.path.join(UPLOAD_FOLDER, file.filename)
    file.save(src_path)
    dst_path = os.path.join(TRIMMED_FOLDER, f'trimmed_{file.filename}')
    # ffmpeg: -t 10 limits output to first 10 seconds
    subprocess.run(['ffmpeg', '-y', '-i', src_path, '-t', '10', dst_path],
                   stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    return send_from_directory(TRIMMED_FOLDER, os.path.basename(dst_path), as_attachment=True)

if __name__ == '__main__':
    app.run(debug=True)
4

Phase 4: Minimal HTML UI

The UI is just a plain HTML form that posts the selected video to the /trim endpoint. We use enctype="multipart/form-data" so the file is correctly transmitted. After the server processes the video it returns the trimmed file, prompting the browser to download it automatically.

app/templates/index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Video Trim Demo</title>
</head>
<body>
  <h1>Upload a video to get a 10‑second preview</h1>
  <form action="/trim" method="post" enctype="multipart/form-data">
    <input type="file" name="video" accept="video/*" required>
    <button type="submit">Trim &amp; Download</button>
  </form>
</body>
</html>
5

Phase 5: Run and verify

Now start the Flask development server and point your browser at the root URL. Choose any short MP4 file, hit the button, and the browser will download a new file prefixed with trimmed_. Open that file in any media player – it should be roughly 10 seconds long. This confirms the end‑to‑end flow works.

# Ensure you are in the project root where the app folder lives
python -m pip install flask
# ffmpeg must be installed on your system (apt, brew, choco, etc.)
python app/main.py

Verifying the Stack

CheckCommand / Why it matters
Server starts without errorpython app/main.py → should show *Running on http://127.0.0.1:5000/*
Upload page loads in browserOpen http://127.0.0.1:5000/ → see upload form
Trimmed video downloads and plays ~10 sUpload any mp4, click download, verify duration with any media player

What’s next?

You now have a functional upload‑trim service. Extend it by adding subtitle overlay (ffmpeg drawtext), storing metadata in SQLite, or wiring an LLM to decide cut points – the same patterns the full video‑use project uses.