]>
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 ; }
42 mkdir -p tmp
/ fav
/ " $month "
47 <!-- Generator: https://git.sourcephile.fr/julm/camera.git -->
48 <!-- GenerationDate: $(date -R -d@"$genDate") -->
52 <meta charset="utf-8">
53 <title>camera/ $user / $year / $month </title>
54 <link rel="stylesheet" href="../index.css? $genDate ">
60 <a href='../../..'>camera</a>/ <a href='../..'> $user </a>/ <a href='..'> $year </a>/
63 if [ " $m " -eq 01 ]; then printf '{ ' ; fi
64 if [ " $m " -eq " $month " ]; then
67 printf % s
"<a href='../ $m '> $m </a>"
69 if [ " $m " -eq 12 ]; then printf ' }' ; else printf ', ' ; fi
77 echo >& 2 " $dir : processing favorites in chronological order"
79 # Time is encoded in filenames like so: {IMG,VID}_YYYYMMDD_hhmmss.*
80 # hence sorting after the underscore (1st field, 5th char).
81 # To support subdirectories, sorting is done on the prefix %f
82 # which is replaced by %p thereafter.
83 ( cd src
; find -L " $month " -name '*.fav.*' -not -name "*.txt" -printf '%f %p \n ' ) | sort -t / -k1 .5
| cut
-f2 -d ' ' |
85 echo >& 2 " $dir : processing $year /src/ $src "
89 creationDate
= $(printf %s "${src##*/???_}" | sed -e 's/\(....\) \
( ..\
) \
( ..\
) _\
( ..\
) \
( ..\
) \
( ..\
) .
*/ \
1 - \
2 - \
3 \
4 : \
5 : \
6 / ')
90 creationDoM= $(date +'%A %_d %B' -d "$creationDate")
91 if test " $creationDoM " != " ${creationDoMOld-} "; then
92 dom= $(date +'%d' -d "$creationDate")
93 echo "<li id=' $dom ' class=' day
'><div>"
94 echo "<a class=' day
-current ' href=' #$dom'>$creationDoM</a>"
96 test ! " ${creationDateOld:+set} " ||
97 echo "<a class='day-previous' href='# $(date +'%d' -d "$creationDateOld") '>^</a>"
100 creationDoMOld
= $creationDoM
101 creationDateOld
= $creationDate
103 mkdir -p fav
/ " ${base%/*} "
104 mkdir -p { tmp
, wip
}/ fav
/ " ${base%/*} "
105 test -e fav
/ " $base " .uuid
||
106 uuidgen
--random > fav
/ " $base " .uuid
107 uuid
= $(cat fav/"$base".uuid)
108 mkdir -p fav
/ " $month " / by
-uuid / " $uuid "
110 test " ${src##*.wow.} " = " ${src} " || wow
= wow
112 # Slow, but needed to make wide videos span two columns of the CSS grid
113 IFS
= ' ' read -r width height rotation
<<< " $(ffprobe -v error -select_streams v:0 -show_entries stream=width,height:stream_side_data=rotation -of csv=p=0:s='\ ' src/"$src") "
115 ( 90 | -90 ) w
= $width ; width
= $height ; height
= $w ;;
117 if [ " $width " -gt " $height " ]
118 then scale
= "-2:360" ; orient
= "landscape"
119 else scale
= "360:-2" ; orient
= "portrait"
125 echo "<li id=' $id ' class=' $wow '><div class='item'>"
127 printf "<source type='image/avif' srcset='"
128 for w
in { 1200 , 600 , 300 }; do
129 test fav
/ " $base " .
" $w " x.avif
-nt src
/ " $src " || {
131 -sampling-factor 4 : 2 : 0 -colorspace sRGB \
132 -auto-orient -thumbnail " $w " x
-unsharp 0 x
.5 \
133 wip
/ fav
/ " $base " .
" $w " x.avif
134 mv_
-f { wip
/,} fav
/ " $base " .
" $w " x.avif
136 printf % s
" $name . ${w} x.avif ${w} w, "
140 test fav
/ " $base " .
" $w " x.jpg
-nt src
/ " $src " || {
141 magick_
-define jpeg
: size
= $((w * 2) ) x src
/ " $src " \
142 -sampling-factor 4 : 2 : 0 -interlace JPEG
-colorspace sRGB \
143 -auto-orient -thumbnail " $w " x
-unsharp 0 x
.5 \
144 wip
/ fav
/ " $base " .
" $w " x.jpg
145 mv_
-f { wip
/,} fav
/ " $base " .
" $w " x.jpg
147 echo "<source type='image/jpeg' srcset=' $name . ${w} x.jpg ${w} w' />"
148 echo "<img src=' $name . ${w} x.jpg' alt=' $creationDate ' />"
150 dst
= " $name " .1200 x.jpg
151 ln -fs -t fav
/ " $month " / by
-uuid / " $uuid " ..
/ ..
/ " $dst "
155 echo "<li id=' $id ' class=' $wow vid-orient- $orient '><div class='item'>"
156 test fav
/ " $base " .avif
-nt src
/ " $src " || {
157 ffmpeg_
-i src
/ " $src " \
159 -filter : v format
= yuv420p10le
, scale
= " $scale " \
160 -frames : v
1 -crf 33 \
162 mv_
-f { wip
/,} fav
/ " $base " .avif
165 test tmp
/ fav
/ " $base " .opus
-nt src
/ " $src " || {
166 ffmpeg_
-i src
/ " $src " \
167 -map 0 : a
-c : a libopus
-b : a
64 k
-application voip \
169 mv_
-f { wip
, tmp
}/ fav
/ " $base " .opus
172 test fav
/ " $base " .360 p.av1.webm
-nt src
/ " $src " || {
174 ffmpeg_
-i src
/ " $src " -i tmp
/ fav
/ " $base " .opus \
176 -filter : v format
= yuv420p
, scale
= " $scale " \
177 -c : v libsvtav1
-preset 10 -crf 33 \
178 -svtav1-params input
-depth = 8 : keyint
= 10 s
: tune
= 0 : enable-overlays = 1 : scd
= 1 : scm
= 0 : fast
-decode = 1 \
180 wip
/ fav
/ " $base " .360 p.av1.webm
181 mv_
-f { wip
/,} fav
/ " $base " .360 p.av1.webm
183 dst
= " $name " .360 p.av1.webm
184 ln -fs -t fav
/ " $month " / by
-uuid / " $uuid " ..
/ ..
/ " $dst "
185 #test fav/"$base".360p.vp9.webm -nt src/"$src" || {
187 # # See https://developers.google.com/media/vp9/settings/vod#recommended_settings
188 # # See https://gist.github.com/mrintrepide/3033c35ee9557e66cff7806f48dbd339
190 # -filter:v format=yuv420p10le,scale="$scale" \
191 # -c:v libvpx-vp9 -quality good -crf 20 \
192 # -minrate 138k -b:v 276k -maxrate 400k \
193 # -cpu-used 4 -static-thresh 0 -tile-columns 0 -tile-rows 0 -frame-parallel 0 \
194 # -row-mt 1 -aq-mode 0 -auto-alt-ref 6 -lag-in-frames 25 -enable-tpl 1
195 # test -e tmp/fav/"$base".360p.vp9.webm-0.log || {
196 # # FIXME: how to disable h264 debug log?
197 # ffmpeg 2>/dev/null -i src/"$src" \
198 # -map 0:v "$@" -pass 1 -passlogfile wip/fav/"$base".360p.vp9.webm \
201 # mv_ -t tmp/fav/"${base%/*}" wip/fav/"$base".360p.vp9.webm-*.log
203 # ffmpeg -i src/"$src" -i tmp/fav/"$base".opus \
204 # -map 0:v "$@" -pass 2 -passlogfile tmp/fav/"$base".360p.vp9.webm \
205 # -map 1:a -c:a copy \
206 # wip/fav/"$base".360p.vp9.webm
207 # mkdir -p fav/"$month"/by-uuid/"$uuid"
208 # mv_ wip/fav/"$base".360p.vp9.webm fav/"$base".360p.vp9.webm
209 # rm -fv tmp/fav/"$base".360p.vp9.webm-*.log
211 #test fav/"$base".mp4 -nt src/"$src" || {
212 # ffmpeg -i src/"$src" \
213 # -filter:v format=yuv420p \
214 # -c:v libx264 -preset medium -crf 22 \
215 # -tune zerolatency \
216 # -maxrate 1M -bufsize 2M \
217 # -movflags use_metadata_tags +faststart \
218 # -c:a libopus -base:a 64k -application voip \
219 # -filter:v "scale=iw/2:ih/2" \
220 # wip/fav/"$base".mp4
221 # mv_ wip/fav/"$base".mp4 fav/"$base".mp4
223 # class='orient$orient'
224 echo "<video controls preload=none poster=' $name .avif'>"
225 # See https://jakearchibald.com/2022/html-codecs-parameter-for-av1/
226 # and ffmpeg -i fav/$month/foo.av1.webm -c:v copy -bsf:v trace_headers -f null /dev/null |&
227 # grep -e seq_profile -e seq_level_idx -e seq_tier -e high_bitdepth -e twelve_bit
228 P
= 0 ; LL
= 01 ; T
= M
; DD
= 08
229 echo "<source type='video/webm; codecs=av01. $P . $LL $T . $DD ' src=' $name .360p.av1.webm' />"
230 echo "<p><a href=' $name .360p.av1.webm'> $name .360p.av1.webm</a></p>"
235 echo "<li id=' $id ' class=' $wow vid-orient- $orient '><div class='item'>"
236 test fav
/ " $base " .avif
-nt src
/ " $src " || {
237 ffmpeg_
-i src
/ " $src " \
239 -filter : v format
= yuv420p10le
, scale
= " $scale " \
240 -frames : v
1 -crf 33 \
242 mv_
-f { wip
/,} fav
/ " $base " .avif
244 test fav
/ " $base " .webm
-nt src
/ " $src " || {
245 ln -f { src
, fav
}/ " $base " .webm
248 ln -fs -t fav
/ " $month " / by
-uuid / " $uuid " ..
/ ..
/ " $dst "
249 echo "<video controls preload=none poster=' $name .avif'>"
250 # See https://jakearchibald.com/2022/html-codecs-parameter-for-av1/
251 # and ffmpeg -i fav/$month/foo.av1.webm -c:v copy -bsf:v trace_headers -f null /dev/null |&
252 # grep -e seq_profile -e seq_level_idx -e seq_tier -e high_bitdepth -e twelve_bit
253 P
= 0 ; LL
= 01 ; T
= M
; DD
= 08
254 echo "<source type='video/webm; codecs=av01. $P . $LL $T . $DD ' src=' $name .webm' />"
255 echo "<p><a href=' $name .webm'> $name .webm</a></p>"
259 echo >& 2 "ERROR: unsupported format: $src "
263 touch -a src
/ " $base " .txt
264 printf % s
"<span class='comment'>"
265 sed -e ' $q ;s/$/<br \/> \n /' src
/ " $base " .txt
267 echo "</div>" # class='item'
268 echo "<span class='infos'>"
269 echo " <span class='creationDate'> $creationDate </span>"
271 echo "<span class='links'>"
272 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>"
273 echo " <a class='anchor' href='# $id ' title='Ancre vers cette capture'>#</a>"
275 echo "<span class='downloads'>"
276 echo " <a class='download' href=' ${dst##*/} ' title='Enregistrer cette capture'>Enregistrer</a>"
288 } > tmp
/ fav
/ " $month " / index.html
289 mv_
-f { tmp
/,} fav
/ " $month " / index.html
291 echo >& 2 " $dir : removing any deleted favorites"
292 ( cd fav
; find -L " $month " -mindepth 1 -not -path '*/by-uuid/*' -type f
-not -name index.html
) |
293 while read -r fav
; do
295 base
= ${base%.300x.avif}
296 base
= ${base%.600x.avif}
297 base
= ${base%.1200x.avif}
298 base
= ${base%.1200x.jpg}
300 base
= ${base%.360p.av1.webm}
305 for src
in src
/ " $base " .???
; do hasSrc
= set ; done
306 test " ${hasSrc:+set} " || {
307 echo >& 2 " $dir : removing $year /fav/ $fav "
309 rm -f fav
/ " $month " / by
-uuid /*/ " $name " .
*
312 rmdir -p 2 >/ dev
/ null fav
/ " $month " / by
-uuid /*/ || true
313 rmdir -p 2 >/ dev
/ null wip
/ fav
/* || true