<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="atom-style.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <id>https://corion.net/blog/</id>
    <title>Corions Musings</title>
    <updated>2026-10-11T00:00:00Z</updated>
    <link href="https://corion.net/blog/index.atom" rel="self" />
    <link href="https://corion.net/blog/" rel="alternate" />
    <generator version="0.098">Statocles</generator>

    <entry>
        <id>https://corion.net/blog/2026/10/11/updated-my-photo-import-pipeline/</id>
        <title>Updating my photo import pipeline</title>
        <author><name>Corion</name></author>
        <link href="https://corion.net/blog/2026/10/11/updated-my-photo-import-pipeline/" rel="alternate" />
        <content type="html"><![CDATA[
            <h1>Why?</h1>

<p>Recently I took up
<a href="https://corion.net/blog/2026/10/11/updated-my-photo-import-pipeline/../../../../tag/photography/">photography</a>
again. Or rather, I made more of a conscious effort to take pictures again, as
opposed to snapping them. I have
<a href="https://github.com/Corion/App-Photoimport">my existing image import pipeline</a>,
which copies the files from the devices to my central server into timestamped
directories.</p>

<p>Recently I actually exhausted the storage of my mobile phone and that made me
realize that I want to run my photo import via <code>rsync</code> from abroad on my phone
instead of local-only copying via mounted drives.</p>

<h2>Reading files</h2>

<p>Before the change, the program took all files in the <code>DCIM</code> directory and
copied them via an SMB mount to the central server:</p>

<ul>
<li>Find all files in <code>DCIM/</code><em><code>Camera</code></em> directories</li>
<li>Read the image creation times from image EXIF data</li>
<li>Upload all files into directories grouped by their timestamps</li>
<li>Move all files into the <code>DCIM/</code><em><code>Camera</code></em><code>/archive</code> as a safety measure. I manually delete the <code>archive/</code> directory from time to time</li>
</ul>

<p>But running the import on a <code>gphoto2</code> mounted directory does not allow to move transferred files to the <code>DCIM/archive</code> directory.
This would be ameliorated by using <code>rsync</code>. but a more discerning approach is still needed since I might have renamed the target directories
on the central server in the meantime.</p>

<p>The new approach addresses these points</p>

<ul>
<li>Find all files in <code>DCIM/</code><em><code>Camera</code></em> directories</li>
<li>Find (rough) creation date from image filename (fast), or from image EXIF data (slow, needed for sequentially numbered image file names)</li>
<li>Read the remote directories starting from the earliest image timestamp</li>
<li>Associate each image with a target directory
<ul>
<li>if it already exists on the remote side, use that directory</li>
<li>use the image timestamp for the image otherwise</li>
</ul></li>
<li>Upload all files into their target directories using <code>rsync</code></li>
</ul>

<p>Using <code>rsync</code> and always transferring / synchronizing all images makes the transfer resilient against network failures and partial transfers.
Looking at the already existing filenames on the target end also opens the door to reading calendar entries and creating the directories with their calendar entry outright, as I&#39;ve decoupled the directory name from the image creation timestamp.</p>

<h2>Having an <code>ssh</code> remote target</h2>

<p>Moving to <code>rsync</code> also enables backing up to a remote machine over <code>ssh</code>. To move the files into the appropriate locations, I also need to read remote directories.
I did not find an established module on CPAN for this. <a href="https://metacpan.org/pod/Filesys::Virtual::SSH">Filesys::Virtual::SSH</a> is OKish, but I don&#39;t like the API
of <code>Filesys::Virtual</code> overall. I only needed a single routine to read a remote directory, so I wrote a very simple wrapper:</p>

<pre><code>sub r_readdir($dir, $type=&quot;d&quot;) {
    if( $dir =~ m!^ssh:(?&lt;host&gt;(\w+\@)?[^:]+):(?&lt;path&gt;.*)! ) {
        my $p = $-{path}-&gt;[0];

        my $cmd = &quot;ssh &#39;$-{host}-&gt;[0]&#39; &#39;find \&quot;$p\&quot; -type $type&#39;&quot;;

        currently(&quot;Reading &#39;$p&#39;&quot;);
        if($verbose) {
            $printer-&gt;output_permanent($cmd);
        }

        return map { s!^\Q$p\E[/\\]?!!r }
            split /\r?\n/,readpipe( $cmd );
    } else {
        opendir my $dh, $dir
            or die &quot;Can&#39;t read &#39;$dir&#39;: $!&quot;;
        return readdir($dh);
    }
}
</code></pre>

<p>This allows me to keep all filtering local in perl, which is not efficient over the
network but highly efficient in protecting me from needing to shell-escape all the commands.</p>

<h2>Naming the image import directories</h2>

<p>I often end up with directories named <code>20260417-1603</code> , which is better than
nothing. But I still would like to know what happened then. Often I have an
entry in my calendar which might be so-and-sos birthday party, or some
conference or whatnot, and having the computer automatically naming the
directory according to the calendar is a nice touch. I&#39;ve put off this for a
long time, but now I&#39;ve actually released
<a href="https://metacpan.org/pod/Net::CalDAV::FindEntry">Net::CalDAV::FindEntry</a>
to make this convenient:</p>

<pre><code>my @relevant_events = $cal-&gt;get_events(
    after    =&gt; $image_timestamp,
    before   =&gt; $image_timestamp,
    calendar =&gt; &#39;Corion&#39;
);

# We blindly take the event that started closest before the photo was taken
my ($ev) = sort { $a-&gt;{start} cmp $b-&gt;{start} } @relevant_events;
if( $ev ) {
  $target_directory{ $image } //= &quot;$image_timestamp - $ev-&gt;{title}&quot;;
}
</code></pre>

<p>With that line added, I get conveniently pre-named directory names on the
central server. It&#39;s still not perfect, as the directory naming needs to
respect timezones
while the image timestamps are either in a floating timezone or GMT,
but this gets me a long step forward in convenience. Also, I need to clean
up the titles of the calendar entries to make them suitable as directory names.
Originally I thought
<a href="https://metacpan.org/pod/Text::CleanFragment">Text::CleanFragment</a>
would be good for this, but it replaces spaces with underscores, which I do
not want in the directory names, so I wrote a small ad-hoc sanitizer
for that. So there still is work to do in the future.</p>


                <p>Tags:
                    <a href="https://corion.net/blog/tag/perl/">Perl</a>
                    <a href="https://corion.net/blog/tag/programming/">programming</a>
                </p>

        ]]></content>
        <updated>2026-10-11T00:00:00Z</updated>
        <category term="Perl" />
        <category term="programming" />
    </entry>
    <entry>
        <id>https://corion.net/blog/2026/10/09/image-of-the-week/</id>
        <title>Image of the Week</title>
        <author><name>Corion</name></author>
        <link href="https://corion.net/blog/2026/10/09/image-of-the-week/" rel="alternate" />
        <content type="html"><![CDATA[
            <p>Another picture trying out the Canon 100mm macro lens.
<a href="https://corion.net/blog/2026/10/09/image-of-the-week/"><img src="https://corion.net/blog/2026/10/09/image-of-the-week/462A0031.JPG"></a></p>


                <p>Tags:
                    <a href="https://corion.net/blog/tag/photography/">Photography</a>
                </p>

        ]]></content>
        <updated>2026-10-09T00:00:00Z</updated>
        <category term="Photography" />
    </entry>
    <entry>
        <id>https://corion.net/blog/2026/10/06/pivot-to-ai/</id>
        <title>Pivot to AI</title>
        <author><name>Corion</name></author>
        <link href="https://corion.net/blog/2026/10/06/pivot-to-ai/" rel="alternate" />
        <content type="html"><![CDATA[
            <h1><img alt="Pivot to AI logo" src="https://corion.net/blog/2026/10/06/pivot-to-ai/cropped-clip-icon.png"></h1>

<p>Link: <a href="https://pivot-to-ai.com/">https://pivot-to-ai.com/</a></p>

<p>What <a href="https://web3isgoinggreat.com/">Web3 is going great</a> is for
Crypto(currency) stuff, <a href="https://pivot-to-ai.com/">Pivot to AI</a>
is for AI-related grift.</p>

<p><a href="https://pivot-to-ai.com/2026/10/05/anthropic-could-ai-be-conscious-pope-leo-lol-no/">Anthropic: Could AI be conscious? Pope Leo: lol, no</a></p>

<blockquote>
  <p>The Catholic Church has a number of obvious issues. But it’s not hard to do better ethically than an AI vendor.</p>
</blockquote>


                <p>Tags:
                    <a href="https://corion.net/blog/tag/linkblog/">Linkblog</a>
                </p>

        ]]></content>
        <updated>2026-10-06T00:00:00Z</updated>
        <category term="Linkblog" />
    </entry>
    <entry>
        <id>https://corion.net/blog/2026/10/04/software-i-use-davinci-resolve/</id>
        <title>Software I use: DaVinci Resolve</title>
        <author><name>Corion</name></author>
        <link href="https://corion.net/blog/2026/10/04/software-i-use-davinci-resolve/" rel="alternate" />
        <content type="html"><![CDATA[
            <h1><a href="https://www.blackmagicdesign.com/products/davinciresolve">DaVinci Resolve</a></h1>

<p><img alt="DaVinci Resolve Screenshot" src="https://corion.net/blog/2026/10/04/software-i-use-davinci-resolve/davinci-resolve.jpg"></p>

<p>This year I first used it for post-processing the videos for the <a href="https://act.yapc.eu/gpw2027/">German Perl Workshop</a>. Usually
the videos only need some slight cutting or insertion of a simple overlay, which <code>ffmpeg</code> does well enough. This year,
I wanted to blank out some PII from a video, and having an interactive
non-linear editor was convenient here.</p>

<p>The program supports Linux, and it is a monster of an non-linear video editor. The free (as in beer) version can do everything
I need, the paid version is cheap(ish) at € 300 (?) for a permanent license. The permanent license has more filters and some
AI built-in, but I don&#39;t need that. Blackmagic Design make their money from selling
hardware, and I also have one ATEM Mini Pro HDMI multiplexer.</p>

<p>The software is complex, but there are lots of Youtube videos showing how to find the relevant buttons. It took me
half a day to find out how to overlay a video with black bars censoring some personal identifying information (PII)
for our workshop videos. But in the process I also learned that even the free edition of Resolve can do
automatic tracking of elements in a shaky-cam video.</p>

<p>For creating the filters, Resolve has the usual filter graph infinite canvas, which also takes some getting
used to. But the automatic layout of the graph connections works well enough for me, and I&#39;m not doing
anything fancy like camera tracking or inserting dynamic video into other video.</p>

<p>I&#39;ve used the software on my beefy Windows machine with an RTX 4090 and 128GB RAM, and editing
and rendering a video on that machine is a breeze, even on a remote desktop connection from my
main Linux desktop. On Debian, I didn&#39;t get it to run since it wants a newer version of the
Nvidia drivers than Debian stable provides, and I didn&#39;t want to play around with mixing
Debian stable and the Nvidia repositories.</p>



        ]]></content>
        <updated>2026-10-04T00:00:00Z</updated>
    </entry>
    <entry>
        <id>https://corion.net/blog/2026/10/02/image-of-the-week/</id>
        <title>Image of the Week</title>
        <author><name>Corion</name></author>
        <link href="https://corion.net/blog/2026/10/02/image-of-the-week/" rel="alternate" />
        <content type="html"><![CDATA[
            <p>I took this picture on a photo walk with colleagues, trying out the Canon 100mm macro lens.
<a href="https://corion.net/blog/2026/10/02/image-of-the-week/"><img src="https://corion.net/blog/2026/10/02/image-of-the-week/462A0129.JPG"></a></p>


                <p>Tags:
                    <a href="https://corion.net/blog/tag/photography/">Photography</a>
                </p>

        ]]></content>
        <updated>2026-10-02T00:00:00Z</updated>
        <category term="Photography" />
    </entry>
</feed>

