Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/data/data/com.termux/files/usr/bin/bash
- # --------------------
- # Licence
- # --------------------
- # 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.
- # 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.
- # You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- # -----------------
- # About
- # -----------------
- # This script is for Termux on Android and is not associated with the apps it uses.
- # Copyright Joshua Hansen and contributors: Microsoft Co-Pilot and ChatGPT.
- # 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.
- # -----------------------
- # Instructions
- # -----------------------
- # Usage: ./ziggle_wump.sh [-r resolution] [-d] [-f "ffmpeg_options"] [-h|--help]
- # -r resolution Custom resolution height for video conversion preserving aspect ratio (default: original resolution) Downscaling your videos will significantly reduce the file size, but may introduce artifacts and shimmering. Upscaling will only result in larger file sizes. It will not make your video look better.
- # -d Use default behavior (original resolution x265 video, opus audio)
- # -f "ffmpeg_options" Override default FFmpeg options with custom command line options. ex. bash ./ziggle_wump.sh -f "-c:v libx265 -c:a libopus -x265-params "aq-mode=1:psy-rd=0.75:psy-rdoq=4.0:rd=4:rdoq-level=1:rect=0:strong-intra-smoothing=0""
- # -h, --help Display this help message
- # 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.
- # 2. Make it executable: chmod +x ziggle_wump.sh
- # 3. Run the script: bash ./ziggle_wump.sh [options]
- # -------------------
- # README
- # -------------------
- # Ziggle Wump: The Simple FFmpeg Command Line Companion Script for Termux on Android
- # 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
- # 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.
- # Check out https://dontkillmyapp.com/ for more information and perhaps find a fix for your particular phone.
- # -----------------------------
- # Title
- # -----------------------------
- # ziggle_wump
- # The Simple FFmpeg Command Line Companion Script for Termux on Android
- # -----------------------------
- # Variables
- # -----------------------------
- # Full Log file path
- log_file="$HOME/storage/shared/Movies/VideoDrop/convert.log"
- # Shortened log file path for terminal output
- log_file_echo=$(echo "$log_file" | sed 's|/data/data/com.termux/files/home|.../home|g')
- # Default resolution (empty implies original resolution)
- default_resolution=""
- # Full directory paths
- video_drop_dir="$HOME/storage/shared/Movies/VideoDrop"
- video_processing_dir="$HOME/storage/shared/Movies/VideoProcessing"
- output_dir_base="$HOME/storage/shared/Movies/VideoConverted"
- # Shortened directory paths for terminal output
- video_drop_dir_echo=$(echo "$video_drop_dir" | sed 's|/data/data/com.termux/files/home|.../home|g')
- video_processing_dir_echo=$(echo "$video_processing_dir" | sed 's|/data/data/com.termux/files/home|.../home|g')
- output_dir_base_echo=$(echo "$output_dir_base" | sed 's|/data/data/com.termux/files/home|.../home|g')
- # Initialize optional variables
- resolution="$default_resolution"
- ffmpeg_custom_options=""
- # -----------------------------
- # Command Flags
- # -----------------------------
- # Function to display help message
- show_help() {
- width=$(tput cols)
- echo "Ziggle Wump will create $video_drop_dir_echo the first time if it doesn't exist. Place your media files here." | tee -a "$log_file" | fmt -w $width
- echo "Usage: $0 [-r resolution] [-d] [-f \"ffmpeg_options\"] [-h|--help]" | fmt -w $width
- echo " -r resolution ex. bash ./ziggle_wump.sh -r 720 Custom resolution height for video conversion preserving aspect ratio (default: original resolution) Downscaling your videos will significantly reduce the file size, but may introduce artifacts and shimmering. Upscaling will only result in larger file sizes. It will not make your video look better." | fmt -w $width
- echo " -d Use default behavior"
- echo "(original resolution x265 video, opus audio)"
- echo " -f \"ffmpeg_options\" Override default FFmpeg options with custom command line options. ex. bash ./ziggle_wump.sh -f \""-c:v libx265 -c:a libopus -x265-params "aq-mode=1:psy-rd=0.75:psy-rdoq=4.0:rd=4:rdoq-level=1:rect=0:strong-intra-smoothing=0\"\"" | fmt -w $width
- echo " -h, --help Display this help message" | fmt -w $width
- exit 0
- }
- # Parse command-line options
- while getopts "r:df:h" opt; do
- case $opt in
- r) resolution="$OPTARG" ;; # Set custom resolution by height
- d) resolution="$default_resolution" ;; # Use default settings
- f) ffmpeg_custom_options="$OPTARG" ;; # Set custom FFmpeg options
- h) show_help ;; # Display help
- *) show_help ;; # Display help for invalid options
- esac
- done
- shift $((OPTIND -1))
- # ---------------------------------
- # Dependencies
- # ---------------------------------
- # Ensure dependencies are installed and all packages are up to date.
- echo "Updating, please wait..."
- sleep 1
- pkg update && pkg upgrade -y
- if ! command -v ffmpeg &> /dev/null; then
- pkg install ffmpeg -y
- fi
- if ! command -v ncurses-utils &> /dev/null; then
- pkg install ncurses-utils -y
- fi
- echo "Update complete."
- sleep 1
- # -----------------------------------------------------
- # Create Directories and log file
- # -----------------------------------------------------
- # Create necessary directories if they don't exist
- mkdir -p "$video_drop_dir" "$video_processing_dir" "$output_dir_base"
- # Change to the VideoDrop directory
- cd "$video_drop_dir" || { echo "Directory change failed"; exit 1; }
- # Check if log file exists
- if [ -f "$log_file" ]; then
- echo "Old log file found. Deleting..."
- rm "$log_file"
- echo "File deleted."
- else
- echo "Log File does not exist. The script will create $log_file_echo"
- fi
- # ------------------------
- # Start script
- # ------------------------
- width=$(tput cols)
- echo "Running... Press Ctrl+C to stop."
- sleep 1
- echo ""
- echo "Ziggle Wump will create $video_drop_dir_echo the first time if it doesn't exist. Place your media files here." | tee -a "$log_file" | fmt -w $width
- echo ""
- 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
- echo ""
- 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
- echo ""
- # Function to prompt the user to continue or quit
- prompt_continue_or_quit() {
- while true; do
- # Recursively find and process videos and audio
- video_count=$(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 '*.mp3' -o -iname '*.wav' -o -iname '*.flac' -o -iname '*.aac' -o -iname '*.ogg' -o -iname '*.m4a' \) | wc -l)
- if [ "$video_count" -eq 0 ]; then
- 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." | tee -a "$log_file" | fmt -w $width
- exit 0
- fi
- # Prompt text
- prompt_text="Compatible media files detected in $video_drop_dir_echo. You can start encoding now. Do you wish to proceed? (Y/N): "
- # Format the prompt text
- formatted_prompt=$(echo "$prompt_text" | fmt -w $width)
- # Read user input with formatted prompt
- read -p "$formatted_prompt" yn
- case $yn in
- [Yy]* ) return 0;; # Continue
- [Nn]* ) echo "Exiting script."; exit 0;; # Quit
- * ) echo "Please answer Y or N.";;
- esac
- done
- }
- # Prompt the user to continue or quit
- prompt_continue_or_quit
- echo "Starting conversion process..." | tee -a "$log_file"
- sleep 1
- # -----------------------------
- # Audio Encoder
- # -----------------------------
- width=$(tput cols)
- # Function to check the log file for "Killed" message
- check_for_killed_message() {
- if grep -q " Killed " "$log_file"; then
- echo "$(date '+%Y-%m-%d %H:%M:%S') Error: Process was killed. Check log file for details." | tee -a "$log_file"
- return 1
- fi
- return 0
- }
- # Function to process audio files
- process_audio() {
- local audio="$1"
- local audio_echo=$(echo "$audio" | sed 's|/data/data/com.termux/files/home|/home|g')
- local relative_path="${audio#$video_drop_dir/}"
- local dir_path=$(dirname "$relative_path")
- local base_name=$(basename "$relative_path" | tr -cd '[:alnum:]._ -')
- local output_dir="$output_dir_base/$dir_path"
- local output_file="$output_dir/${base_name}_converted.opus"
- local temp_output_file="$output_file.tmp"
- mkdir -p "$output_dir" # Create output directory
- echo "$(date '+%Y-%m-%d %H:%M:%S') Processing $audio to $output_file" | tee -a "$log_file"
- # Construct the FFmpeg command for audio processing
- local ffmpeg_command="ffmpeg -nostdin -loglevel verbose -y -i \"$audio\" -c:a libopus -f opus \"$temp_output_file\""
- # Execute the FFmpeg command
- eval $ffmpeg_command 2>&1 | tee -a "$log_file"
- # Check for "Killed" message in the log file
- if ! check_for_killed_message; then
- echo "$(date '+%Y-%m-%d %H:%M:%S') Error: Process was killed. Exiting." | tee -a "$log_file"
- exit 1
- fi
- if [ $? -eq 0 ]; then
- mv "$temp_output_file" "$output_file" # Rename the temporary file to the final output file
- mkdir -p "$video_processing_dir/$dir_path" # Create processing directory
- mv "$audio" "$video_processing_dir/$relative_path"
- echo ""
- 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
- else
- echo ""
- echo "$(date '+%Y-%m-%d %H:%M:%S') Error processing \"$audio\". Check log file for details." | tee -a "$log_file"
- exit 1
- fi
- }
- # ------------------------------
- # Video Encoder
- # ------------------------------
- width=$(tput cols)
- # Function to check the log file for "Killed" message
- check_for_killed_message() {
- if grep -q " Killed " "$log_file"; then
- echo "$(date '+%Y-%m-%d %H:%M:%S') Error: Process was killed. Check log file for details." | tee -a "$log_file" | fmt -w $width
- exit 1
- fi
- }
- # Function to process videos
- process_video() {
- local video="$1"
- local video_echo=$(echo "$video" | sed 's|/data/data/com.termux/files/home|.../home|g')
- local relative_path="${video#$video_drop_dir/}"
- local dir_path=$(dirname "$relative_path")
- local base_name=$(basename "$relative_path" | tr -cd '[:alnum:]._ -')
- local output_dir="$output_dir_base/$dir_path"
- local output_file="$output_dir/${base_name}_converted.mkv"
- local temp_output_file="$output_file.tmp"
- local scale_filter=""
- [ -n "$resolution" ] && scale_filter="-vf \"scale=trunc(oh*a/2)*2:$resolution,setsar=1\""
- mkdir -p "$output_dir" # Create output directory
- echo "$(date '+%Y-%m-%d %H:%M:%S') Processing $video to $output_file" | tee -a "$log_file"
- # Construct the FFmpeg command
- local ffmpeg_command
- if [ -n "$ffmpeg_custom_options" ]; then
- ffmpeg_command="ffmpeg -nostdin -loglevel verbose -y -i \"$video\" $ffmpeg_custom_options -f matroska \"$temp_output_file\""
- else
- ffmpeg_command="ffmpeg -nostdin -loglevel verbose -y -i \"$video\" -c:v libx265 -c:a libopus $scale_filter -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\" -f matroska \"$temp_output_file\""
- fi
- # Execute the FFmpeg command
- eval $ffmpeg_command 2>&1 | tee -a "$log_file"
- # Check for "Killed" message in the log file
- check_for_killed_message
- if [ $? -eq 0 ]; then
- mv "$temp_output_file" "$output_file" # Rename the temporary file to the final output file
- mkdir -p "$video_processing_dir/$dir_path" # Create processing directory
- mv "$video" "$video_processing_dir/$relative_path"
- echo ""
- 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
- else
- echo ""
- echo "$(date '+%Y-%m-%d %H:%M:%S') Error processing \"$video\". Check log file for details." | tee -a "$log_file"
- exit 1
- fi
- }
- # --------------------------------------
- # Start Batch Encoding
- # --------------------------------------
- width=$(tput cols)
- # Recursively find and process videos and audio
- video_count=$(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 '*.mp3' -o -iname '*.wav' -o -iname '*.flac' -o -iname '*.aac' -o -iname '*.ogg' -o -iname '*.m4a' \) | wc -l)
- # Process each audio file found
- 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
- stop_processing=false
- # Function to handle SIGINT (Ctrl+C)
- handle_sigint() {
- echo ""
- echo "Caught SIGINT (Ctrl+C). Exiting immediately." | fmt -w $width
- exit 1 # Exit immediately without performing cleanup
- }
- # Trap SIGINT and call the handle_sigint function
- trap handle_sigint SIGINT
- if [ "$stop_processing" = true ]; then
- echo "Stopping processing due to SIGINT."
- exit 1
- fi
- process_audio "$audio" || exit 1
- done
- # Process each video found
- 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' \) | while read -r video; do
- stop_processing=false
- # Function to handle SIGINT (Ctrl+C)
- handle_sigint() {
- echo ""
- echo "Caught SIGINT (Ctrl+C). Exiting immediately." | fmt -w $width
- exit 1 # Exit immediately without performing cleanup
- }
- # Trap SIGINT and call the handle_sigint function
- trap handle_sigint SIGINT
- if [ "$stop_processing" = true ]; then
- echo "Stopping processing due to SIGINT."
- exit 1
- fi
- process_video "$video" || exit 1
- done
- # -----------------------------
- # Finishing Up
- # -----------------------------
- width=$(tput cols)
- # Check for empty directories and remove them, except for the VideoDrop folder
- find "$video_drop_dir" -type d -empty -not -path "$video_drop_dir" -exec echo "Removing empty directory: {} Checking..." \; -exec rmdir {} \; | fmt -w $width
- echo ""
- echo "Log file is in $video_drop_dir_echo. There may also be nested folders that are empty, and unprocessed media files or other incompatible files. Some files may need to be remuxed for compatibility." | tee -a "$log_file" | fmt -w $width
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement