#!/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 " 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}'