mirror of
https://github.com/arthur-pbty/arthur-os.git
synced 2026-08-01 20:28:16 +02:00
208 lines
4.9 KiB
Bash
Executable File
208 lines
4.9 KiB
Bash
Executable File
#!/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/wallpaper.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 with Walker 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 "$output"
|
|
else
|
|
ffmpeg -i "$input" -vf "$scale" -c:v libx264 -preset fast -crf 23 -c:a copy "$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
|
|
[[ $# -gt 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 "" "Transcoding video…" "$(basename -- "$input") to $format ($resolution)"
|
|
transcode_video "$input" "$format" "$resolution" "$output"
|
|
copy_to_clipboard "$output"
|
|
omarchy-notification-send "" "Transcoded to $resolution $format" "Saved and copied to clipboard."
|
|
else
|
|
transcode_picture "$input" "$format" "$resolution" "$output"
|
|
copy_to_clipboard "$output"
|
|
omarchy-notification-send "" "Transcoded to $resolution $format" "Saved and copied to clipboard."
|
|
fi
|
|
}
|
|
|
|
main "$@"
|