Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Deploy Architecture Page

on:
push:
branches:
- main
paths:
- index.html
- .github/workflows/deploy.yml
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: true

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Pages
uses: actions/configure-pages@v5

- name: Prepare site artifact
shell: bash
run: |
mkdir -p _site
cp index.html _site/index.html

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: _site

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ jobs:
run: pip install pyinstaller

- name: Build Executables
env:
BUILD_VERSION: ${{ github.ref_name }}
run: python build.py

# --- Upload Section ---
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Discord has too small file size limit for free. And, any online video compressor
A normal user isn't curious about these configuration and just want a _targeted file size_ video compression with minimal quality loss.

So, here's a simple drag and drop usage (In Windows) easy solution.
> [!TIP]
> Visit [this page](https://simpnick6703.github.io/Video-Compression) for Architectural overview and more.

## Requirements
For running the script locally (your own build):
Expand All @@ -23,7 +25,9 @@ For using prebuilt binaries from releases, you just need to download the executa
- Download any of the target filesize build from [releases](<https://github.com/SimpNick6703/Video-Compression/releases>).
- Drag and drop your video on the executable. (Or run in Command Prompt/Terminal as `./{size}mb-win64 <input.mp4> [output.mp4]`)

https://github.com/user-attachments/assets/0272427b-0db4-40dd-bd14-37d705d110a0

https://github.com/user-attachments/assets/2f9c79d7-ce15-41a5-8895-a89b549afa3e


- In Linux:
- Download your desired build from [releases](<https://github.com/SimpNick6703/Video-Compression/releases>).
Expand All @@ -45,7 +49,7 @@ python build.py

This will:
1. Automatically download FFmpeg/FFprobe for your platform (if not already present)
2. Generate all preset executables (8mb, 50mb, 100mb, 500mb) in `dist/`
2. Generate all preset executables (10mb, 50mb, 100mb, 500mb) in `dist/`
3. Clean up build artifacts and downloaded binaries

To keep build artifacts for debugging:
Expand All @@ -65,4 +69,4 @@ Considering the wide variety of hardware configurations, the script uses the fol

> [!NOTE]
> Only NVENC supports Two-Pass encoding among the listed encoders. Other encoders use Single-Pass encoding only.
> If your dedicated GPU is being bypassed in favor of integrated GPU or CPU encoding, you'll need to manually change the priority logic in the script to suit your hardware setup. Or, you may simply remove unwanted encoders from the priority list in the script, build the executable again, and use that custom build.
> If your dedicated GPU is being bypassed in favor of integrated GPU or CPU encoding, you'll need to manually change the priority logic in the script to suit your hardware setup. Or, you may simply remove unwanted encoders from the priority list in the script, build the executable again, and use that custom build.
37 changes: 27 additions & 10 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
Build script for Video-Compression executables.

Generates preset executables (8mb, 50mb, 100mb, 500mb) from videocompress.py
Generates preset executables (10mb, 50mb, 100mb, 500mb) from videocompress.py
by creating temporary copies with hardcoded target sizes, then compiling with PyInstaller.

Usage:
Expand All @@ -23,7 +23,8 @@
from pathlib import Path

# --- Configuration ---
PRESET_SIZES = [8, 50, 100, 500]
PRESET_SIZES = [10, 50, 100, 500]
PRESET_CODECS = ["hevc", "h264"]
SOURCE_SCRIPT = "videocompress.py"
FFMPEG_BINARIES = ["ffmpeg", "ffprobe"]
OUTPUT_DIR = "dist"
Expand Down Expand Up @@ -171,7 +172,7 @@ def check_ffmpeg_available() -> bool:
return True


def create_preset_script(target_mb: int, temp_dir: str) -> str:
def create_preset_script(target_mb: int, codec: str, temp_dir: str) -> str:
"""Create a temporary script with hardcoded target size."""
with open(SOURCE_SCRIPT, "r", encoding="utf-8") as f:
content = f.read()
Expand All @@ -183,24 +184,39 @@ def create_preset_script(target_mb: int, temp_dir: str) -> str:
content
)

# Replace the default codec value
content = re.sub(
r'CODEC_TYPE\s*=\s*"hevc"',
f'CODEC_TYPE = "{codec}"',
content
)
Comment on lines +188 to +192
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regular expression used to replace the CODEC_TYPE is a bit fragile as it specifically looks for "hevc". If the default value in videocompress.py changes in the future, this replacement will fail silently. It would be more robust to match any string inside the quotes.

Suggested change
content = re.sub(
r'CODEC_TYPE\s*=\s*"hevc"',
f'CODEC_TYPE = "{codec}"',
content
)
content = re.sub(
r'CODEC_TYPE\s*=\s*".*?"',
f'CODEC_TYPE = "{codec}"',
content
)


# Update the usage message to reflect the preset
content = re.sub(
r'print\("Usage: python script\.py <input> \[output\] \[size_mb\]"\)',
f'print("Usage: {target_mb}mb <input> [output]")',
f'print("Usage: {target_mb}mb-{codec} <input> [output] [size_mb]")',
content
)

script_path = os.path.join(temp_dir, f"{target_mb}mb.py")
script_path = os.path.join(temp_dir, f"{target_mb}mb_{codec}.py")
with open(script_path, "w", encoding="utf-8") as f:
f.write(content)

return script_path


def build_executable(script_path: str, target_mb: int) -> bool:
def build_executable(script_path: str, target_mb: int, codec: str) -> bool:
"""Build a single executable using PyInstaller."""
platform_suffix = get_platform_suffix()
output_name = f"{target_mb}mb-{platform_suffix}"

version = os.environ.get("BUILD_VERSION")
if version:
# Sanitize version for filename (allow alphanumeric, dot, hyphen, underscore)
# Using standard versioning (e.g. v1.1.0) is safer than stripping dots (110) to avoid ambiguity.
safe_version = re.sub(r'[^\w\-\.]', '', version)
output_name = f"{target_mb}mb-{codec}-{platform_suffix}-{safe_version}"
else:
output_name = f"{target_mb}mb-{codec}-{platform_suffix}"

log.info("Building %s...", output_name)

Expand Down Expand Up @@ -287,8 +303,9 @@ def main() -> int:

with tempfile.TemporaryDirectory(prefix="vidcomp_build_") as temp_dir:
for size in PRESET_SIZES:
script_path = create_preset_script(size, temp_dir)
results[size] = build_executable(script_path, size)
for codec in PRESET_CODECS:
script_path = create_preset_script(size, codec, temp_dir)
results[f"{size}mb-{codec}"] = build_executable(script_path, size, codec)

# Clean build artifacts by default (unless --verbose)
if not verbose:
Expand All @@ -302,7 +319,7 @@ def main() -> int:

for size, success in results.items():
status = "Success" if success else "Failed"
log.info(" %dMB: %s", size, status)
log.info(" %s: %s", size, status)

failed = [s for s, ok in results.items() if not ok]
if failed:
Expand Down
Loading