From dc8be77bfdab5857c1a64430594501c590e9b6f6 Mon Sep 17 00:00:00 2001 From: Julien Moutinho Date: Sun, 26 Feb 2023 00:51:44 +0100 Subject: [PATCH 1/1] init --- index.css | 125 ++++++++++++++++++++++++++++++++ index.sh | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ pull.sh | 24 +++++++ push.sh | 13 ++++ 4 files changed, 374 insertions(+) create mode 100644 index.css create mode 100755 index.sh create mode 100755 pull.sh create mode 100755 push.sh diff --git a/index.css b/index.css new file mode 100644 index 0000000..5ffc4e7 --- /dev/null +++ b/index.css @@ -0,0 +1,125 @@ +html { + text-rendering: optimizeLegibility; + font-kerning: normal; +} + +nav.path > ul { + padding-left: 0; +} +nav.path > ul > li { + list-style-type: none; +} + +.camera { + clear:right; +} +.camera > ul { + display: grid; + grid-auto-flow: dense; + grid-gap: 1em; + /* Grow the pictures when the screen grows, + * fitting as many 640x360 videos per row as possible, + * without resizing a video more than its width, + * substracting 2*5px for the margins. + */ + grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); + padding: 0 0; +} + +/* +@media screen and (min-width: 320px) { + .camera > ul { + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + } +} +@media screen and (min-width: 768px) { + .camera > ul { + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + } +} +*/ + +.camera > ul > li { + list-style-type: none; + position: relative; +} +.camera > ul > li.highlight-box { + grid-row: span 2; + grid-column: span 2; +} +.camera > ul > li.highlight-tall { + grid-row: span 2; +} +.camera > ul > li.highlight-wide { + grid-column: span 2; +} +.camera > ul > li img { + border: 1px solid black; + box-shadow: 1px 3px 8px rgba(0, 0, 0, 0.5); + display: block; + object-fit: contain; + margin: auto; + /*height: 100%;*/ + width: 100%; +} +.camera > ul > li video { + border: 1px solid black; + box-shadow: 1px 3px 8px rgba(0, 0, 0, 0.5); + background-color: black; + display: block; + object-fit: contain; + margin: auto; + width: 100%; + height: 100%; +} +.camera > ul > li video.orient-90 { +} +.camera > ul > li:target img, +.camera > ul > li:target video { + border: 1px solid blue; +} + +.camera > ul > li div.item { + display: flex; + flex-direction: column; +} +.camera > ul > li div.item > span.comment { + display: inline-block; + margin: 1ex 1ex 1ex 1ex; +} + + +.camera > ul > li span.infos { + display:none; + font-size: 0.8rem; + font-weight: normal; + color: #fff; + position: absolute; + top: 0; + left: 0; + margin: 1ex 1ex 1ex 1ex; + text-shadow: 2px 2px 6px rgba(0, 0, 0, 1); +} +.camera > ul > li:hover span.infos { + display:inline; +} + +.camera > ul > li span.links { + display:none; + font-size: 0.8rem; + font-weight: normal; + color: #fff; + position: absolute; + top: 0; + right: 0; + margin: 1ex 1ex 1ex 1ex; + text-decoration: none; + flex-direction: column; +} +.camera > ul > li:hover span.links { + display:flex; +} +.camera > ul > li span.links > a { + color: inherit; + text-decoration: none; +} diff --git a/index.sh b/index.sh new file mode 100755 index 0000000..c1b16b5 --- /dev/null +++ b/index.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2086 +# License: AGPL3+ +cd "${0%/*}" +set -eu +shopt -s nullglob + +ffmpeg_ () { local -; set -x; nice -19 ffmpeg &2 "$@"; } + +user=$(realpath --relative-to .. .) +declare -a years=${years:-$(find * -maxdepth 0 -type d -not -name ".*")} +for year in ${years[@]}; do + pushd "$year" >/dev/null + test -d src || { popd; continue; } + mkdir -p fav + ln -sf -t fav ../../index.css + declare -a months=${months:-(01 02 03 04 05 06 07 08 09 10 11 12)} + for month in ${months[@]}; do + test -d src/"$month" || { popd; continue; } + mkdir -p fav/"$month" + mkdir -p {tmp,wip}/fav/"$month" + { + genDate=$(date +%s) + cat < + + + + + + + camera/$user/$year/$month + + + + + + + +
+
    +EOF + echo >&2 "$year/$month: processing favorites in chronological order" + # Time is encoded in filenames like so: MM/{IMG,VID}_YYYYMMDD_hhmmss.* + # hence sorting after the underscore (2nd field, 5th char). + (cd src; find "$month" -name '*.fav.*' -not -name "*.txt") | sort -n -t/ -k2.5 | + while read -r src; do + echo >&2 "$year/$month: processing $year/src/$src" + base=${src%.*} + name=${base##*/} + id=${name%%.*} + creationDate=$(printf %s "${src##*/???_}" | sed -e 's/\(....\)\(..\)\(..\)_\(..\)\(..\)\(..\).*/\1-\2-\3 \4:\5:\6/') + echo "
  • " + test -e fav/"$base".uuid || + uuidgen --random >fav/"$base".uuid + uuid=$(cat fav/"$base".uuid) + mkdir -p fav/"$month"/by-uuid/"$uuid" + case "$src" in + *.jpg) + echo "" + printf "" + w=600 + test fav/"$base"."$w"x.avif -nt src/"$src" || { + magick_ -define jpeg:size=$((w * 2))x src/"$src" \ + -sampling-factor 4:2:0 -interlace JPEG -colorspace sRGB \ + -auto-orient -thumbnail "$w"x -unsharp 0x.5 \ + fav/"$base"."$w"x.jpg + } + echo "" + echo "$creationDate" + echo "" + dst="$name".1200x.avif + ln -fs -t fav/"$month"/by-uuid/"$uuid" ../../"$dst" + ;; + *.mp4) + test fav/"$base".avif -nt src/"$src" || { + ffmpeg_ -i src/"$src" \ + -map 0:v \ + -filter:v format=yuv420p,scale='trunc(oh*a/2)*2:360' \ + -frames:v 1 -crf 40 \ + wip/fav/"$base".avif + mv_ {wip/,}fav/"$base".avif + } + need_opus () { + test tmp/fav/"$base".opus -nt src/"$src" || { + ffmpeg_ -i src/"$src" \ + -map 0:a -c:a libopus -b:a 64k -application voip \ + wip/fav/"$base".opus + mv_ {wip,tmp}/fav/"$base".opus + } + } + test fav/"$base".360p.av1.webm -nt src/"$src" || { + need_opus + ffmpeg_ -i src/"$src" -i tmp/fav/"$base".opus \ + -map 0:v \ + -filter:v format=yuv420p,scale='trunc(oh*a/2)*2:360' \ + -c:v libsvtav1 -crf 40 -g 120 \ + -map 1:a -c:a copy \ + wip/fav/"$base".360p.av1.webm + # -i fav/"$base".avif -map 1 \ + # -c:v:1 jpeg -disposition:v:1 attached_pic \ + mv_ {wip/,}fav/"$base".360p.av1.webm + } + dst="$name".360p.av1.webm + ln -fs -t fav/"$month"/by-uuid/"$uuid" ../../"$dst" + #test fav/"$base".360p.vp9.webm -nt src/"$src" || { + # need_opus + # # See https://developers.google.com/media/vp9/settings/vod#recommended_settings + # # See https://gist.github.com/mrintrepide/3033c35ee9557e66cff7806f48dbd339 + # set -- \ + # -filter:v format=yuv420p,scale='trunc(oh*a/2)*2:360' \ + # -c:v libvpx-vp9 -quality good -crf 20 \ + # -minrate 138k -b:v 276k -maxrate 400k \ + # -cpu-used 4 -static-thresh 0 -tile-columns 0 -tile-rows 0 -frame-parallel 0 \ + # -row-mt 1 -aq-mode 0 -auto-alt-ref 6 -lag-in-frames 25 -enable-tpl 1 + # test -e tmp/fav/"$base".360p.vp9.webm-0.log || { + # # FIXME: how to disable h264 debug log? + # ffmpeg 2>/dev/null -i src/"$src" \ + # -map 0:v "$@" -pass 1 -passlogfile wip/fav/"$base".360p.vp9.webm \ + # -f null \ + # /dev/null + # mv_ -t tmp/fav/"${base%/*}" wip/fav/"$base".360p.vp9.webm-*.log + # } + # ffmpeg -i src/"$src" -i tmp/fav/"$base".opus \ + # -map 0:v "$@" -pass 2 -passlogfile tmp/fav/"$base".360p.vp9.webm \ + # -map 1:a -c:a copy \ + # wip/fav/"$base".360p.vp9.webm + # mkdir -p fav/"$month"/by-uuid/"$uuid" + # mv_ wip/fav/"$base".360p.vp9.webm fav/"$base".360p.vp9.webm + # rm -fv tmp/fav/"$base".360p.vp9.webm-*.log + #} + #test fav/"$base".mp4 -nt src/"$src" || { + # ffmpeg -i src/"$src" \ + # -filter:v format=yuv420p \ + # -c:v libx264 -preset medium -crf 22 \ + # -tune zerolatency \ + # -maxrate 1M -bufsize 2M \ + # -movflags use_metadata_tags +faststart \ + # -c:a libopus -base:a 64k -application voip \ + # -filter:v "scale=iw/2:ih/2" \ + # wip/fav/"$base".mp4 + # mv_ wip/fav/"$base".mp4 fav/"$base".mp4 + #} + #orient=$(ffprobe -v 0 -select_streams v:0 -show_entries stream_side_data=rotation -of default=nw=1:nk=1 src/"$src") + # class='orient$orient' + echo "" + esac + touch -a src/"$base".txt + printf %s "" + sed -e '$q;s/$/
    \n/' src/"$base".txt + echo "
    " + echo "
    " + echo "" + echo " $creationDate" + echo "" + echo "" + echo " #" + echo " @" + echo "" + echo "
  • " + echo + done + cat < +
+ + + +EOF + } >tmp/fav/"$month"/index.html + mv_ -f {tmp/,}fav/"$month"/index.html + + echo >&2 "$year/$month: remove any deleted favorites" + (cd fav; find "$month" -mindepth 1 -type f -not -name index.html) | + while read -r fav; do + base=${fav%.fav.*} + name=${base##*/} + unset hasSrc + for src in src/"$base".fav.*; do test "${src%.txt}" != "$src" || hasSrc=set; done + test "${hasSrc:+set}" || { + echo >&2 "$year/$month: removing $year/fav/$fav" + rm -f fav/"$fav" + rm -f fav/"$month"/by-uuid/*/"${name%.*}".* + } + done + rmdir -p 2>/dev/null fav/"$month"/by-uuid/*/ || true + done + popd >/dev/null +done +rmdir 2>/dev/null -p wip/fav/* || true diff --git a/pull.sh b/pull.sh new file mode 100755 index 0000000..ea84f3f --- /dev/null +++ b/pull.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +host=Xiaomi_SDM439-QRD__SN%3AB0796589_c7565cf60006 +cd "${0%/*}" +set -eux +gio mount -l | grep mtp://"$host" || +gio mount mtp://"$host"/"Carte SD SanDisk"/ + +year=$(date +%Y) +mkdir -p "$year"/audio/src +rsync -ai --no-inc-recursive --info=progress2 --inplace --partial \ + --remove-source-files \ + /run/user/"$(id -u)"/gvfs/mtp:host="$host"/"Espace de stockage interne partagé"/MIUI/sound_recorder \ + "$year"/audio/src/ + +# FIXME: handle previous year on new year +mkdir -p "$year"/src +for month in {01..12}; do + rsync -ai --no-inc-recursive --info=progress2 --inplace --partial \ + --remove-source-files \ + --include "???_$year$month*" --exclude '*' \ + /run/user/"$(id -u)"/gvfs/mtp:host="$host"/"Espace de stockage interne partagé"/DCIM/Camera/ \ + /run/user/"$(id -u)"/gvfs/mtp:host="$host"/"Carte SD SanDisk"/DCIM/Camera/ \ + "$year"/src/"$month" +done diff --git a/push.sh b/push.sh new file mode 100755 index 0000000..67c08b4 --- /dev/null +++ b/push.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +cd "${0%/*}" +set -eu +shopt -s nullglob + +year=$(date +%Y) +test $# -gt 0 || +set -- "$year"/fav/ + +rsync -ai --no-inc-recursive --info=progress2 --inplace --partial \ + --copy-links --exclude "*.vp9.webm" --exclude "*.opus" --delete --delete-after \ + "$@" \ + mermet.wg:/var/lib/nginx/autogeree.net/julm/perso/camera/"$year"/ -- 2.47.0