Files
at2-workstation-scripts/ffmpeg_video_compress.sh
2025-04-12 09:56:11 +02:00

77 lines
2.5 KiB
Bash
Executable File

#!/bin/zsh
# Script Version: 14
# Description: Compress a video using ffmpeg with NVIDIA CUDA for acceleration, aiming for a smaller file size. Push GPU usage and CPU multicore hyperthreading to maximize performance by parallel processing.
# Set variables
# ========
INPUT_VIDEO="$1"
OUTPUT_VIDEO="${INPUT_VIDEO%.*}_compressed.mkv" # Output filename based on input with '_compressed' suffix and .mkv extension
TEMP_DIR="/tmp/ffmpeg_chunks"
CHUNK_DURATION=30 # Split video into 30-second chunks for parallel processing
NUM_CHUNKS=4 # Limit to 4 chunks
# Main Process
# ========
if [[ -z "$INPUT_VIDEO" ]]; then
echo "Usage: $0 <input_video>"
exit 1
fi
# Check if GNU Parallel is installed
if ! command -v parallel &> /dev/null; then
echo "GNU Parallel is required but not installed. Please install it with: apt-get install parallel"
exit 1
fi
# Create a temporary directory for storing chunks
mkdir -p "$TEMP_DIR"
# Split the input video into smaller chunks, ensuring proper timestamps and avoiding timestamp issues
ffmpeg -fflags +genpts -copyts -i "$INPUT_VIDEO" -c copy -map 0 -segment_time "$CHUNK_DURATION" -reset_timestamps 1 -f segment "$TEMP_DIR/chunk_%03d.mkv"
# Verify if splitting succeeded
if [[ $? -ne 0 ]]; then
echo "Error: Failed to split the video into chunks."
rm -rf "$TEMP_DIR"
exit 1
fi
# Limit the number of chunks to 4
CHUNKS=$(ls "$TEMP_DIR"/chunk_*.mkv | head -n "$NUM_CHUNKS")
# Compress each chunk in parallel using GNU Parallel
echo "$CHUNKS" | parallel -j "$NUM_CHUNKS" ffmpeg -hwaccel cuda -i {} -c:v hevc_nvenc -preset p1 -rc constqp -qp 20 -b:v 5M -maxrate 10M -bufsize 20M -c:a copy {.}_compressed.mkv
# Verify if compression succeeded
if [[ $? -ne 0 ]]; then
echo "Error: Compression failed for one or more chunks."
rm -rf "$TEMP_DIR"
exit 1
fi
# Concatenate the compressed chunks into the final output file
ls "$TEMP_DIR"/*_compressed.mkv | sort | xargs -I {} echo "file '{}'" > "$TEMP_DIR/file_list.txt"
ffmpeg -f concat -safe 0 -i "$TEMP_DIR/file_list.txt" -c copy "$OUTPUT_VIDEO"
# Verify if concatenation succeeded
if [[ $? -ne 0 ]]; then
echo "Error: Failed to concatenate the compressed chunks."
rm -rf "$TEMP_DIR"
exit 1
fi
# Clean up temporary files
rm -rf "$TEMP_DIR"
# Output status
if [[ -f "$OUTPUT_VIDEO" ]]; then
echo "Compression complete. Output file: $OUTPUT_VIDEO"
else
echo "Compression failed. Output file was not created."
exit 1
fi
# Display file sizes
ls -lh "$INPUT_VIDEO" "$OUTPUT_VIDEO" | awk '{print $9, $5}'