Static photo albums with llgal
This commit is contained in:
162
llgal.org
Normal file
162
llgal.org
Normal file
@ -0,0 +1,162 @@
|
||||
#+TITLE: Static photo albums with llgal
|
||||
#+DATE: 2023-01-29
|
||||
* Prologue
|
||||
I used to create photo albums on [[https://flickr.com/photos/tlakh/][flickr]] for our vacations. I even had
|
||||
a paid pro account for a few years. While I have backups of all my
|
||||
photos, it still felt off to show these albums using somebody else's
|
||||
computer. They might disappear any day. Since I have the storage
|
||||
capacity and some time to waste I set out to self-host photo albums.
|
||||
* Nextcloud Photos
|
||||
My first layer of photo backups is a self-hosted [[https://nextcloud.com/][Nextcloud]]. I am using
|
||||
the Nextcloud android app to automatically upload pictures when on
|
||||
WiFi. So I might as well use the built-in Nextcloud Photos 2.0[fn::Why
|
||||
is there not way to link to a description of this thing? There is a
|
||||
GitHub page and it's described on [[https://nextcloud.com/athome/][https://nextcloud.com/athome/]] but
|
||||
you can't direct-link to it‽].
|
||||
|
||||
Unfortunately it's not quite there yet. In increasing order of
|
||||
annoyance:
|
||||
1) Video buffering is not a thing.
|
||||
2) Videos do not get a preview image.
|
||||
3) It is very confused about ordering. The order in the photo app is
|
||||
correct but when added to the gallery sometimes two photos switch
|
||||
places. There is some mumbling about mtime vs. ctime vs. exiff data
|
||||
in some forum, but that's not the problem here. First of all, no
|
||||
matter how Nextcloud sorts the picture it would always arrive at
|
||||
the same ordering. I did not edit the photos, so mtime and ctime
|
||||
are the same. But also note that the order in the photo app is
|
||||
correct. It only gets confused when photos are added to an
|
||||
album. The photo album tells a story. It is really bad if the
|
||||
"arrival at home" photo is shown before the "last night of the
|
||||
vacation" photo.
|
||||
4) The absolute deal-breaker is that it does not work though. The
|
||||
whole idea is to share a link to the album for anonymous users. You
|
||||
can do that, and it shows you the album with thumbnails. But as
|
||||
soon as you click on a photo or start the slide show it wants you
|
||||
to login. I suspect you need to enable sharing via link to every
|
||||
photo in the album to make it work. There does not seem to be a way
|
||||
to do this in bulk so I did not try it. I have also found a
|
||||
discussion online where people argue for years along the lines of
|
||||
"it does not work" - "yes it does" - "no it does not". That was
|
||||
tiresome and they are still going on. There was some mumbling that
|
||||
you need to enable federation in Nextcloud to make anonymous albums
|
||||
work, but I have that on and it still does not work.
|
||||
* llgal
|
||||
I then remembered that I had used a static photo album generator
|
||||
before: [[http://bgoglin.free.fr/llgal/][llgal]]. But I never tried to make it "pretty" or convert all my
|
||||
flickr albums to it.
|
||||
** Setup
|
||||
llgal is in OpenBSD ports, so it can be installed with
|
||||
~pkg_add~. I store all my albums as sub-folders in
|
||||
~/var/www/img.sha256.net/~ and then run ~llgal~. I was experimenting a
|
||||
bit with the command line flags to figure out what I need and then
|
||||
setup a =~[[file:llgal/llgalrc.txt][/.llgal/llgal.rc]]= file.
|
||||
|
||||
These are the things I configured:
|
||||
#+begin_export ascii
|
||||
thumbnails_per_row = 3
|
||||
thumbnail_height_max = 240
|
||||
thumbnail_width_max = 240
|
||||
MVI_link_to_target = 1
|
||||
DIR_link_to_target = 1
|
||||
slide_width_max = 700
|
||||
slide_height_max = 700
|
||||
show_all_exif_tags = 1
|
||||
credits_text = "Copyright © 2014 - 2023 Florian Obser. All rights reserved."
|
||||
exclude = "^js$"
|
||||
sort_criteria = "revtime"
|
||||
recursive = 1
|
||||
link_subgalleries = 1
|
||||
#+end_export
|
||||
** Video thumbnails
|
||||
llgal does not create thumbnails for video files (yet) so I had to
|
||||
hack around that a bit.
|
||||
First we use ~ffmpeg~ to create the thumbnails:
|
||||
#+begin_src shell
|
||||
for i in *.mp4; do
|
||||
ffmpeg -ss 1 -i ${i} -vframes 1 -vf "scale=240:-1" \
|
||||
.llgal/my_thump_${i}.jpg
|
||||
done
|
||||
#+end_src
|
||||
We grab one frame (=-vframes 1=), one second into the video (=-ss
|
||||
1=), and scale it to 240 pixels wide while keeping the aspect ratio
|
||||
(=-vf "scale=240:-1"=). We store the thumbnail in the ~.llgal~
|
||||
sub-directory, where ~llgal~ stores its own thumbnails and scaled
|
||||
images. The config file has this:
|
||||
#+begin_export ascii
|
||||
# Additional prefix of user-provided scaled images
|
||||
# user_scaled_image_filenameprefix = "my"
|
||||
|
||||
# Additional prefix of user-provided thumbnails
|
||||
# user_thumbnail_image_filenameprefix = "my"
|
||||
#+end_export
|
||||
I have not worked out what that does, but I am using the "my" prefix
|
||||
because of this.
|
||||
|
||||
llgal does not pick up these thumbnails but we can use the /captions/
|
||||
file to show them. First we are creating /captions files in all
|
||||
albums: ~llgal --gc~. This creates =.llgal/captions= in all albums.
|
||||
|
||||
It creates lines for all photos and videos that we can edit, for
|
||||
videos it looks like this:
|
||||
#+begin_export ascii
|
||||
MVI: VID_20230120_124000.mp4 ---- Open movie VID_20230120_124000.mp4 ----
|
||||
#+end_export
|
||||
And we can change it to this to show the thumbnail[fn::I am using an
|
||||
emacs macro for that. YMMV.]:
|
||||
#+begin_export ascii
|
||||
MVI: VID_20230120_124000.mp4 ---- <img src=".llgal/my_thump_VID_20230120_124000.mp4.jpg" /><br /> Open movie ----
|
||||
#+end_export
|
||||
I am using the same trick to have thumbnails for the top-level [[https://img.sha256.net/index.html][album
|
||||
overview]]. The only difference is that it is a =DIR= line instead of
|
||||
=MVI=.
|
||||
** Keyboard and swipe navigation.
|
||||
llgal links to [[http://santana2000.com/][santana2000.com]] as an example. Those albums use
|
||||
[[https://hammerjs.github.io/][hammer.js]] for swipe navigation and [[https://craig.is/killing/mice][mousetrap]] for keyboard navigation.
|
||||
I have copied =slidetemplate.html= from =/usr/local/share/llgal= to
|
||||
=~/.llgal= and edited it: [[file:llgal/slidetemplate.html.txt][slidetemplate.html]].
|
||||
We need to include the JavaScript files in the header:
|
||||
#+begin_src html
|
||||
<script type="text/javascript" src="/js/mousetrap.min.js"></script>
|
||||
<script type="text/javascript" src="/js/hammer.min.js"></script>
|
||||
#+end_src
|
||||
Set the =id= for the navigation links:
|
||||
#+begin_src html
|
||||
<p class="center">
|
||||
<a id="prevslide" href="<!--PREV-SLIDE-->"><!--PREV-SLIDE-LINK-TEXT--></a>
|
||||
|
||||
<a id="indexlink" href="<!--INDEX-FILE-->"><!--INDEX-LINK-TEXT--></a>
|
||||
|
||||
<a id="nextslide" href="<!--NEXT-SLIDE-->"><!--NEXT-SLIDE-LINK-TEXT--></a>
|
||||
</p>
|
||||
#+end_src
|
||||
And then hook up JavaScript to the navigation links:
|
||||
#+begin_src html
|
||||
<script type="text/javascript">
|
||||
// Script for keyboard navigation
|
||||
var prev = document.getElementById("prevslide").href;
|
||||
var next = document.getElementById("nextslide").href;
|
||||
Mousetrap.bind('left', function () { location.href = prev; });
|
||||
Mousetrap.bind('right', function () { location.href = next; });
|
||||
Mousetrap.bind('h', function () { location.href = indexlink; });
|
||||
Mousetrap.bind('j', function () { location.href = prev; });
|
||||
Mousetrap.bind('k', function () { location.href = next; });
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Script for touch gestures (Hammerjs)
|
||||
var slide = document.getElementById('slide-container');
|
||||
var mc = new Hammer(slide);
|
||||
mc.on("swiperight", function(ev) { location.href = next; });
|
||||
mc.on("swipeleft", function(ev) { location.href = prev; });
|
||||
</script>
|
||||
#+end_src
|
||||
This seems to disable pinch-zooming on the image itself on android. I
|
||||
have not figured out why that is. The hammerjs documentation talks
|
||||
about pinch, but my understanding is that it should just work. It does
|
||||
not though...
|
||||
* Epilogue
|
||||
This was not a lot of work, please enjoy the first [[https://img.sha256.net/2023-01%20Malta/index.html][album from our trip
|
||||
to Malta in 2023]].
|
||||
Time permitting I will convert more albums from flickr and google
|
||||
photos in the future.
|
Reference in New Issue
Block a user