Skip to content

Repository files navigation

Parallel Video Transcoder

An HPC-inspired parallel video processing pipeline designed to eliminate hardware playback constraints on legacy smart TVs. This repository automates codec detection, structural filtering, process-level isolation, and core-bounded hardware acceleration to convert modern, high-efficiency AV1 video streams down to universally compatible H.264 main profiles.


The Origin: Digitizing Media for Dad's Legacy TV

This project originated from a real-world hardware incompatibility issue. My dad wanted to digitize his older video collection and convert downloaded and CD files onto a FAT32 USB drive to watch on his living room TV. However, modern video downloaders frequently compress files using the newer AV1 codec.

When plugged into my dad's legacy non-Android smart TV, every video threw a frustrating "Unsupported Format" error.

Legacy television architectures rely on fixed-function Application-Specific Integrated Circuits (ASICs) designed long before AV1 hardware decoding existed. Unable to parse the AV1 bitstream, the TV rejected the files. To fix this without spending hours manually converting media files one by one, I built this parallel transcoding pipeline transforming a restrictive hardware bottleneck into an optimized multi-core media processing showcase.


Repository Architecture

parallel-video-transcoder/
├── .github/
│   └── workflows/
│       ├── ci.yml               # Automated Pytest & test coverage pipeline
│       └── docker-publish.yml   # Multi-platform Docker build & Docker Hub publish
├── converter/
│   ├── __init__.py
│   ├── detector.py              # ffprobe wrappers & metadata inspection
│   ├── transcode.py             # FFmpeg execution engine & error handling
│   └── parallel_convert.py      # CLI entry point for parallel execution
├── docs/
│   ├── ARCHITECTURE.md          # Deep dive system design & sequence flow
│   └── CONTRIBUTORS.md          # Contribution guidelines & team metadata
├── tests/
│   ├── test_detector.py         # Pytest suite for metadata parsing
│   └── test_transcode.py        # Pytest suite for transcode logic
├── utils/
│   ├── benchmark.py             # Performance evaluation suite
│   └── check_codec.py           # Fast drive inspector wrapper
├── Dockerfile                   # Container specification bundling FFmpeg & Python
├── docker-compose.yml           # Local volume mapping & container runtime orchestration
├── requirements.txt             # Dependency definitions
├── run.sh                       # POSIX shell entry point
├── SETUP.md                     # Manual system installation guide
└── README.md                    # Core system documentation


Systems Engineering & Performance Architecture

Transcoding high-bitrate media across multiple video files can easily overwhelm low-core CPUs or virtualized development environments (like WSL). This project solves hardware starvation through four core design decisions:

1. Process Isolation vs. Thread Thrashing

Standard single-instance FFmpeg commands attempt to spawn internal thread pools to saturate all detected CPU cores. Running multiple naive jobs concurrently causes severe Context Switching forcing the CPU to constantly flush L1/L2 caches to swap state.

This pipeline fixes thread thrashing by leveraging Python's ProcessPoolExecutor to spawn bounded worker processes corresponding to physical core counts, while explicitly locking each individual FFmpeg sub-process using the -threads 1 flag. This guarantees core-level isolation and predictable throughput.

2. Bypassing Memory & Storage Bottlenecks

Writing transcode artifacts directly onto legacy storage media (e.g., USB 2.0/3.0 flash drives formatted in FAT32) introduces high I/O Wait (iowait) states, causing the CPU to sit idle waiting for write confirmations. The benchmarking suite routes volatile test conversions through /tmp (tmpfs), performing operations in system RAM to isolate CPU performance from storage write bottlenecks.

3. Early-Exit Stream Metadata Filtering

Before triggering expensive encoding operations, utils/check_codec.py executes lightweight inspection using ffprobe. It extracts structural header metadata directly from the container stream. Non-AV1 assets (or already compatible H.264 streams) trigger an immediate early exit, avoiding wasted processing cycles.

4. Zero-Copy Audio Stream Copying

Re-encoding audio requires decoding compressed bitstreams into raw PCM waveforms, calculating Fast Fourier Transforms (FFT), and re-compressing them. By specifying -c:a copy for standard audio tracks, raw audio packets are transferred byte-for-byte directly into the destination MP4 container without uncompression overhead.


Containerization & CI/CD Pipeline

The project is packaged as a standalone Docker image and automatically published via GitHub Actions.

1. Running with Docker Compose (Recommended)

Mount your local video input and output folders without installing ffmpeg or python on the host machine:

# Pull and start the container via Docker Compose
docker compose up

2. Running directly via Docker Hub Image

# Pull the latest published image
docker pull geonjunge/parallel-video-transcoder:latest

# Execute conversion on mounted media volumes
docker run --rm \
  -v /path/to/your/input:/app/media_input \
  -v /path/to/your/output:/app/media_output \
  geonjunge/parallel-video-transcoder:latest

Local Setup & Native Execution

Prerequisites

If running natively without Docker, ensure ffmpeg and ffprobe binaries are available in your system path.

  • Linux / Debian / WSL:
sudo apt update && sudo apt install ffmpeg -y
  • macOS:
brew install ffmpeg

Installation

  1. Clone the repository:
git clone https://github.com/GeoNjunge/parallel-video-transcoder.git
cd parallel-video-transcoder
  1. Initialize Python virtual environment:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
  1. Set execution permissions:
chmod +x run.sh

Native Usage Instructions

Use the POSIX wrapper script (run.sh) to execute conversion or evaluation workloads:

# Run production parallel transcoding on a specific directory/USB path
./run.sh convert /path/to/media/folder

# Run microarchitectural benchmarking suite against an AV1 sample
./run.sh benchmark /path/to/media/folder

Alternatively, invoke Python directly with custom worker counts:

python3 converter/parallel_convert.py /path/to/media/folder --workers 4

Benchmark & Performance Summary

Evaluated on a sample 480p AV1 media batch (05 - The World Is A Cycle by Richie Spice.mp4) comparing single-threaded sequential execution against the core-bounded parallel pipeline:

Metric Sequential Baseline (1 Worker) Bounded Parallel Pipeline (2 Workers)
Wall-Clock Duration 30.31s 21.07s
Transcoding Throughput 463.2 FPS 666.5 FPS
Speedup Factor 1.0x (Baseline) 1.44x Faster

Parallel scaling yields a 71.9% hardware utilization efficiency (+203.3 FPS throughput delta) on a 2-core execution environment, accounting for process orchestration and shared memory bandwidth limits.

About

An HPC-inspired parallel video processing pipeline built to bypass legacy hardware limitations for my dad's old TV

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages