Bash | bulding a script to handle media operations split, merge and convert for all formats and a single executable script


in this post we will explore the process of building a terminal bash script to split, merge and convert media files (video and audio) writing and explaining the code block by block


The Code

#!/bin/bash
################################################################################
# Script: media_tools.sh
# Description: A script for media processing (split, merge, and convert)
# Author: Saleh Geberty
################################################################################

# Function to display script usage
display_usage() {
    echo "Usage: ./media_tools.sh [OPTIONS] [FILES...]"
    echo "Options:"
    echo "  -a, --action     Specify the action to perform: split, convert, merge"
    echo "  -p, --process    Specify the process to apply: copy, encode"
    echo
    echo "Actions:"
    echo "  split    Split a video file into smaller segments."
    echo "  convert  Convert an audio file to a different format."
    echo "  merge    Merge multiple files into one."
    echo
    echo "Examples:"
    echo "  ./media_tools.sh -a split input.mp4 00:00:30 00:05:00 output.mp4"
    echo "  ./media_tools.sh -a convert input.wav mp3 output.mp3"
    echo "  ./media_tools.sh -a merge output.txt file1.txt file2.txt file3.txt"
}

# Function to split a video file into smaller segments
split_video() {
    input_file=$1
    start_time=$2
    duration=$3
    output_file=$4

    echo "Splitting video: $input_file"
    echo "Start time: $start_time"
    echo "Duration: $duration"
    echo "Output file: $output_file"

    # Use FFmpeg to split the video
    ffmpeg -i "$input_file" -ss "$start_time" -t "$duration" -c copy "$output_file"
}

# Function to convert an audio file to a different format
convert_audio() {
    input_file=$1
    output_format=$2
    output_file=$3

    echo "Converting audio: $input_file"
    echo "Output format: $output_format"
    echo "Output file: $output_file"

    # Use FFmpeg to convert the audio
    ffmpeg -i "$input_file" -c:a "$output_format" "$output_file"
}

# Function to merge multiple media files into one using ffmpeg
merge_files() {
    output_file=$1
    shift
    input_files=("$@")

    # Check if all input files are media files
    for file in "${input_files[@]}"; do
        if ! file --mime-type "$file" | grep -qE 'video|audio'; then
            echo "Error: $file is not a media file."
            return 1
        fi
    done

    echo "Merging files: ${input_files[*]}"
    echo "Output file: $output_file"

    # Use ffmpeg to merge the media files
    ffmpeg -i "concat:$(printf '%s|' "${input_files[@]}")" -c copy "$output_file"
}

# Autocompletion function for command-line options
_params_autocomplete() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--action --process"

    case "${prev}" in
        -a|--action)
            COMPREPLY=($(compgen -W "split convert merge" -- "${cur}"))
            return 0
            ;;
        -p|--process)
            COMPREPLY=($(compgen -W "copy encode" -- "${cur}"))
            return 0
            ;;
        *)
            COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
            return 0
            ;;
    esac
}

# If the script is being sourced, enable autocomplete
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
    complete -F _params_autocomplete -o default ./media_tools.sh
    return 0
fi


# Parse the command-line arguments only if the script is executed directly
while [[ $# -gt 0 ]]; do
    key="$1"

    case $key in
        -h|--help)
            display_usage
            exit 0
            ;;
        -a|--action)
            action="$2"
            shift # past argument
            shift # past value
            ;;
        -p|--process)
            process="$2"
            shift # past argument
            shift # past value
            ;;
        *)
            files+=("$1") # add the file to the list
            shift
            ;;
    esac
done

# Handle the action based on the provided arguments
if [[ -n $action ]]; then
    if [[ $action == "split" ]]; then
        input_file="${files[0]}"
        start_time="${files[1]}"
        duration="${files[2]}"
        output_file="${files[3]}"
        split_video "$input_file" "$start_time" "$duration" "$output_file"
    elif [[ $action == "convert" ]]; then
        input_file="${files[0]}"
        output_format="${files[1]}"
        output_file="${files[2]}"
        convert_audio "$input_file" "$output_format" "$output_file"
    elif [[ $action == "merge" ]]; then
        output_file="${files[0]}"
        shift
        input_files=("$@")
        merge_files "$output_file" "${input_files[@]}"
    else
        echo "Invalid action. Available actions: split, convert, merge"
    fi
fi


How it Works

This code is a Bash script called "media_tools.sh" that provides a set of media processing functionalities. Let's go through the code and understand how it works.

The script begins with some comments that describe the purpose of the script, its author, and a brief summary of what it does.

Next, there is a function called `display_usage()` that is responsible for displaying the script's usage instructions. It prints out the available options, actions, and provides some examples.

After that, there are three main functions that implement the media processing operations: `split_video()`, `convert_audio()`, and `merge_files()`. These functions are defined but not executed yet.

The `split_video()` function takes an input file, start time, duration, and output file as parameters. Inside the function, there are echo statements that display the details of the video splitting process. You can see a comment that instructs you to add the actual command for splitting the video.

The `convert_audio()` function takes an input file, output format, and output file as parameters. Similar to `split_video()`, it echoes the details of the audio conversion process, and there's a comment indicating where you should put the actual command for converting the audio.

The `merge_files()` function is responsible for merging multiple media files into one using the FFmpeg tool. It takes an output file and an array of input files as parameters. The function first checks if all input files are valid media files by using the `file` command. If any file is not recognized as a media file, it prints an error message and returns an error status. Otherwise, it echoes the details of the merging process and uses the FFmpeg command to merge the files.

The script also includes an autocompletion function called `_params_autocomplete()` that provides autocomplete suggestions for command-line options. It is used for enhancing the script's usability.

After the autocompletion function, there is a conditional statement that checks if the script is being sourced or executed directly. If the script is being sourced, it enables autocomplete by using the `complete` command and returns.

If the script is executed directly, it enters a while loop that iterates over the command-line arguments. It parses the options and values provided and assigns them to variables. The files are stored in an array called `files`.

Finally, the script handles the action based on the provided arguments. It checks the value of the `action` variable and calls the corresponding function with the appropriate parameters.

To summarize, this script provides media processing functionalities such as splitting videos, converting audio files, and merging media files. It allows users to specify the desired action and parameters through command-line arguments and then executes the corresponding function based on the provided action.

Comments