77 lines
2.5 KiB
Bash
Executable File
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}'
|
|
|