Advertisement
MaxDjently

Ziggle Wump Media Compressor 0.2-beta.09.06.2024

Sep 5th, 2024
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 17.43 KB | Source Code | 0 0
  1. #!/data/data/com.termux/files/usr/bin/bash
  2.  
  3. # ATTENTION:
  4.  
  5. # Copying and pasting the script can introduce formatting that is improper to bash.  If the script doesn't run, you may need to use the dos2unix command to fix it.
  6.  
  7. # ex.  dos2unix ziggle_wump.sh
  8.  
  9. # --------------------
  10. #     Licence
  11. # --------------------
  12.  
  13. # This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  14.  
  15. # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  16.  
  17. # You should have received a copy of the GNU General Public License along with  this program. If not, see <https://www.gnu.org/licenses/>.
  18.  
  19. # -----------------
  20. #     About
  21. # -----------------
  22.  
  23. # This script is for Termux on Android and is not associated with the apps it uses.
  24.  
  25. # Copyright Joshua Hansen and contributors: Microsoft Co-Pilot and ChatGPT.
  26.  
  27. # Shout out to Webernets https://youtu.be/0aeCfDKLfbs?si=58y58eWSiXurcHpj who gave me the inspiration for this, the one who did the heavy lifting figuring out the command line options. And this video helping me figure out how to do it in Handbrake, but I needed it all in a one-line command line option and this was it, I had to write it myself.
  28.  
  29. # -----------------------
  30. #   Instructions
  31. # -----------------------
  32.  
  33. # Usage: ./ziggle_wump.sh [-r resolution] [-f "ffmpeg_options"] [-h|--help]
  34. #   -r resolution        Custom resolution height preserving aspect ratio, Downscaling your videos will significantly reduce the file size, but may introduce artifacts and shimmering.  Upscaling will produce larger file sizes and not increase quality.
  35. #   -f "ffmpeg_options" Override default FFmpeg options with custom command line options.  ex. bash ./ziggle_wump.sh -f "-c:v libx264 -c:a libmp3lame"
  36. #   -h, --help           Display this help message
  37.  
  38. # 1. Download or Copy this script to a file, and rename it if you want.  e.g., ziggle_wump.sh.  Putting it in your Movies folder will make it easy to find on both Android and Termux, although it's possible to put this in your /usr/bin to use it as a system app.  Your mileage may vary.
  39. # 2. Make it executable: chmod +x ziggle_wump.sh
  40. # 3. Run the script: bash ./ziggle_wump.sh [options]
  41.  
  42. # -------------------
  43. #    README
  44. # -------------------
  45.  
  46. # Ziggle Wump: The Simple FFmpeg Command Line Companion Script for Termux on Android
  47.  
  48. # DISCLAIMER:  THE SCRIPT DOES NOT ALLOW YOU TO CONVERT ENCRYPTED FILES, COPYRIGHTED CONTENT IS GENERALLY ENCRYPTED. THE SCRIPT IN ITSELF DOES NOT VIOLATE COPYRIGHT BUT THE USER MIGHT.  CODE TO PREVENT CIRCUMVENTION IS BEYOND MY CAPABILITY.  NOR SHOULD IT BE MY RESPONSIBILITY, IT'S THE COPYRIGHT HOLDERS RESPONSIBILITY TO ENCRYPT THEIR MEDIA.  IT IS NOT RECOMMENDED TO USE THE SCRIPT TO VIOLATE COPYRIGHT LAW.  US COPYRIGHT LAW ALLOWS FOR SPACESHIFTING, AND FAIR USE OF COPYRIGHTED MATERIAL
  49.  
  50. # NOTE:  Some phones have a battery saving feature such as the Galaxy S24, that can impact the encoding process and leave you with partially encoded files.  Please make sure Termux is in focus otherwise, either full screen or split screen if you want to do other things, and keep the screen on while encoding.
  51.  
  52. # Check out https://dontkillmyapp.com/ for more information and perhaps find a fix for your particular phone.
  53.  
  54. # Supported File Types:
  55. # Video:  mp4 mkv avi mov flv wmv webm mts
  56. # Audio: mp3 wav flac aac ogg m4a
  57.  
  58. # -----------------------------
  59. #             Title
  60. # -----------------------------
  61.  
  62. # Ziggle Wump Media Compressor 0.2-beta
  63.  
  64. # The Simple FFmpeg Command Line Companion Script for Termux on Android
  65.  
  66. # -----------------------------
  67. #        Variables
  68. # -----------------------------
  69.  
  70. # Full Log file path
  71. log_file="$HOME/storage/shared/Movies/VideoDrop/convert.log"
  72.  
  73. # Shortened log file path for terminal output
  74. log_file_echo=$(echo "$log_file" | sed 's|/data/data/com.termux/files/home|.../home|g')
  75.  
  76. # Default resolution (empty implies original resolution)
  77. default_resolution=""
  78.  
  79. # Full directory paths
  80. video_drop_dir="$HOME/storage/shared/Movies/VideoDrop"
  81. video_processing_dir="$HOME/storage/shared/Movies/VideoProcessing"
  82. output_dir_base="$HOME/storage/shared/Movies/VideoConverted"
  83.  
  84. # Shortened directory paths for terminal output
  85. video_drop_dir_echo=$(echo "$video_drop_dir" | sed 's|/data/data/com.termux/files/home|.../home|g')
  86. video_processing_dir_echo=$(echo "$video_processing_dir" | sed 's|/data/data/com.termux/files/home|.../home|g')
  87. output_dir_base_echo=$(echo "$output_dir_base" | sed 's|/data/data/com.termux/files/home|.../home|g')
  88.  
  89. # Initialize optional variables
  90. resolution="$default_resolution"
  91. ffmpeg_custom_options=""
  92.  
  93. # -----------------------------
  94. #    Command Flags
  95. # -----------------------------
  96.  
  97. # Function to display help message
  98. show_help() {
  99.     width=$(tput cols)
  100.     echo "Place your media files in $video_drop_dir_echo." | tee -a "$log_file" | fmt -w $width
  101.     echo "Usage: $0 [-r resolution] [-f \"ffmpeg_options\"] [-h|--help]" | fmt -w $width
  102.     echo "  -r resolution ex. bash $0 -r 720               Custom resolution height preserving aspect ratio, Downscaling your videos will significantly reduce the file size, but may introduce artifacts and shimmering.  Upscaling will produce larger file sizes and not increase quality." | fmt -w $width
  103.     echo "  -f \"ffmpeg_options\"  Override default FFmpeg options with custom command line options.  ex. bash $0 -f \""-c:v libx264 -c:a libmp3lame\" | fmt -w $width
  104.     echo "  -h, --help           Display this help message" | fmt -w $width
  105.     exit 0
  106. }
  107.  
  108. # Parse command-line options
  109. while getopts "r:f:h" opt; do
  110.     case $opt in
  111.         r) resolution="$OPTARG" ;;  # Set custom resolution by height
  112.         f) ffmpeg_custom_options="$OPTARG" ;;  # Set custom FFmpeg options
  113.         h) show_help ;;  # Display help
  114.         *) show_help ;;  # Display help for invalid options
  115.     esac
  116. done
  117.  
  118. shift $((OPTIND -1))
  119.  
  120. # ---------------------------------
  121. #       Dependencies
  122. # ---------------------------------
  123.  
  124. # Ensure dependencies are installed and all packages are up to date.
  125.     echo "Updating, please wait..."
  126.     sleep 1
  127.     pkg update && pkg upgrade -y
  128.     if ! command -v bc &> /dev/null; then
  129.         pkg install bc -y
  130.     fi
  131.     if ! command -v ffmpeg &> /dev/null; then
  132.         pkg install ffmpeg -y
  133.     fi
  134.     if ! command -v ncurses-utils &> /dev/null; then
  135.         pkg install ncurses-utils -y
  136.     fi
  137. echo "Update complete."
  138.     sleep 1
  139.  
  140. # -----------------------------------------------------
  141. #     Create Directories and log file
  142. # -----------------------------------------------------
  143.  
  144. # Create necessary directories if they don't exist
  145. mkdir -p "$video_drop_dir" "$video_processing_dir" "$output_dir_base"
  146.  
  147. # Change to the VideoDrop directory
  148. cd "$video_drop_dir" || { echo "Directory change failed"; exit 1; }
  149.  
  150. # Check if log file exists
  151. if [ -f "$log_file" ]; then
  152.     echo "Old log file found.  Deleting..."
  153.     rm "$log_file"
  154.     echo "File deleted."
  155. else
  156.     echo "Log File does not exist.  The script will create $log_file_echo"
  157. fi
  158.  
  159. # ------------------------
  160. #     Start script
  161. # ------------------------
  162.  
  163. width=$(tput cols)
  164.  
  165. echo "Running... Press Ctrl+C to stop."
  166.     sleep 1
  167.  
  168. echo ""
  169. echo "NOTE:  Some phones have a battery saving feature such as the Galaxy S24, that can impact the encoding process and leave you with partially encoded files.  Please make sure Termux is in  focus, either full screen or split screen if you want to do other things, and keep the screen on while encoding." | tee -a "$log_file" | fmt -w $width
  170.  
  171. echo ""
  172. echo "Check out https://dontkillmyapp.com/ for more information and perhaps find a fix for your particular phone." | tee -a "$log_file" | fmt -w $width
  173.  
  174. echo ""
  175. # Function to prompt the user to continue or quit
  176. prompt_continue_or_quit() {
  177.     while true; do
  178. # Recursively find and process videos and audio
  179. video_count=$(find "$video_drop_dir" -type f \( -iname '*.mp3' -o -iname '*.wav' -o -iname '*.flac' -o -iname '*.aac' -o -iname '*.ogg' -o -iname '*.m4a' -o -iname '*.mp4' -o -iname '*.mkv' -o -iname '*.avi' -o -iname '*.mov' -o -iname '*.flv' -o -iname '*.wmv' -o -iname '*.webm' -o -iname '*.mts' \) | wc -l)
  180.  
  181. if [ "$video_count" -eq 0 ]; then
  182.     echo "No videos or audio found. $video_drop_dir_echo folder created. Place your videos and audio here including in folders using your favorite file manager for Android, and then run the script again.  Supported File Types:  Video:  mp4 mkv avi mov flv wmv webm mts Audio: mp3 wav flac aac ogg m4a" | tee -a "$log_file" | fmt -w $width
  183.     exit 0
  184. fi
  185.  
  186. # Prompt text
  187. prompt_text="Compatible media files detected in $video_drop_dir_echo. You can start encoding now. Do you wish to proceed? (Y/N): "
  188.  
  189. # Format the prompt text
  190. formatted_prompt=$(echo "$prompt_text" | fmt -w $width)
  191.  
  192. # Read user input with formatted prompt
  193. read -p "$formatted_prompt" yn
  194. case $yn in
  195.     [Yy]* ) return 0;;  # Continue
  196.     [Nn]* ) echo "Exiting script."; exit 0;;  # Quit
  197.     * ) echo "Please answer Y or N.";;
  198. esac
  199. done
  200. }
  201.  
  202.     # Prompt the user to continue or quit
  203.     prompt_continue_or_quit
  204.  
  205. echo "Starting conversion process..." | tee -a "$log_file"
  206. sleep 1
  207.  
  208. # -----------------------------
  209. #    Audio Encoder
  210. # -----------------------------
  211.  
  212. width=$(tput cols)
  213.  
  214. # Function to check the log file for "Killed" message
  215. check_for_killed_message() {
  216.     if grep -q " Killed     " "$log_file"; then
  217.         echo "$(date '+%Y-%m-%d %H:%M:%S') Error: Process was killed. Check log file for details." | tee -a "$log_file"
  218.         return 1
  219.     fi
  220.     return 0
  221. }
  222.  
  223. # Function to process audio files
  224. process_audio() {
  225.     local audio="$1"
  226.     local audio_echo=$(echo "$audio" | sed 's|/data/data/com.termux/files/home|/home|g')
  227.     local relative_path="${audio#$video_drop_dir/}"
  228.     local dir_path=$(dirname "$relative_path")
  229.     local base_name=$(basename "$relative_path" | tr -cd '[:alnum:]._ -')
  230.     local output_dir="$output_dir_base/$dir_path"
  231.     local output_file="$output_dir/${base_name}_converted.opus"
  232.     local temp_output_file="$output_file.tmp"
  233.  
  234.     mkdir -p "$output_dir"  # Create output directory
  235.  
  236.     echo "$(date '+%Y-%m-%d %H:%M:%S') Processing $audio to $output_file" | tee -a "$log_file"
  237.  
  238.     # Construct the FFmpeg command for audio processing
  239.     local ffmpeg_command="ffmpeg -nostdin -loglevel verbose -y -i \"$audio\" -c:a libopus -f opus \"$temp_output_file\""
  240.  
  241.     # Execute the FFmpeg command
  242.     eval $ffmpeg_command 2>&1 | tee -a "$log_file"
  243.  
  244.     # Check for "Killed" message in the log file
  245.     if ! check_for_killed_message; then
  246.         echo "$(date '+%Y-%m-%d %H:%M:%S') Error: Process was killed. Exiting." | tee -a "$log_file"
  247.         exit 1
  248.     fi
  249.  
  250.     if [ $? -eq 0 ]; then
  251.         mv "$temp_output_file" "$output_file"  # Rename the temporary file to the final output file
  252.         mkdir -p "$video_processing_dir/$dir_path"  # Create processing directory
  253.         mv "$audio" "$video_processing_dir/$relative_path"
  254.         echo ""
  255.         echo "$(date '+%Y-%m-%d %H:%M:%S') Converted $audio_echo. Your original files will be in the $video_processing_dir_echo folder for comparison. Your new files are in $output_dir_base_echo" | tee -a "$log_file" | fmt -w $width
  256.     else
  257.         echo ""
  258.         echo "$(date '+%Y-%m-%d %H:%M:%S') Error processing \"$audio\". Check log file for details." | tee -a "$log_file"
  259.         exit 1
  260.     fi
  261. }
  262.  
  263. # ------------------------------
  264. #      Video Encoder
  265. # ------------------------------
  266.  
  267. width=$(tput cols)
  268.  
  269. # Function to check the log file for "Killed" message
  270. check_for_killed_message() {
  271.     if grep -q " Killed     " "$log_file"; then
  272.         echo "$(date '+%Y-%m-%d %H:%M:%S') Error: Process was killed. Check log file for details." | tee -a "$log_file" | fmt -w $width
  273.         exit 1
  274.     fi
  275. }
  276.  
  277. # Function to process videos
  278. process_video() {
  279.     local video="$1"
  280.     local video_echo=$(echo "$video" | sed 's|/data/data/com.termux/files/home|.../home|g')
  281.     local relative_path="${video#$video_drop_dir/}"
  282.     local dir_path=$(dirname "$relative_path")
  283.     local base_name=$(basename "$relative_path" | tr -cd '[:alnum:]._ -')
  284.     local output_dir="$output_dir_base/$dir_path"
  285.     local output_file="$output_dir/${base_name}_converted.mkv"
  286.     local temp_output_file="$output_file.tmp"
  287.     local scale_filter=""
  288.    
  289.     if [ -n "$resolution" ]; then
  290.         scale_filter="scale=-2:$resolution,"
  291.         echo "Resolution set to: $resolution" | tee -a "$log_file"
  292.     else
  293.         echo "Resolution set to: original" | tee -a "$log_file"
  294.     fi
  295.  
  296.     mkdir -p "$output_dir"  # Create output directory
  297.  
  298.     echo "$(date '+%Y-%m-%d %H:%M:%S') Processing $video to $output_file" | tee -a "$log_file"
  299.  
  300.     # Construct the FFmpeg command
  301.     local ffmpeg_command
  302.     if [ -n "$ffmpeg_custom_options" ]; then
  303.         ffmpeg_command="ffmpeg -nostdin -loglevel verbose -y -i \"$video\" $ffmpeg_custom_options -f matroska \"$temp_output_file\""
  304.     else
  305.         # Get the frame rate of the input video
  306.         input_fps=$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=noprint_wrappers=1:nokey=1 "$video" | bc)
  307.  
  308.         # Set the frame rate to 23 if the input frame rate is higher, otherwise use the original frame rate
  309.         if (( $(echo "$input_fps > 23" | bc -l) )); then
  310.             video_filter_option="-vf \"${scale_filter}yadif=2,fps=23\""
  311.         else
  312.             video_filter_option="-vf \"${scale_filter}yadif=2\""
  313.         fi
  314.  
  315.         # FFmpeg command with conditional frame rate option
  316.         ffmpeg_command="ffmpeg -nostdin -loglevel verbose -y -i \"$video\" $video_filter_option -c:v libx265 -x265-params \"keyint=250:aq-mode=1:psy-rd=0.75:psy-rdoq=4.0:rd=4:rdoq-level=1:rect=0:strong-intra-smoothing=0\" -c:a libopus -ac 2 -f matroska \"$temp_output_file\""
  317.     fi
  318.  
  319.     echo "FFmpeg command: $ffmpeg_command" | tee -a "$log_file"
  320.     sleep 1
  321.  
  322.     # Execute the FFmpeg command
  323.     eval $ffmpeg_command 2>&1 | tee -a "$log_file"
  324.  
  325.     # Check for "Killed" message in the log file
  326.     check_for_killed_message
  327.  
  328.     if [ $? -eq 0 ]; then
  329.         mv "$temp_output_file" "$output_file"  # Rename the temporary file to the final output file
  330.         mkdir -p "$video_processing_dir/$dir_path"  # Create processing directory
  331.         mv "$video" "$video_processing_dir/$relative_path"
  332.         echo ""
  333.         echo "$(date '+%Y-%m-%d %H:%M:%S') Converted $video_echo. Your original files will be in the $video_processing_dir_echo folder for comparison. Your new files are in $output_dir_base_echo" | tee -a "$log_file" | fmt -w $width
  334.     else
  335.         echo ""
  336.         echo "$(date '+%Y-%m-%d %H:%M:%S') Error processing \"$video\". Check log file for details." | tee -a "$log_file"
  337.         exit 1
  338.     fi
  339. }
  340.  
  341. # --------------------------------------
  342. #    Start Batch Encoding
  343. # --------------------------------------
  344.  
  345. width=$(tput cols)
  346.  
  347. # Recursively find and process videos and audio
  348. video_count=$(find "$video_drop_dir" -type f \( -iname '*.mp3' -o -iname '*.wav' -o -iname '*.flac' -o -iname '*.aac' -o -iname '*.ogg' -o -iname '*.m4a' -o -iname '*.mp4' -o -iname '*.mkv' -o -iname '*.avi' -o -iname '*.mov' -o -iname '*.flv' -o -iname '*.wmv' -o -iname '*.webm' -o -iname '*.mts' \) | wc -l)
  349.  
  350. # Process each audio file found
  351. find "$video_drop_dir" -type f \( -iname '*.mp3' -o -iname '*.wav' -o -iname '*.flac' -o -iname '*.aac' -o -iname '*.ogg' -o -iname '*.m4a' \) | while read -r audio; do
  352.  
  353.     stop_processing=false
  354.  
  355.     # Function to handle SIGINT (Ctrl+C)
  356.     handle_sigint() {
  357.         echo ""
  358.         echo "Caught SIGINT (Ctrl+C). Exiting immediately." | fmt -w $width
  359.         exit 1  # Exit immediately without performing cleanup
  360.     }
  361.  
  362.     # Trap SIGINT and call the handle_sigint function
  363.     trap handle_sigint SIGINT
  364.  
  365.     if [ "$stop_processing" = true ]; then
  366.         echo "Stopping processing due to SIGINT."
  367.         exit 1
  368.     fi
  369.     process_audio "$audio" || exit 1
  370.  
  371.     # Remove the relative path folder if it's empty
  372.     rmdir "$(dirname "$audio")" --ignore-fail-on-non-empty
  373. done
  374.  
  375. # Process each video found
  376. find "$video_drop_dir" -type f \( -iname '*.mp4' -o -iname '*.mkv' -o -iname '*.avi' -o -iname '*.mov' -o -iname '*.flv' -o -iname '*.wmv' -o -iname '*.webm'  -o -iname '*.mts' \) | while read -r video; do
  377.  
  378.     stop_processing=false
  379.  
  380.     # Function to handle SIGINT (Ctrl+C)
  381.     handle_sigint() {
  382.         echo ""
  383.         echo "Caught SIGINT (Ctrl+C). Exiting immediately." | fmt -w $width
  384.         exit 1  # Exit immediately without performing cleanup
  385.     }
  386.  
  387.     # Trap SIGINT and call the handle_sigint function
  388.     trap handle_sigint SIGINT
  389.  
  390.     if [ "$stop_processing" = true ]; then
  391.         echo "Stopping processing due to SIGINT."
  392.         exit 1
  393.     fi
  394.     process_video "$video" || exit 1
  395.  
  396.     # Remove the relative path folder if it's empty
  397.     rmdir "$(dirname "$video")" --ignore-fail-on-non-empty
  398. done
  399.  
  400. # -----------------------------
  401. #     Finishing Up
  402. # -----------------------------
  403.  
  404. width=$(tput cols)
  405.  
  406. # final output message
  407. echo ""
  408. echo "Log file is in $video_drop_dir_echo.  There may be unprocessed media files or other incompatible files.  Some files may need to be remuxed for compatibility." | tee -a "$log_file" | fmt -w $width
  409. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement