/ de-omarchy / bin / omarchy-transcode
swadhinbiswas Initial de-omarchy: Omarchy UI layer for Arch-based distros · 8/22/2026
9f393b2
208 lines · 4.9 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/bin/bash

# omarchy:group=transcode
# omarchy:name=
# omarchy:summary=Transcode pictures and videos for sharing
# omarchy:args=[--path path] [input] [format] [resolution]
# omarchy:examples=omarchy transcode|omarchy transcode --path ~/Downloads|omarchy transcode ~/Videos/demo.mov mp4 1080p|omarchy transcode ~/Pictures/background.heic jpg medium

set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  omarchy transcode [--path path] [input] [format] [resolution]

With no input, pick a picture or video from ~/Pictures and ~/Videos,
or only from --path when provided. Then pick the output format and resolution.

Options:
  --path path  Limit interactive fuzzy file selection to this path

Formats:
  Pictures: jpg, png
  Videos: mp4, gif

Resolutions:
  Pictures: high, medium, low
  Videos: 4k, 1080p, 720p
EOF
}

media_type() {
  local mime
  mime=$(file -b --mime-type "$1")

  case "$mime" in
  image/*) echo picture ;;
  video/*) echo video ;;
  *)
    echo "Unsupported file type: $mime" >&2
    return 1
    ;;
  esac
}

output_path() {
  local input="$1"
  local format="$2"
  local resolution="$3"
  local dir base stem

  dir=$(dirname -- "$input")
  base=$(basename -- "$input")
  stem="${base%.*}"

  printf '%s/%s-%s.%s' "$dir" "$stem" "$resolution" "$format"
}

transcode_picture() {
  local input="$1" format="$2" resolution="$3" output="$4"
  local resize

  case "$resolution" in
  high) resize='3160x>' ;;
  medium) resize='2160x>' ;;
  low) resize='1080x>' ;;
  *)
    echo "Invalid picture resolution: $resolution" >&2
    return 1
    ;;
  esac

  case "$format" in
  jpg)
    magick "$input" -resize "$resize" -quality 85 -strip "$output"
    ;;
  png)
    magick "$input" -resize "$resize" -strip -define png:compression-filter=5 \
      -define png:compression-level=9 \
      -define png:compression-strategy=1 \
      -define png:exclude-chunk=all \
      "$output"
    ;;
  *)
    echo "Invalid picture format: $format" >&2
    return 1
    ;;
  esac
}

transcode_video() {
  local input="$1" format="$2" resolution="$3" output="$4"
  local scale

  case "$resolution" in
  4k) scale='scale=-2:2160' ;;
  1080p) scale='scale=-2:1080' ;;
  720p) scale='scale=-2:720' ;;
  *)
    echo "Invalid video resolution: $resolution" >&2
    return 1
    ;;
  esac

  case "$format" in
  mp4)
    if [[ $resolution == "4k" ]]; then
      ffmpeg -i "$input" -vf "$scale" -c:v libx265 -preset slow -crf 24 -c:a aac -b:a 192k -movflags +faststart "$output"
    else
      ffmpeg -i "$input" -vf "$scale" -c:v libx264 -preset fast -crf 23 -c:a aac -b:a 192k -movflags +faststart "$output"
    fi
    ;;
  gif)
    ffmpeg -i "$input" -vf "fps=10,$scale:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" "$output"
    ;;
  *)
    echo "Invalid video format: $format" >&2
    return 1
    ;;
  esac
}

copy_to_clipboard() {
  local output="$1"
  local uri

  uri="file://$(realpath -- "$output")"
  printf '%s\n' "$uri" | wl-copy --type text/uri-list
}

main() {
  local input="" format="" resolution="" search_path=""
  local type output positional=()

  while (( $# > 0 )); do
    case "$1" in
    --path)
      shift
      (( $# > 0 )) || { echo "Missing value for --path" >&2; return 2; }
      search_path="$1"
      ;;
    --help | -h)
      usage
      return 0
      ;;
    --)
      shift
      positional+=("$@")
      break
      ;;
    --*)
      echo "Unknown option: $1" >&2
      usage >&2
      return 2
      ;;
    *)
      positional+=("$1")
      ;;
    esac
    shift
  done

  input="${positional[0]:-}"
  format="${positional[1]:-}"
  resolution="${positional[2]:-}"
  search_path="${search_path:-$HOME/Pictures:$HOME/Videos}"

  if [[ -z $input ]]; then
    input=$(omarchy-menu-file "Transcode picture or video" "$search_path" "jpg jpeg png webp gif heic avif mp4 mov m4v mkv webm avi")
  fi

  [[ -n $input ]] || return 1
  [[ -f $input ]] || { echo "File not found: $input" >&2; return 1; }

  type=$(media_type "$input")

  if [[ -z $format ]]; then
    if [[ $type == "picture" ]]; then
      format=$(omarchy-menu-select "Select format" jpg png)
    else
      format=$(omarchy-menu-select "Select format" mp4 gif)
    fi
  fi

  if [[ -z $resolution ]]; then
    if [[ $type == "picture" ]]; then
      resolution=$(omarchy-menu-select "Select resolution" high medium low)
    else
      resolution=$(omarchy-menu-select "Select resolution" 4k 1080p 720p)
    fi
  fi

  output=$(output_path "$input" "$format" "$resolution")

  if [[ $type == "video" ]]; then
    omarchy-notification-send -g  "Transcoding video…" "$(basename -- "$input") to $format ($resolution)"
    transcode_video "$input" "$format" "$resolution" "$output"
    copy_to_clipboard "$output"
    omarchy-notification-send -g  "Transcoded to $resolution $format" "Saved and copied to clipboard."
  else
    transcode_picture "$input" "$format" "$resolution" "$output"
    copy_to_clipboard "$output"
    omarchy-notification-send -g  "Transcoded to $resolution $format" "Saved and copied to clipboard."
  fi
}

main "$@"