Created
June 18, 2026 02:51
-
-
Save eloyesp/1637eaa9960769ebf764a92e90851283 to your computer and use it in GitHub Desktop.
Automatic (safe) video compression (scaling)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| # --- Default Variables --- | |
| AUTO_DELETE=false | |
| DRY_RUN=false | |
| DEBUG=false | |
| LOG_FILE="${HOME}/video-scale.log" | |
| # --- Argument Parsing --- | |
| FILES=() | |
| while [[ "$#" -gt 0 ]]; do | |
| case $1 in | |
| -y) AUTO_DELETE=true ;; | |
| -n) DRY_RUN=true ;; | |
| --debug) DEBUG=true ;; | |
| -*) echo "Warning: Unknown parameter '$1'" ;; | |
| *) FILES+=("$1") ;; | |
| esac | |
| shift | |
| done | |
| # Enable or disable debug mode based on flag | |
| if [[ "$DEBUG" == true ]]; then | |
| set -x | |
| else | |
| set +x | |
| fi | |
| # --- Main Processing Loop --- | |
| PROCESSED_COUNT=0 | |
| for INPUT in "${FILES[@]}"; do | |
| # 1. Skip if already compressed | |
| if [[ "$INPUT" == *".comp."* ]]; then | |
| echo "Warning: Skipping '$INPUT' (already contains '.comp.')." | |
| continue | |
| fi | |
| # 2. Skip if source doesn't exist | |
| if [[ ! -f "$INPUT" ]]; then | |
| echo "Warning: Source file '$INPUT' does not exist." | |
| continue | |
| fi | |
| OUTPUT="${INPUT%.*}.comp.mp4" | |
| # 3. Skip if output already exists | |
| if [[ -f "$OUTPUT" ]]; then | |
| echo "Warning: Output file '$OUTPUT' already exists. Skipping." | |
| continue | |
| fi | |
| CRF="${CRF:-24}" | |
| RES="${RES:-1080}" | |
| # 4. Dry-run mode | |
| if [[ "$DRY_RUN" == true ]]; then | |
| echo "[Dry Run] Would process: '$INPUT' -> '$OUTPUT' (CRF: $CRF, RES: $RES)" | |
| [[ "$AUTO_DELETE" == true ]] && echo "[Dry Run] Would auto-delete original: '$INPUT'" | |
| continue | |
| fi | |
| # 5. Delay 30 seconds between files (skipped for the first processed file) | |
| if [[ "$PROCESSED_COUNT" -gt 0 ]]; then | |
| sleep 30 | |
| fi | |
| # Get initial sizes (wc -c is cross-platform friendly for bytes) | |
| ORIG_SIZE_BYTES=$(wc -c < "$INPUT") | |
| ORIG_SIZE_DISPLAY=$(du -hs "$INPUT" | cut -f1) | |
| # 6. Run ffmpeg and log output | |
| echo "--- Starting ffmpeg for $INPUT at $(date) ---" >> "$LOG_FILE" | |
| ffmpeg -y -i "$INPUT" \ | |
| -vf "scale=w='if(gt(iw\,ih)\,$RES\,-2)':h='if(gt(iw\,ih)\,-2\,$RES)'" \ | |
| -c:v libx264 -preset fast -crf "$CRF" -c:a copy \ | |
| "$OUTPUT" >> "$LOG_FILE" 2>&1 | |
| # Get final sizes | |
| NEW_SIZE_BYTES=$(wc -c < "$OUTPUT") | |
| NEW_SIZE_DISPLAY=$(du -hs "$OUTPUT" | cut -f1) | |
| # Calculate compression percentage (New Size / Old Size * 100) | |
| if [[ -n "$ORIG_SIZE_BYTES" && "$ORIG_SIZE_BYTES" -gt 0 ]]; then | |
| PERCENT=$(awk "BEGIN { printf \"%.0f\", ($NEW_SIZE_BYTES / $ORIG_SIZE_BYTES) * 100 }") | |
| else | |
| PERCENT=0 | |
| fi | |
| # 7. Output summary line | |
| echo "Processed $INPUT -> $OUTPUT | $ORIG_SIZE_DISPLAY -> $NEW_SIZE_DISPLAY | ${PERCENT}%" | |
| # 8. Deletion logic | |
| if [[ "$AUTO_DELETE" == true ]]; then | |
| trash "$INPUT" | |
| else | |
| read -rp "Borro el archivo original $INPUT? [y/N] " yn | |
| # Note: Your original regex `^([Yy]|)$` makes pressing Enter (empty) default to Yes. | |
| [[ $yn =~ ^([Yy]|)$ ]] && trash "$INPUT" | |
| fi | |
| PROCESSED_COUNT=$((PROCESSED_COUNT + 1)) | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment