]>
Git — Sourcephile - julm/camera.git/blob - index.sh
2 # Copyright: Julien Moutinho <julm+camera@sourcephile.fr>
3 # License: AGPL-3.0-or-later
5 # $ mv julm/2023/src/02/IMG_20230228_111645{,.fav}.jpg
6 # $ echo >julm/2023/src/02/IMG_20230228_111645.fav.txt "Some HTML <b>comment</b> about the picture"
7 # $ ./index.sh julm/2023/src/02
8 # $ sensible-browser julm/2023/fav/02/index.html
11 # locations."/julm/perso/camera/" = {
12 # alias = "${root}/julm/perso/camera/";
13 # basicAuthFile = "/run/credentials/nginx.service/autogeree.net.www.julm.perso.camera.htpasswd";
15 # # Disable basicAuthFile for by-uuid
16 # locations."~ ^/julm/perso/camera/([0-9]+/[0-9][0-9]/by-uuid/[0-9a-f-]+/.+)$" = {
17 # alias = "${root}/julm/perso/camera/$1";
20 # shellcheck disable=SC2086
26 ffmpeg_
() { local -; set -x ; nice
-19 time ffmpeg
</ dev
/ null
-hide_banner -loglevel warning
-stats -y "$@" ; }
27 magick_
() { local -; set -x ; nice
-19 magick
"$@" ; }
28 mv_
() { local -; mv -i >& 2 "$@" ; }
31 IFS
=/ read -r user year x month x
<<< " $dir "
32 test -n " $year " || exec " $0 " " $user " / 2 */ src
/*/
33 test -n " $month " || exec " $0 " " $user " / " $year " / src
/*/
34 pushd " $user / $year " >/ dev
/ null
35 test -d src
|| { popd ; continue ; }
37 # cp, not ln, because in push.sh --copy-links cannot be used for by-uuid/
38 cp -f --remove-destination -t fav ..
/ ..
/ index.css
39 test -d src
/ " $month " || { popd ; continue ; }
46 <!-- Generator: https://git.sourcephile.fr/julm/camera.git -->
47 <!-- GenerationDate: $(date -R -d@"$genDate") -->
51 <meta charset="utf-8">
52 <title>camera/ $user / $year / $month </title>
53 <link rel="stylesheet" href="../index.css? $genDate ">
59 <a href='../../..'>camera</a>/ <a href='../..'> $user </a>/ <a href='..'> $year </a>/
62 if [ " $m " -eq 01 ]; then printf '{ ' ; fi
63 if [ " $m " -eq " $month " ]; then
66 printf % s
"<a href='../ $m '> $m </a>"
68 if [ " $m " -eq 12 ]; then printf ' }' ; else printf ', ' ; fi
76 echo >& 2 " $dir : processing favorites in chronological order"
77 # Time is encoded in filenames like so: {IMG,VID}_YYYYMMDD_hhmmss.*
78 # hence sorting after the underscore (1st field, 5th char).
79 # To support subdirectories, sorting is done on the prefix %f
80 # which is replaced by %p thereafter.
81 ( cd src
; find -L " $month " -name '*.fav.*' -not -name "*.txt" -printf '%f %p \n ' ) | sort -t / -k1 .5
| cut
-f2 -d ' ' |
83 echo >& 2 " $dir : processing $year /src/ $src "
87 creationDate
= $(printf %s "${src##*/???_}" | sed -e 's/\(....\) \
( ..\
) \
( ..\
) _\
( ..\
) \
( ..\
) \
( ..\
) .
*/ \
1 - \
2 - \
3 \
4 : \
5 : \
6 / ')
88 creationDoM= $(date +'%A %_d %B' -d "$creationDate")
89 if test " $creationDoM " != " ${creationDoMOld-} "; then
90 dom= $(date +'%d' -d "$creationDate")
91 echo "<li id=' $dom ' class=' day
'><div>"
92 echo "<a class=' day
-current ' href=' #$dom'>$creationDoM</a>"
94 test ! " ${creationDateOld:+set} " ||
95 echo "<a class='day-previous' href='# $(date +'%d' -d "$creationDateOld") '>^</a>"
98 creationDoMOld
= $creationDoM
99 creationDateOld
= $creationDate
101 test -e fav
/ " $base " .uuid
||
102 uuidgen
--random > fav
/ " $base " .uuid
103 uuid
= $(cat fav/"$base".uuid)
104 mkdir -p fav
/ " ${base%/*} "
105 mkdir -p { tmp
, wip
}/ fav
/ " ${base%/*} "
106 mkdir -p fav
/ " $month " / by
-uuid / " $uuid "
108 test " ${src##*.wow.} " = " ${src} " || wow
= wow
111 echo "<li id=' $id ' class=' $wow '><div class='item'>"
113 printf "<source type='image/avif' srcset='"
114 for w
in { 1200 , 600 , 300 }; do
115 test fav
/ " $base " .
" $w " x.avif
-nt src
/ " $src " || {
117 -sampling-factor 4 : 2 : 0 -colorspace sRGB \
118 -auto-orient -thumbnail " $w " x
-unsharp 0 x
.5 \
119 wip
/ fav
/ " $base " .
" $w " x.avif
120 mv_
{ wip
/,} fav
/ " $base " .
" $w " x.avif
122 printf % s
" $name . ${w} x.avif ${w} w, "
126 test fav
/ " $base " .
" $w " x.jpg
-nt src
/ " $src " || {
127 magick_
-define jpeg
: size
= $((w * 2) ) x src
/ " $src " \
128 -sampling-factor 4 : 2 : 0 -interlace JPEG
-colorspace sRGB \
129 -auto-orient -thumbnail " $w " x
-unsharp 0 x
.5 \
130 wip
/ fav
/ " $base " .
" $w " x.jpg
131 mv_
{ wip
/,} fav
/ " $base " .
" $w " x.jpg
133 echo "<source type='image/jpeg' srcset=' $name . ${w} x.jpg ${w} w' />"
134 echo "<img src=' $name . ${w} x.jpg' alt=' $creationDate ' />"
136 dst
= " $name " .1200 x.avif
137 ln -fs -t fav
/ " $month " / by
-uuid / " $uuid " ..
/ ..
/ " $dst "
140 # Slow, but needed to make wide videos span two columns of the CSS grid
141 orient
= $(ffprobe -v 0 -select_streams v:0 -show_entries stream_side_data=rotation -of default=nw=1:nk=1 src/"$src")
142 if [ -z " $orient " ]; then scale
= "-2:360" ; else scale
= "360:-2" ; fi
143 echo "<li id=' $id ' class=' $wow vid-orient- $orient '><div class='item'>"
144 test fav
/ " $base " .avif
-nt src
/ " $src " || {
145 ffmpeg_
-i src
/ " $src " \
147 -filter : v format
= yuv420p10le
, scale
= " $scale " \
148 -frames : v
1 -crf 33 \
150 mv_
{ wip
/,} fav
/ " $base " .avif
153 test tmp
/ fav
/ " $base " .opus
-nt src
/ " $src " || {
154 ffmpeg_
-i src
/ " $src " \
155 -map 0 : a
-c : a libopus
-b : a
64 k
-application voip \
157 mv_
{ wip
, tmp
}/ fav
/ " $base " .opus
160 test fav
/ " $base " .360 p.av1.webm
-nt src
/ " $src " || {
162 ffmpeg_
-i src
/ " $src " -i tmp
/ fav
/ " $base " .opus \
164 -filter : v format
= yuv420p
, scale
= " $scale " \
165 -c : v libsvtav1
-preset 10 -crf 33 \
166 -svtav1-params input
-depth = 8 : keyint
= 10 s
: tune
= 0 : enable-overlays = 1 : scd
= 1 : scm
= 0 : fast
-decode = 1 : film
-grain = 10 \
168 wip
/ fav
/ " $base " .360 p.av1.webm
169 mv_
{ wip
/,} fav
/ " $base " .360 p.av1.webm
171 dst
= " $name " .360 p.av1.webm
172 ln -fs -t fav
/ " $month " / by
-uuid / " $uuid " ..
/ ..
/ " $dst "
173 #test fav/"$base".360p.vp9.webm -nt src/"$src" || {
175 # # See https://developers.google.com/media/vp9/settings/vod#recommended_settings
176 # # See https://gist.github.com/mrintrepide/3033c35ee9557e66cff7806f48dbd339
178 # -filter:v format=yuv420p10le,scale="$scale" \
179 # -c:v libvpx-vp9 -quality good -crf 20 \
180 # -minrate 138k -b:v 276k -maxrate 400k \
181 # -cpu-used 4 -static-thresh 0 -tile-columns 0 -tile-rows 0 -frame-parallel 0 \
182 # -row-mt 1 -aq-mode 0 -auto-alt-ref 6 -lag-in-frames 25 -enable-tpl 1
183 # test -e tmp/fav/"$base".360p.vp9.webm-0.log || {
184 # # FIXME: how to disable h264 debug log?
185 # ffmpeg 2>/dev/null -i src/"$src" \
186 # -map 0:v "$@" -pass 1 -passlogfile wip/fav/"$base".360p.vp9.webm \
189 # mv_ -t tmp/fav/"${base%/*}" wip/fav/"$base".360p.vp9.webm-*.log
191 # ffmpeg -i src/"$src" -i tmp/fav/"$base".opus \
192 # -map 0:v "$@" -pass 2 -passlogfile tmp/fav/"$base".360p.vp9.webm \
193 # -map 1:a -c:a copy \
194 # wip/fav/"$base".360p.vp9.webm
195 # mkdir -p fav/"$month"/by-uuid/"$uuid"
196 # mv_ wip/fav/"$base".360p.vp9.webm fav/"$base".360p.vp9.webm
197 # rm -fv tmp/fav/"$base".360p.vp9.webm-*.log
199 #test fav/"$base".mp4 -nt src/"$src" || {
200 # ffmpeg -i src/"$src" \
201 # -filter:v format=yuv420p \
202 # -c:v libx264 -preset medium -crf 22 \
203 # -tune zerolatency \
204 # -maxrate 1M -bufsize 2M \
205 # -movflags use_metadata_tags +faststart \
206 # -c:a libopus -base:a 64k -application voip \
207 # -filter:v "scale=iw/2:ih/2" \
208 # wip/fav/"$base".mp4
209 # mv_ wip/fav/"$base".mp4 fav/"$base".mp4
211 # class='orient$orient'
212 echo "<video controls preload=none poster=' $name .avif'>"
213 # See https://jakearchibald.com/2022/html-codecs-parameter-for-av1/
214 # and ffmpeg -i fav/$month/foo.av1.webm -c:v copy -bsf:v trace_headers -f null /dev/null |&
215 # grep -e seq_profile -e seq_level_idx -e seq_tier -e high_bitdepth -e twelve_bit
216 P
= 0 ; LL
= 01 ; T
= M
; DD
= 08
217 echo "<source type='video/webm; codecs=av01. $P . $LL $T . $DD ' src=' $name .360p.av1.webm' />"
218 echo "<p><a href=' $name .360p.av1.webm'> $name .360p.av1.webm</a></p>"
222 # Slow, but needed to make wide videos span two columns of the CSS grid
223 orient
= $(ffprobe -v 0 -select_streams v:0 -show_entries stream_side_data=rotation -of default=nw=1:nk=1 src/"$src")
224 if [ -z " $orient " ]; then scale
= "-2:360" ; else scale
= "360:-2" ; fi
225 echo "<li id=' $id ' class=' $wow vid-orient- $orient '><div class='item'>"
226 test fav
/ " $base " .avif
-nt src
/ " $src " || {
227 ffmpeg_
-i src
/ " $src " \
229 -filter : v format
= yuv420p10le
, scale
= " $scale " \
230 -frames : v
1 -crf 33 \
232 mv_
{ wip
/,} fav
/ " $base " .avif
234 test fav
/ " $base " .webm
-nt src
/ " $src " || {
235 ln -f { src
, fav
}/ " $base " .webm
238 ln -fs -t fav
/ " $month " / by
-uuid / " $uuid " ..
/ ..
/ " $dst "
239 echo "<video controls preload=none poster=' $name .avif'>"
240 # See https://jakearchibald.com/2022/html-codecs-parameter-for-av1/
241 # and ffmpeg -i fav/$month/foo.av1.webm -c:v copy -bsf:v trace_headers -f null /dev/null |&
242 # grep -e seq_profile -e seq_level_idx -e seq_tier -e high_bitdepth -e twelve_bit
243 P
= 0 ; LL
= 01 ; T
= M
; DD
= 08
244 echo "<source type='video/webm; codecs=av01. $P . $LL $T . $DD ' src=' $name .webm' />"
245 echo "<p><a href=' $name .webm'> $name .webm</a></p>"
248 touch -a src
/ " $base " .txt
249 printf % s
"<span class='comment'>"
250 sed -e ' $q ;s/$/<br \/> \n /' src
/ " $base " .txt
252 echo "</div>" # class='item'
253 echo "<span class='infos'>"
254 echo " <span class='creationDate'> $creationDate </span>"
256 echo "<span class='links'>"
257 echo " <a class='by-uuid' href='https://autogeree.net/julm/perso/camera/ $year / $month /by-uuid/ $uuid / ${dst##*/} ' title='Lien public vers cette capture' target='_blank'>@</a>"
258 echo " <a class='anchor' href='# $id ' title='Ancre vers cette capture'>#</a>"
260 echo "<span class='downloads'>"
261 echo " <a class='download' href=' ${dst##*/} ' title='Enregistrer cette capture'>Enregistrer</a>"
273 } > tmp
/ fav
/ " $month " / index.html
274 mv_
-f { tmp
/,} fav
/ " $month " / index.html
276 echo >& 2 " $dir : removing any deleted favorites"
277 ( cd fav
; find -L " $month " -mindepth 1 -not -path '*/by-uuid/*' -type f
-not -name index.html
) |
278 while read -r fav
; do
280 base
= ${base%.300x.avif}
281 base
= ${base%.600x.avif}
282 base
= ${base%.600x.jpg}
283 base
= ${base%.1200x.avif}
285 base
= ${base%.360p.av1.webm}
290 for src
in src
/ " $base " .???
; do hasSrc
= set ; done
291 test " ${hasSrc:+set} " || {
292 echo >& 2 " $dir : removing $year /fav/ $fav "
294 rm -f fav
/ " $month " / by
-uuid /*/ " $name " .
{ 1200 x.avif
, avif
, 360 p.av1.webm
, webm
, uuid
}
297 rmdir -p 2 >/ dev
/ null fav
/ " $month " / by
-uuid /*/ || true
298 rmdir -p 2 >/ dev
/ null wip
/ fav
/* || true