iCloud HEIC/MOV To JPEG/MP4 Bash Script Conversion

Introduction

Two weeks ago, I found that I could not download zipped JPEG/MP4 file anymore. Even if I clicked the “Most Compatible” option, the zipped file I downloaded would only contain HEIC/MOV files.

iCloud Browser Download Interface

At first, I thought it was a bug and could be fixed soon. But after two weeks, it still did not work. On Reddit, many people have also found this issue and reached out to Apple. However, the response they got from Apple is that it is the expected behavior and there is a chance that it will never be reverted. This means I will have to convert HEIC/MOV files to JPEG/MP4 files manually.

In this blog post, I created a bash script for converting HEIC/MOV files to JPEG/MP4 files on Linux systems.

iCloud HEIC/MOV To JPEG/MP4 Bash Script Conversion

With some assistance from ChatGPT, I created the following bash script for converting HEIC/MOV files downloaded from iCloud to JPEG/MP4 files. It assumes FFMPEG and ImageMagick are installed.

To install FFMPEG and ImageMagick on Ubuntu, run the following command.

1
2
$ sudo apt update
$ sudo apt install ffmpeg imagemagick

The bash script is as follows.

convert.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/bin/bash

# Default value for verbosity (suppress FFmpeg outputs)
verbosity="-v quiet"

# Check if ffmpeg and convert (from ImageMagick) are installed
if ! command -v ffmpeg &> /dev/null || ! command -v convert &> /dev/null; then
echo "Please install ffmpeg and ImageMagick before running this script."
exit 1
fi

# Set default resolutions
heic_resolution="2048x1536"
mov_resolution="1280x720"

# Parse command line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-i|--input)
input_dir="$2"
shift 2
;;
-o|--output)
output_dir="$2"
shift 2
;;
-hr|--heic-resolution)
heic_resolution="$2"
shift 2
;;
-mr|--mov-resolution)
mov_resolution="$2"
shift 2
;;
-v|--verbosity)
verbosity="" # Enable FFmpeg console outputs
shift
;;
*)
echo "Unknown argument: $1"
exit 1
;;
esac
done

# Check if input and output directories are provided
if [ -z "$input_dir" ] || [ -z "$output_dir" ]; then
echo "Usage: ./convert.sh -i <input_dir> -o <output_dir> [-hr <heic_resolution>] [-mr <mov_resolution>] [-v]"
exit 1
fi

# Create the output directory if it doesn't exist
mkdir -p "$output_dir"

# Convert HEIC to JPEG or heic to jpeg
for heic_file in "$input_dir"/*.[Hh][Ee][Ii][Cc]; do
if [ -f "$heic_file" ]; then
base_name="$(basename "$heic_file" | sed 's/\(.*\)\.[Hh][Ee][Ii][Cc]/\1/')"
ext="$(basename "$heic_file" | sed 's/.*\.\([Hh][Ee][Ii][Cc]\)/\1/')"
if [ "$ext" == "HEIC" ]; then
output_ext="JPEG"
elif [ "$ext" == "heic" ]; then
output_ext="jpeg"
fi
output_file="$output_dir/$base_name.$output_ext"
convert "$heic_file" -resize "$heic_resolution" "$output_file"
echo "Converted $heic_file to $output_file"
fi
done

# Convert MOV to MP4 or mov to mp4 using ffmpeg
for mov_file in "$input_dir"/*.[Mm][Oo][Vv]; do
if [ -f "$mov_file" ]; then
base_name="$(basename "$mov_file" | sed 's/\(.*\)\.[Mm][Oo][Vv]/\1/')"
ext="$(basename "$mov_file" | sed 's/.*\.\([Mm][Oo][Vv]\)/\1/')"
if [ "$ext" == "MOV" ]; then
output_ext="MP4"
elif [ "$ext" == "mov" ]; then
output_ext="mp4"
fi
output_file="$output_dir/$base_name.$output_ext"
ffmpeg -i "$mov_file" -vf "scale=$mov_resolution" -c:v libx264 -c:a aac -strict experimental $verbosity "$output_file"
echo "Converted $mov_file to $output_file"
fi
done

# Copy files with other extensions
for other_file in "$input_dir"/*; do
if [ -f "$other_file" ] && ! [[ "$other_file" =~ \.[Hh][Ee][Ii][Cc]$|\.[Mm][Oo][Vv]$ ]]; then
cp "$other_file" "$output_dir/$(basename "$other_file")"
echo "Copied $other_file to $output_dir/$(basename "$other_file")"
fi
done

echo "Conversion and copying complete."

The script can be used as follows. It will convert HEIC/MOV files to JPEG/MP4 files and copy other files directly. The format extension letter case is preserved. The user can also specify the resolutions for the converted JPEG/MP4 files.

1
2
3
4
5
6
7
8
9
10
11
$ bash convert.sh -i example-inputs -o example-outputs -hr 2048x1536 -mr 1280x720
Converted example-inputs/IMG_8554.HEIC to example-outputs/IMG_8554.JPEG
Converted example-inputs/IMG_8555.HEIC to example-outputs/IMG_8555.JPEG
Converted example-inputs/IMG_8556.HEIC to example-outputs/IMG_8556.JPEG
Converted example-inputs/IMG_8559.HEIC to example-outputs/IMG_8559.JPEG
Converted example-inputs/IMG_8560.heic to example-outputs/IMG_8560.jpeg
Converted example-inputs/IMG_8557.MOV to example-outputs/IMG_8557.MP4
Converted example-inputs/IMG_8558.MOV to example-outputs/IMG_8558.MP4
Converted example-inputs/IMG_8595.mov to example-outputs/IMG_8595.mp4
Copied example-inputs/KICA-2505.jpg to example-outputs/KICA-2505.jpg
Conversion and copying complete.

Conclusions

Some stupid product designs sometimes changed features that have already been nearly optimum. People should not do stupid things simply because they get paid and have to do something which turns out to be completely useless.

References

iCloud HEIC/MOV To JPEG/MP4 Bash Script Conversion

https://leimao.github.io/blog/iCloud-Bash-Script-HEIC-MOV-To-JPEG-MP4/

Author

Lei Mao

Posted on

10-11-2023

Updated on

10-11-2023

Licensed under


Comments