Thi's avatar
HomeAboutNotesBlogTopicsToolsReading
About|My sketches |Cooking |Cafe icon Support Thi
💌 [email protected]

Video / Image editor with ffmpeg commands

Anh-Thi Dinh
draft
RelaxMacOSWindowsLinuxSkillsOthers
Left aside
⚠️
This is a quick & dirty draft, for me only!

Remove sound from video

Compress images

Compress all images in the current folder,

Compress and reduce video size

  • Compress and resize video to 480p
  • Compress and resize all videos in the current folder to 480p
  • Create a handy command in .zshrc or .bashrc to compress a video
  • Do the same things for all videos in a folder,

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.

Split a videos

Split a video into segments of 200 ms each,

Converter

Convert .m3u8 (streaming video) to a .mp4
◆Remove sound from video◆Compress images◆Compress and reduce video size◆Merge videos◆Split a videos◆Converter
About|My sketches |Cooking |Cafe icon Support Thi
💌 [email protected]
1ffmpeg -i input.mp4 -c:v copy -an output.mp4
1for file in *.jpg *.jpeg *.png; do ffmpeg -i "$file" -q:v 10 -y "${file%.*}_temp.${file##*.}" && mv "${file%.*}_temp.${file##*.}" "$file"; done
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
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
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>
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.
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
1ffmpeg -i input.mp4 -c copy -map 0 -segment_time 200 -f segment output_%03d.mp4
1ffmpeg -i "$1" -c copy -bsf:a aac_adtstoasc "${1%.m3u8}.mp4"