Thi Notes
AboutNotesBlogTopicsToolsReading
About|Sketches |Cooking |Cafe icon Support Thi
📺

Video / Image editor with ffmpeg commands

Video / Image editor with ffmpeg commands

Anh-Thi Dinh
Relax
MacOS
Windows
Linux
Skills
Others

Remove sound from video

1ffmpeg -i input.mp4 -c:v copy -an output.mp4

Compress images

Compress all images in the current folder,
1for file in *.jpg *.jpeg *.png; do ffmpeg -i "$file" -q:v 10 -y "${file%.*}_temp.${file##*.}" && mv "${file%.*}_temp.${file##*.}" "$file"; done

Compress and reduce video size

  • Compress and resize video to 480p
    • 1ffmpeg -i file_name.mp4 -vf scale=-2:480 -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k -movflags +faststart file_name_compressed.mp4
  • Compress and resize all videos in the current folder to 480p
    • 1for file in *.{mp4,mov,avi,mkv,m4v}; do
      2  [ -f "$file" ] || continue
      3  ffmpeg -i "$file" -vf "scale=-2:480" -c:v libx264 -crf 28 -preset slow -c:a aac -b:a 96k "480p_${file%.*}.mp4"
      4done
  • Create a handy command in .zshrc or .bashrc to compress a video
    • 1fix_video() {
      2    local replace=false
      3    local input=""
      4    local threads="6"
      5
      6    # Parse arguments
      7    while [[ $# -gt 0 ]]; do
      8        case $1 in
      9            --replace)
      10                replace=true
      11                shift
      12                ;;
      13            --threads)
      14                if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then
      15                    threads="$2"
      16                    shift 2
      17                else
      18                    echo "Error: --threads requires a numeric value"
      19                    return 1
      20                fi
      21                ;;
      22            *)
      23                if [[ -z "$input" ]]; then
      24                    input="$1"
      25                else
      26                    echo "Error: Multiple input files specified"
      27                    return 1
      28                fi
      29                shift
      30                ;;
      31        esac
      32    done
      33
      34    if [[ -z "$input" ]]; then
      35        echo "Usage: fix_video [--replace] [--threads N] <filename.ext>"
      36        return 1
      37    fi
      38
      39    local basename="${input%.*}"
      40    local output_file
      41    local ffmpeg_cmd="ffmpeg -i \"$input\" -threads $threads -c:v libx264 -c:a aac -map_metadata 0"
      42
      43    if [[ "$replace" == true ]]; then
      44        # Create temporary file first, then replace original
      45        output_file="${basename}_temp.mp4"
      46        eval "$ffmpeg_cmd \"$output_file\""
      47
      48        if [[ $? -eq 0 ]]; then
      49            # Preserve original file's creation date
      50            touch -r "$input" "$output_file"
      51            mv "$output_file" "$input"
      52            echo "Video fixed and replaced: $input"
      53        else
      54            rm -f "$output_file"
      55            echo "Error: Failed to process video"
      56            return 1
      57        fi
      58    else
      59        # Create new file with fixed_ prefix
      60        output_file="fixed_${basename}.mp4"
      61        eval "$ffmpeg_cmd \"$output_file\""
      62
      63        if [[ $? -eq 0 ]]; then
      64            # Preserve original file's creation date
      65            touch -r "$input" "$output_file"
      66            echo "Video fixed: $output_file"
      67        else
      68            echo "Error: Failed to process video"
      69            return 1
      70        fi
      71    fi
      72}
      Usage: fix_video [--replace] [--threads N] <filename.ext>
  • Do the same things for all videos in a folder,
    • 1fix_all_videos() {
      2    local replace=false
      3    local target_folder="."
      4    local threads="6"
      5    locall processed_count=0
      6    local error_count=0
      7
      8    # Parse arguments
      9    while [[ $# -gt 0 ]]; do
      10        case $1 in
      11            --replace)
      12                replace=true
      13                shift
      14                ;;
      15            --threads)
      16                if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then
      17                    threads="$2"
      18                    shift 2
      19                else
      20                    echo "Error: --threads requires a numeric value"
      21                    return 1
      22                fi
      23                ;;
      24            *)
      25                if [[ -z "$target_folder" || "$target_folder" == "." ]]; then
      26                    target_folder="$1"
      27                else
      28                    echo "Error: Multiple target folders specified"
      29                    return 1
      30                fi
      31                shift
      32                ;;
      33        esac
      34    done
      35
      36    # Check if target folder exists
      37    if [[ ! -d "$target_folder" ]]; then
      38        echo "Error: Folder '$target_folder' does not exist"
      39        return 1
      40    fi
      41
      42    # Define common video extensions
      43    local extensions=("mp4" "MP4" "mov" "MOV" "avi" "AVI" "mkv" "MKV" "webm" "WEBM" "flv" "FLV" "wmv" "WMV" "m4v" "M4V")
      44
      45    echo "Searching for videos in: $target_folder"
      46    echo "Mode: $([ "$replace" == true ] && echo "Replace original files" || echo "Create new files with 'fixed_' prefix")"
      47    echo "Threads: $threads"
      48    echo "----------------------------------------"
      49
      50    # Find and process all video files
      51    for ext in "${extensions[@]}"; do
      52        while IFS= read -r -d '' file; do
      53            echo "Processing: $(basename "$file")"
      54
      55            # Call fix_video function for each file
      56            if [[ "$replace" == true ]]; then
      57                fix_video --replace --threads "$threads" "$file"
      58            else
      59                fix_video --threads "$threads" "$file"
      60            fi
      61
      62            if [[ $? -eq 0 ]]; then
      63                ((processed_count++))
      64                echo "✅ Success: $(basename "$file")"
      65            else
      66                ((error_count++))
      67                echo "❌ Failed: $(basename "$file")"
      68            fi
      69            echo ""
      70        done &lt; &lt;(find "$target_folder" -maxdepth 1 -name "*.${ext}" -type f -print0 2&gt;/dev/null)
      71    done
      72
      73    echo "----------------------------------------"
      74    echo "Processing complete!"
      75    echo "✅ Successfully processed: $processed_count videos"
      76    if [[ $error_count -gt 0 ]]; then
      77        echo "❌ Failed: $error_count videos"
      78    fi
      79}
      Usage: fix_all_videos [--replace] [--threads N] [folder]. Use . for the current folder of the cursor.

Merge videos

Merge all video files named a_1.mp4, a_2.mp4, etc. into a single file a.mp4 in order, with smooth transitions.
1ffmpeg -f concat -safe 0 -i <(for i in {1..2}; do echo "file '$(pwd)/a_$i.mp4'"; done) -c:v libx264 -preset fast -crf 23 -c:a aac a.mp4
An alias in .zshrc or .bashrc to merge and also mute all video starting with letter a and the number of the last file is 5
1alias merge_video='_merge_video() { 
2  local prefix=$1
3  local last=$2
4  local concat_file=$(mktemp)
5  
6  for i in {1..$last}; do
7    echo "file '\''$(pwd)/${prefix}_${i}.mp4'\''" >> $concat_file
8  done
9  
10  ffmpeg -f concat -safe 0 -i $concat_file -an -c copy "${prefix}_merged.mp4"
11  rm $concat_file
12}; _merge_video'
Usage: merge_video a 5

Split a videos

Split a video into segments of 200 ms each,
1ffmpeg -i input.mp4 -c copy -map 0 -segment_time 200 -f segment output_%03d.mp4

Converter

Convert .m3u8 (streaming video) to a .mp4
1ffmpeg -i "$1" -c copy -bsf:a aac_adtstoasc "${1%.m3u8}.mp4"
In this post
◆Remove sound from video◆Compress images◆Compress and reduce video size◆Merge videos◆Split a videos◆Converter