<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Alessandro Lorenzi</title>
    <description></description>
    <link>https://alorenzi.eu/</link>
    <atom:link href="https://alorenzi.eu/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 19 Dec 2025 15:51:07 -0600</pubDate>
    <lastBuildDate>Fri, 19 Dec 2025 15:51:07 -0600</lastBuildDate>
    <generator>Jekyll v4.2.2</generator>
    
     
      <item>
        <title>Redis db sizes</title>
        <description>&lt;p&gt;Ho un redis, che sta sempre con l’utilizzo della memoria a tappo. Ogni servizio ha il suo DB dedicato e sto tentando di capire quale servizio sta occupando tanto tanto spazio.&lt;/p&gt;

&lt;p&gt;Non ho trovato il modo di farmelo dire direttamente da redis, quindi mi sono fatto lo script io.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env python3
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;redis&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;concurrent.futures&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_memory_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;redis_conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Redis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;  
        &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Rimpiazza con l&apos;indirizzo del tuo redis
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6379&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redis_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_memory_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redis_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memory_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;total_memory_usage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;concurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;futures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_workers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;executor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_memory_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;total_memory_usage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total_memory_usage&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bytes_to_human_readable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size_in_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;KB&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;MB&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;GB&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;TB&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;PB&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size_in_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size_in_bytes&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;size_in_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size_in_bytes&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; PB&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mem_usage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculate_memory_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mem_usage_human&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes_to_human_readable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Total memory usage for database &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem_usage_human&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;L’ho parallelizzato perché stavo diventando vecchio ad aspettare che si facesse la lista di tutte le chiavi una per una, ma potete aggiustare il &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;max_workers&lt;/code&gt; se non volete pesare sul redis.&lt;/p&gt;

&lt;p&gt;E niente, il colpevole era chi pensavamo che fosse, ma abbiamo la prova provata.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;Total memory usage for database 0: 1.01 GB &lt;span class=&quot;nt&quot;&gt;&amp;lt;--&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;eccolo&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;2.23&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;148.51&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;150.20&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;20.15&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;504.94&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5.76&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;110.75&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0.00&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;120.00&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5.28&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;707.13&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;KB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1.77&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;MB&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0.00&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0.00&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0.00&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 03 Jul 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/07/03/redis-db-sizes.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/07/03/redis-db-sizes.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Slipknot - 2025 Setlist</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.setlist.fm/setlists/slipknot-1bd6a5b4.html&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/videoseries?si=iK_y85_yj2qSLcAJ&amp;amp;list=PL7-NLIL7NXgvZiD7XLUeSlkbHBw8FB7SL&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Sun, 04 May 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/05/04/slipknot-2025-setlist.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/05/04/slipknot-2025-setlist.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Cloud vs In House</title>
        <description>&lt;p&gt;Sto scrivendo un altro articolo che mi sta uscendo un rant lunghissimo. Visto che ci sto mettendo tre giorni causa deficit visivo (chi mi conosce sa), ho deciso di staccare e ampliare questo pezzo di storia.&lt;/p&gt;

&lt;p&gt;Parliamo di &lt;strong&gt;Cloud&lt;/strong&gt;, quella cosa che gli europei non riescono proprio a fare.&lt;/p&gt;

&lt;p&gt;I tre maggiori cloud provider sono americani (&lt;em&gt;AWS&lt;/em&gt;, &lt;em&gt;GCP&lt;/em&gt;, &lt;em&gt;Azure&lt;/em&gt;); gli altri hanno numeri irrilevanti. Forse spicca la cinese &lt;em&gt;Alibaba&lt;/em&gt; ma più per motivazioni politiche che tecnologiche.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Europa&lt;/strong&gt; tutto tace, le grosse aziende sono piú orientate all’&lt;em&gt;hosting web&lt;/em&gt; e di &lt;em&gt;macchine virtuali&lt;/em&gt; che ai servizi cloud e si muovono alla rinfusa. Ogni tanto escono notizie che mi fanno ben sperare (&lt;a href=&quot;https://www.wired.it/article/lidl-cloud-schwarz-digit/&quot;&gt;il cloud della LIDL&lt;/a&gt;, &lt;a href=&quot;https://www.gaiax-italia.eu/cosa-facciamo&quot;&gt;gaia x&lt;/a&gt;) ma nella relata non vedo una corsa alla cloudizzazione europea.&lt;br /&gt;
Nemmeno le varie &lt;a href=&quot;https://it.wikipedia.org/wiki/Sentenze_Schrems&quot;&gt;&lt;strong&gt;sentenze Shrems&lt;/strong&gt;&lt;/a&gt; hanno mai scosso le coscienze delle aziende verso il passaggio all’autarchia europea del cloud.&lt;/p&gt;
&lt;h2 id=&quot;ma-il-cloud-serve-davvero&quot;&gt;Ma il cloud serve davvero?&lt;/h2&gt;

&lt;p&gt;Ultimamente mi sto facendo spesso questa domanda.&lt;/p&gt;

&lt;p&gt;Vengo da un background di &lt;strong&gt;sistemista unix&lt;/strong&gt;, il mio primo lavoro é stato su macchine &lt;a href=&quot;https://en.wikipedia.org/wiki/Oracle_Solaris&quot;&gt;Solaris&lt;/a&gt; e &lt;a href=&quot;https://en.wikipedia.org/wiki/HP-UX&quot;&gt;HP-UX&lt;/a&gt;, ho seguito tutte le evoluzioni del ruolo e ad oggi lavoro principalmente su AWS come &lt;strong&gt;platform engineer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ho sempre avuto un server personale, prima un “server” in casa (un vecchio computer con la ventola costantemente accesa fuori dalla porta della camera da letto), poi una vps, e oggi sono tornato ad ospitare un mini-pc fanless in casa.&lt;/p&gt;

&lt;p&gt;Un paio di anni fa ho iniziato ad &lt;strong&gt;abbattere i costi&lt;/strong&gt; del cloud nella mia azienda. Mi sono accorto di quanti sprechi avevamo e - nonostante il lavoro fatto - ancora oggi ci sono costi intrinsechi non eliminabili.
Ho quindi pensato a quanto ci costerebbe oggi l’infrastruttura se fossero state fatte scelte diverse e a quali sarebbero i costi di una migrazione.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-04-15-cloud-vs-in-house/meme.jpg&quot; alt=&quot;Meme Left Exit 12 Off Ramp. Testo 1: &amp;quot;Cloud&amp;quot;, Testo 2 &amp;quot;In House&amp;quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;il-viaggio-di-alpha-e-sigma&quot;&gt;Il viaggio di Alpha e Sigma&lt;/h2&gt;

&lt;p&gt;Per questo viaggio  prenderemo ad esempio le aziende Alpha e Sigma. Entrambe vogliono “andare veloce” ma in modi diversi.&lt;/p&gt;

&lt;p&gt;L’azienda &lt;strong&gt;Alpha&lt;/strong&gt; é all’avanguardia, va sul cloud, scrive microservizi che fa girare su kubernetes gestito, il database gestito, e magari fa anche il vibe coding.&lt;/p&gt;

&lt;p&gt;L’azienda &lt;strong&gt;Sigma&lt;/strong&gt; invece sceglie una via minimalista: un servizio monolite, un database e poco altro.&lt;/p&gt;

&lt;p&gt;⚠️ queste due aziende sono un il mischione di decine di aziende per le quali ho lavorato direttamente o in consulenza. Spero che nessun (ex)collega si ritrovi pienamente in nessuna delle due.&lt;/p&gt;

&lt;h3 id=&quot;fase-1-startup&quot;&gt;Fase 1: startup&lt;/h3&gt;

&lt;p&gt;In questa fase le aziende vogliono validare la propria idea, aprirsi al mercato e gettare le basi dell’impero economico che ne nascerà.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Alpha&lt;/strong&gt; gli sviluppatori vanno su microservizi e AWS: EKS, RDS, S3, VPC, GW e qualche altra sigla.&lt;/p&gt;

&lt;p&gt;In locale ogni sviluppatore crea il proprio microservizio isolato. Inizia a scrivere con il proprio linguaggio di programmazione preferito sul framework preferito. Lo fa girare in locale con docker compose e fa deploy su kubernetes. Poche persone full-stack che iniziano a tirare su il proprio pezzo di &lt;a href=&quot;https://en.wikipedia.org/wiki/Domain-driven_design&quot;&gt;dominio&lt;/a&gt;, fare meeting per decidere come interfacciare i pezzi e incastrare i pezzi del puzzle.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Sigma&lt;/strong&gt; si sviluppa sullo stesso monolite in sessioni di pair o mud programming. Ognuno installa il database sul proprio computer ed esegue il monolite, si prende una VPS su hetzner e si installa il database e l’applicativo esattamente come gira sulla propria macchina di sviluppo.&lt;/p&gt;

&lt;h4 id=&quot;i-costi&quot;&gt;I costi&lt;/h4&gt;

&lt;p&gt;Per &lt;strong&gt;Alpha&lt;/strong&gt; calcolo un eks, rds, un po’ di nodi kubernetes, il gateway per la vpc privata, siamo tra i 200$ e i 300$ mensili.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sigma&lt;/strong&gt; fa girare tutto su una macchina hetzner CPX31, 13.60€ mensili.&lt;/p&gt;

&lt;h3 id=&quot;fase-2-scale-up&quot;&gt;Fase 2: Scale up&lt;/h3&gt;

&lt;p&gt;La startup é diventata &lt;strong&gt;scale up&lt;/strong&gt;! L’idea funziona, ha preso fondi dagli investitori, si cresce, si assumono piú persone.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Alpha&lt;/strong&gt; creano team specializzati (hanno letto &lt;a href=&quot;https://www.instagram.com/p/CP-9cVjghmU/&quot;&gt;team topology&lt;/a&gt;), hanno sempre piú microservizi da gestire perché ogni funzionalità del sistema ha un microservizio, aumentano i nodi del cluster kubernetes. I microservizi sono tanti, non é facilmente ricreabile localmente l’ambiente di sviluppo per intero quindi anche i cluster diventano due, viene aggiunto un ambiente di test con cui interfacciarsi durante lo sviluppo del microservizio. 
In seguito si crea anche uno di staging dove poter testare tutto in un ambiente un po’ piú stabile prima di mandare in produzione.&lt;/p&gt;

&lt;p&gt;In pratica bisogna &lt;strong&gt;triplicare l’aumento&lt;/strong&gt; delle risorse richiesto ad ogni sviluppo fatto.&lt;/p&gt;

&lt;p&gt;Nel frattempo si accumula debito tecnico, alcuni servizi non sono piú toccati da mesi. Molti hanno versioni del framework vecchi, non aggiornati con patch di sicurezza non applicate, altri sono scritti in linguaggi di programmazione che piacevano tanto a qualche sviluppatore che ora lavora in altre aziende e ora non c’é piú nessuno che li padroneggia.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Sigma&lt;/strong&gt; si continua a lavorare in maniera minimale e pulita. Vengono assunte persone che conoscono quel linguaggio di programmazione e quel framework o che sono interessati a studiarli. Tutti sono in grado di mettere mano a quel codice, viene mantenuto e aggiornato perché é piú facile mantenere un singolo servizio. Anche quando viene diviso il servizio in sito pubblico e backoffice si mantengono le stesse tecnologie.&lt;/p&gt;

&lt;p&gt;Il software non dovendo fare chiamate ad altri microservizi é veloce e non avendo overhead per ogni servizio é anche efficiente in termini di memoria. Quindi gli sviluppatori continuano a poter eseguire “&lt;em&gt;tutta l’azienda&lt;/em&gt;” sul proprio computer, non servono particolari ambienti di sviluppo.&lt;/p&gt;

&lt;p&gt;Per scalare l’infrastruttura di produzione si decide nel tempo di mettere il database su un VPS separato, di scalare verticalmente prendendo una macchina virtuale piú grossa per il servizio e alla fine di scalare orizzontalmente prendendo tre macchine virtuali piú una piccola macchina varnish che fa da server proxy e cache.&lt;/p&gt;

&lt;p&gt;Database e le immagini vengono backuppate ad ogni ora sul nas aziendale (il primo pezzo di hardware acquistato) e settimanalmente viene fatto uno snapshot di tutto su un disco cifrato tenuto offline in una sede diversa.&lt;/p&gt;

&lt;p&gt;Per il disaster recovery viene realizzato un sito statico su un diverso provider su cui puntare i dns in caso di problemi seri. Gli utenti non possono acquistare i servizi direttamente ma possono esplorare il catalogo e fare ordini via mail.&lt;/p&gt;

&lt;h4 id=&quot;i-costi-1&quot;&gt;I costi&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Alpha&lt;/strong&gt; quindi ormai avrà tre cluster kubernetes, tre cluster postgres, tutto in reti isolate e qualche bucket s3. Spannometricamente spenderemo 10k$/mo per produzione e 5k$ a testa per dev e staging, arrotondiamo 250k$/anno su AWS.&lt;/p&gt;

&lt;p&gt;Invece &lt;strong&gt;Sigma&lt;/strong&gt; utilizza ben 6 macchine CPX41 per prodotto e database e una CPX31, per un totale di 158€. Arrotondiamo a 200€ mensili su hetzner includendo anche storage aggiuntivo e 1000€ per un qnap e dischi. 3400€ all’anno, fiscalmente 2.6k ammortizzando l’hardware.&lt;/p&gt;

&lt;h3 id=&quot;fase-3-la-maturità&quot;&gt;Fase 3: La maturità&lt;/h3&gt;

&lt;p&gt;Siamo arrivati al famoso break even point, il punto in cui i profitti superano i costi, iniziamo a fare i big money.&lt;/p&gt;

&lt;p&gt;Come sta il nostro reparto tech?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alpha&lt;/strong&gt; usa tutti i servizi che AWS propone, salvo poi non ricordarsi per quale motivo un servizio é acceso, intanto il billing aumenta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sigma&lt;/strong&gt; si é mantenuta ai principi fondamentali. Vengono adottate nuove tecnologie solo se rispondono a precise esigenze non coperte da tecnologie giá adottate e per ognuna si calcola i costi di mantenimento sul lungo periodo. Il team rimane piccolo e focalizzato sullo sviluppo di  un prodotto solido.
L’infrastruttura passa al ferro. Con tre server “carrozzati” in colocation e un sistema di virtualizzazione il servizio é stabile. L’acquisto dei server é stato visto non come un costo ma come investimento e il canone della colocation é contenuto rispetto ai costi che avevano prima sul provider (i nodi con GPU iniziavano a costare parecchio).&lt;/p&gt;

&lt;p&gt;Non sto piú nemmeno a calcolare &lt;strong&gt;i costi&lt;/strong&gt; che possono avere in questa fase le aziende. Ci sono aziende che hanno billing milionari sul cloud e altre che costruiscono interi datacenter, e altri ancora che hanno un rack nello sgabuzzino.&lt;/p&gt;

&lt;h2 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h2&gt;

&lt;p&gt;Sicuramente sto passando in un momento di &lt;strong&gt;disillusione&lt;/strong&gt; del cloud, ci sono aspetti &lt;strong&gt;positivi&lt;/strong&gt; che ho tralasciato, ad esempio le availability zone sono una cosa stupenda per l’uptime, e amplificato aspetti &lt;strong&gt;negativi&lt;/strong&gt; che non sono propri del “cloud” in quanto tale ma conseguenza di scelte di design che comunque il cloud non ostacola.&lt;/p&gt;

&lt;p&gt;D’altra parte forse sto dimenticando i &lt;strong&gt;dolori del giovane sistemista&lt;/strong&gt;: le repliche postgres che si de-sincronizzano e bisogna ricreare, l’aggiornamento delle macchine, le sudate fredde quando il riavvio impiega piú di 30 secondi.&lt;/p&gt;

&lt;p&gt;Non so dove mi porterà il futuro, gli scenari aperti dalle nuove tecnologie e come io le accoglierò. Come dico ogni tanto, il ruolo che ho ora non esisteva nemmeno quando mi sono laureato, per non parlare di quando ho scritto la prima riga in GW Basic a fine anni 90; chissà cosa farò da grande.&lt;/p&gt;
</description>
        <pubDate>Tue, 15 Apr 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/04/15/cloud-vs-in-house.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/04/15/cloud-vs-in-house.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Immich-FUSE</title>
        <description>&lt;p&gt;tl;dr: ho creato un filesystem in userspace (FUSE) per montare le immagini di Immich in una directory locale. &lt;a href=&quot;https://github.com/AlessandroLorenzi/immich-fuse&quot;&gt;Questo é il repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sto usando Immich da un mese, ho spostato lì tutti i miei archivi (&lt;a href=&quot;https://alorenzi.eu/2025/03/31/sistemato-metadati-foto-google-takeout.html&quot;&gt;Google Photos&lt;/a&gt;, foto di Shotwell, backup vari) e penso che sia un software fantastico.&lt;/p&gt;

&lt;p&gt;C’è solo un problema: rompe il mio solito flusso di lavoro di editing delle foto che avevo con Shotwell: scaricare tutte le foto dalla fotocamera su Shotwell -&amp;gt; rivedere le foto più interessanti dello shooting -&amp;gt; modificare con GIMP/Darktable/qualsiasi altro software -&amp;gt; profit.&lt;/p&gt;

&lt;p&gt;Ora, con Immich, utilizzo il comando &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;immich upload -r /var/media/[....]/DCIM&lt;/code&gt; per caricare le immagini sul server, ed è persino più comodo rispetto a Shotwell che ogni tanto si imballava. MA ora devo scaricare le immagini per modificarle.&lt;/p&gt;

&lt;p&gt;L’idea è: perché non montare Immich direttamente in una directory locale?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-04-13-immich-fuse/graph.jpg&quot; alt=&quot;Grafico che spiega la mia idea&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Questo progetto è un Proof of Concept (POC), è in sola lettura, ma funziona! È possibile sfogliare le immagini di Immich per data, solo preferiti e cercando persone taggate.&lt;/p&gt;

&lt;p&gt;Peró funziona, questo é uno screenshot di Nautilus che mostra le foto di Immich:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-04-13-immich-fuse/nautilus.jpg&quot; alt=&quot;screen delle foto in nautilus&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nel &lt;a href=&quot;https://github.com/AlessandroLorenzi/immich-fuse&quot;&gt;README&lt;/a&gt; ci sono più dettagli implementativi.&lt;/p&gt;

&lt;p&gt;In futuro mi piacerebbe implementare una sorta di caricamento diretto. Ad esempio, salvando un’immagine da GIMP, questa verrebbe caricata automaticamente su Immich.&lt;/p&gt;

</description>
        <pubDate>Sun, 13 Apr 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/04/13/immich-fuse.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/04/13/immich-fuse.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Ho sistemato i metadati delle foto di Google Takeout</title>
        <description>&lt;p&gt;Dopo aver fatto l’upload di tutti i &lt;a href=&quot;https://alorenzi.eu/2025/03/28/che-me-ne-faccio-dei-video.html&quot;&gt;video compressi&lt;/a&gt; che avevo in giro su immich sono passato a richiedere a google tutto il mio archivio fotografico.&lt;/p&gt;

&lt;p&gt;Ho fatto partire l’upload di qualche foto ma mi sono accorto che non tutte andavano nel posto giusto, qualcuna veniva caricata con la data in cui ho chiesto il takeout. 😱&lt;/p&gt;

&lt;p&gt;Mi sono accorto che tutti i file foto e video avevano un file &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;.supplemental-metadata.json&lt;/code&gt; associato. Ad esempio:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;# ls -l ./Garda2020/DSC01374.jpg*                          
-rw-r--r--. 1 alorenzi alorenzi 160565 Aug 18  2020 ./Garda2020/DSC01374.jpg
-rw-r--r--. 1 alorenzi alorenzi    599 Mar 25 00:02 ./Garda2020/DSC01374.jpg.supplemental-metadata.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Inoltre qualcuno aveva il nome di quel file tagliato, ad esempio  &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;./Photos from 2025/IMG_20250310_201005_380.webp.supplemental-meta.json&lt;/code&gt; . Sicuramente volevano tenere il nome di una lunghezza massima, ma non ha sicuramente facilitato il lavoro di puliza.&lt;/p&gt;

&lt;h2 id=&quot;che-sono-gli-exif&quot;&gt;Che sono gli exif?&lt;/h2&gt;

&lt;p&gt;Gli exif sono metadati che la macchina fotografica (o il telefono) scrive all’interno del file della fotografia. Ci potete trovare il modello della macchina con cui é stata scattata la foto, i settaggi (tempi di esposizione, iso…), la posizione GPS e l’orario.&lt;/p&gt;

&lt;p&gt;I software di gestione delle foto utilizzano queste informazioni per mettere la foto sulla mappa o appunto metterla correttamente nella timeline.&lt;/p&gt;

&lt;h2 id=&quot;scriptiamo&quot;&gt;Scriptiamo…&lt;/h2&gt;

&lt;p&gt;In questo caso ho utilizzato &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;exiftool&lt;/code&gt; per estrarre la data dal file originale per evitare di processare inutilmente tutte le immagini, poi ho estratto dal json il timestamp con &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;jq&lt;/code&gt; e infine ho settato l’exif usando ancora &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;exiftool&lt;/code&gt; .&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;update_metadata&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Extract the date from exif&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;DATE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;exiftool &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%Y-%m-%d&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DateTimeOriginal&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s3&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# if the date is valid return&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DATE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        return &lt;/span&gt;0
    &lt;span class=&quot;k&quot;&gt;fi
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;JSON_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;.&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.json&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Get the date from metadata json&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.photoTakenTime.timestamp&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;JSON_FILE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Set exif&lt;/span&gt;
    exiftool &lt;span class=&quot;nt&quot;&gt;-overwrite_original&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;-DateTimeOriginal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;-FileCreateDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;-FileModifyDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Una veloce modifica al codice e troviamo quali immagini non sono state configurate correttamente&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;check_date&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;DATE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;exiftool &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%Y-%m-%d&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DateTimeOriginal&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s3&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# if the date is valid return&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DATE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        return &lt;/span&gt;0
    &lt;span class=&quot;k&quot;&gt;fi
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;No date found for &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Entrambe le funzioni si possono lanciare con il comando &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;find&lt;/code&gt; come fatto nell’&lt;a href=&quot;https://alorenzi.eu/2025/03/28/che-me-ne-faccio-dei-video.html#lo-script&quot;&gt;articolo precedente&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Con &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;check_date&lt;/code&gt; ho scoperto che una trentina di foto non avevano né gli exif settati e nemmeno un file json associato. Ma é anche vero che erano quasi tutte foto &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;NOMEFILE-edited.jpg&lt;/code&gt; o simili.&lt;/p&gt;

&lt;p&gt;Quindi l’ultimo giro di giostra é stato fare uno script che prendesse due immagini e copiasse la data di scatto da una all’altra:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;lastfix&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;exiftool &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DateTimeOriginal&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s3&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Writing &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    exiftool &lt;span class=&quot;nt&quot;&gt;-overwrite_original&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-DateTimeOriginal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-FileCreateDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-FileModifyDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PHOTO_TAKEN_TIME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

lastfix photo-edited.jpg photo.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;upload&quot;&gt;Upload&lt;/h2&gt;

&lt;p&gt;Alla fine ho caricato ben 3332 foto nuove al mio archivio unico 🤩&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;Crawling &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;assets...
Hashing files           | ████████████████████████████████████████ | 100% | ETA: 0s | 6280/6280 assets
Checking &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;duplicates | ████████████████████████████████████████ | 100% | ETA: 0s | 6280/6280 assets
Found 3832 new files and 2448 duplicates
Uploading assets | ███████████████████████████████████░░░░░ | 87% | ETA: NFs | 15.7 GB/15.7 GB
Successfully uploaded 3332 new assets &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;13.8 GB&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Skipped 500 duplicate assets &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1.9 GB&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 31 Mar 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/03/31/sistemato-metadati-foto-google-takeout.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/03/31/sistemato-metadati-foto-google-takeout.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Che me ne faccio dei video?</title>
        <description>&lt;p&gt;Nelle ultime settimane sto risistemando tutte le foto e i video che ho in giro e sto caricando tutto su immich, un servizio self-hosted che rimpiazza Google Photos.&lt;/p&gt;

&lt;p&gt;Visto che dei video in alta qualità non me ne faccio assolutamente nulla, e anzi ne sto eliminando un po’, ho deciso di comprimerli tutti in locale e poi caricarli sul mio serverino.&lt;/p&gt;

&lt;p&gt;È vero che immich stesso fa una compressione all’upload, ma il serverino stesso è piccolino, poco potente e impiegherebbe più tempo. Inoltre, la conversione avverrebbe dopo l’upload, e anche i tempi di upload si allungherebbero inutilmente.&lt;/p&gt;

&lt;p&gt;E poi è possibile usare questo script anche per altri archivi, non necessariamente per immich.&lt;/p&gt;

&lt;h2 id=&quot;i-requisiti&quot;&gt;I requisiti&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Devo comprimere i video in modo da risparmiare spazio&lt;/li&gt;
  &lt;li&gt;Posso lanciare il comando più volte e, se già esiste il video compresso, vado avanti&lt;/li&gt;
  &lt;li&gt;Voglio che ci sia una verifica del file compresso
    &lt;ul&gt;
      &lt;li&gt;nei test mi sono capitati dei file fallati&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Il file compresso deve avere gli stessi metadata del sorgente&lt;/li&gt;
  &lt;li&gt;al primo upload su immich avevano tutti la data del giorno in cui ho fatto l’upload, mancando i metadati di quando sono stati girati&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;try-this-at-home-ma-con-calma&quot;&gt;Try this at home, ma con calma&lt;/h2&gt;

&lt;p&gt;⚠️ Testate il funzionamento in una directory con qualche video di test e/o abbiate i backup prima di fare qualsiasi cosa&lt;/p&gt;

&lt;h3 id=&quot;lo-script&quot;&gt;&lt;strong&gt;Lo script&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;La funzione si genera un nome file del nome esistente, ad esempio &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;example.ext&lt;/code&gt; → &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;example_compressed.mp4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Poi controlla se il file di destinazione esiste e se è valido utilizzando &lt;a href=&quot;https://ffmpeg.org/ffprobe.html&quot;&gt;&lt;code class=&quot;language-html highlighter-rouge&quot;&gt;ffprobe&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Infine utilizza ffmpeg per generare il video finale.&lt;/p&gt;

&lt;p&gt;Utilizzo &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;find&lt;/code&gt; per cercare tutte le estensioni video che mi vengono in mente ed eseguire la funzione compress.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-euo&lt;/span&gt; pipefail

compress &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;ORIGIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ORIGIN&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dirname&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ORIGIN&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%.*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_compressed.mp4&quot;&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;☑️ Task TODO: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ORIGIN&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -&amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Check if destination already exists and is corrupted&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        if &lt;/span&gt;ffprobe &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; error &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;✅ Task completed: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; already exists&quot;&lt;/span&gt; 
            &lt;span class=&quot;k&quot;&gt;return
        fi
        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;⚠️  File corrupted, removing and recreating: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Compress at 720p, 30fps, H.265 video coding&lt;/span&gt;
    ffmpeg &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ORIGIN&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-map_metadata&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;-movflags&lt;/span&gt; use_metadata_tags &lt;span class=&quot;nt&quot;&gt;-vf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;scale=-2:720,fps=30&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;:v libx265 &lt;span class=&quot;nt&quot;&gt;-crf&lt;/span&gt; 28 &lt;span class=&quot;nt&quot;&gt;-preset&lt;/span&gt; slow &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;:a aac &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt;:a 128k &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;✅ Task completed: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; done&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; compress

find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.MP4&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;compress &quot;$0&quot;&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.MOV&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;compress &quot;$0&quot;&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.MTS&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;compress &quot;$0&quot;&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.mp4&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*_compressed.mp4&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;compress &quot;$0&quot;&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;decluttering-digitale&quot;&gt;Decluttering digitale&lt;/h3&gt;

&lt;p&gt;Facciamo qualche prova random, testiamo che tutti i video siano felicemente compressi e possiamo gettare il cuore oltre l’ostacolo: eliminiamo tutti i video vecchi.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.MP4&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-delete&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# tutte le estensioni video che avete in mente&lt;/span&gt;
find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.mp4&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*_compressed.mp4&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Come nello script sopra dobbiamo distinguere gli  &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;*.mp4&lt;/code&gt; originali da quelli compressi. Nei due esempi usiamo il punto esclamativo (&lt;code class=&quot;language-html highlighter-rouge&quot;&gt;! -name “*_compressed.mp4&lt;/code&gt;) per escludere le foto compresse.&lt;/p&gt;

&lt;h3 id=&quot;mass-import&quot;&gt;Mass import&lt;/h3&gt;

&lt;p&gt;Bene ora che abbiamo il nostro archivio molto piú leggero possiamo fare l’upload di tutto.&lt;/p&gt;

&lt;p&gt;Usiamo &lt;a href=&quot;https://immich.app/docs/features/command-line-interface/&quot;&gt;immich-cli&lt;/a&gt; per fare l’upload di massa. Non é necessario essere sulla stessa macchina di immich per usare la cli, ci basta installarla sulla macchina in cui ci sono le foto(&lt;code class=&quot;language-html highlighter-rouge&quot;&gt;npm i -g @immich/cli&lt;/code&gt; ) e fare login (&lt;code class=&quot;language-html highlighter-rouge&quot;&gt;immich login https://photos.example.com key-from-account-settings&lt;/code&gt;).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;immich upload &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;thats-it&quot;&gt;That’s it&lt;/h2&gt;

&lt;p&gt;Adesso potete decidere cosa farne di foto volanti e backup vari.&lt;/p&gt;

&lt;p&gt;Io sto tenendo immich come servizio primario, ho dismesso shotwell dopo 10+ anni e relativi backup e faccio backup di immich.&lt;/p&gt;

&lt;p&gt;&lt;a data-fslightbox=&quot;&quot; href=&quot;/media/posts/2025-03-28-che-me-ne-faccio-dei-video/server_stats.jpg&quot;&gt;
&lt;img src=&quot;/media/posts/2025-03-28-che-me-ne-faccio-dei-video/server_stats.jpg&quot; alt=&quot;Schermata delle statistiche&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 28 Mar 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/03/28/che-me-ne-faccio-dei-video.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/03/28/che-me-ne-faccio-dei-video.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Un nuovo altbot</title>
        <description>&lt;p&gt;Negli ultimi giorni sul metaverso (dalla parte di Mastodon almeno) é apparso un bot molto molto interessante. Si chiama &lt;a href=&quot;https://livellosegreto.it/@altbot@fuzzies.wtf&quot;&gt;@altbot@fuzzies.wtf&lt;/a&gt; e - una volta iscritti al canale, risponde ai tuoi post con immagini proponendo una descrizione fatta con intelligenza artificiale molto ben fatta.&lt;/p&gt;

&lt;p&gt;L’invito é di compilare manualmente la descrizione dell’immagine (alt tag) con il testo prodotto.&lt;/p&gt;

&lt;p&gt;Visto che é un po’ che gioco con &lt;a href=&quot;https://ollama.com/&quot;&gt;ollama&lt;/a&gt; mi é arrivata l’occasione di tirare fuori un client Mastodon che faccia esattamente lo stesso lavoro ma che configuri direttamente lui la descrizione senza ulteriori modifiche a mano.&lt;/p&gt;

&lt;p&gt;tl;dr: ecco il repo: &lt;a href=&quot;https://github.com/AlessandroLorenzi/mastodon_alt_text&quot;&gt;AlessandroLorenzi/AlessandroLorenzi/mastodon_alt_text&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;cosa-é-lalt-tag&quot;&gt;Cosa é l’ALT Tag&lt;/h2&gt;

&lt;p&gt;L’alt tag é la descrizione dell’immagine dentro l’html.&lt;/p&gt;

&lt;p&gt;É molto importante per facilitare a chi é non vedente o ipovedente la fruizione dei contenuti web. La maggior parte dei social commerciali questo lavoro lo fa in automatico, ma dispongono di una potenza di calcolo maggiore e sono interessati anche dalla miglior indicizzazione dei contenuti che l’alt tag porta.&lt;/p&gt;

&lt;h2 id=&quot;cosa-é-ollama&quot;&gt;Cosa é Ollama&lt;/h2&gt;

&lt;p&gt;Ollama é un servizio che permette di far girare i modelli LLM in locale. Ce ne sono tanti disponibili dedicati a varie esigenze.&lt;/p&gt;

&lt;p&gt;É anche possibile “chattare” direttamente con ollama tramite riga di comando, ad esempio per utilizzare il modello llava: &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;ollama run llava:7b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La cosa piú interessante peró é fare chiamate api o utilizzare una libreria per integrare l’intelligenza artificiale nel software che stiamo sviluppando. Con python in questo progetto ho utilizzato la &lt;a href=&quot;https://pypi.org/project/ollama/&quot;&gt;libreria ufficiale&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;architettura&quot;&gt;Architettura&lt;/h2&gt;

&lt;p&gt;L’idea é un po’ questa:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Piglio i miei post&lt;/li&gt;
  &lt;li&gt;Chiedo ad Ollama di darmi la descrizione del post&lt;/li&gt;
  &lt;li&gt;La traduco nella lingua desiderata&lt;/li&gt;
  &lt;li&gt;Aggiorno l’immagine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-03-20-un-nuovo-altbot/sequence_diagram.jpg&quot; alt=&quot;sequence Diagram&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Riporto anche in modalitá testuale per coerenza con l’argomento:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;sequenceDiagram
    Servizio-&amp;gt;&amp;gt;+Istanza Mastodon: Nuovo Post?
    Istanza Mastodon-&amp;gt;&amp;gt;-Servizio: Yep, eccotelo
    Servizio-&amp;gt;&amp;gt;+Ollama: Cosa c&apos;é in questa immagine?
    Ollama-&amp;gt;&amp;gt;-Servizio: The pen is on the table
    Servizio-&amp;gt;&amp;gt;+Ollama: Me lo dici in italiano?
    Ollama-&amp;gt;&amp;gt;-Servizio: La penna é sul tavolo
    Servizio-&amp;gt;&amp;gt;+Istanza Mastodon: Aggiorna l&apos;alt dell&apos;immagine: &quot;La penna é sul tavolo&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;la-scelta-dei-modelli&quot;&gt;La scelta dei modelli&lt;/h2&gt;

&lt;p&gt;La parte piú complicata é stata scegliere i modelli per “vedere” l’immagine e poi tradurre.&lt;/p&gt;

&lt;p&gt;I modelli vision candidati finali sono:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://ollama.com/library/llava&quot;&gt;llava&lt;/a&gt;&lt;/strong&gt;: (che é quello che ha vinto) genera una descrizione molto dettagliata e precisa. Di contro é che é un po’ pesante e impiega un po’ di tempo a generare la descrizione (sul mio serverino sfigato senza GPU) e genera un testo molto lungo. E non sono riuscito a limitarlo con il prompt. L’idea iniziale era mettere la descrizione sia in italiano che in inglese ma mi sono scontrato con il limite dei 1500 caratteri.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://ollama.com/library/moondream&quot;&gt;moondream&lt;/a&gt;: é l’esatto opposto di llava, genera delle descrizioni che circa piú o meno ci siamo pressappoco. In compenso é molto molto leggero e risponde molto velocemente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I modelli per la traduzione invece:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://ollama.com/library/mistral-nemo&quot;&gt;mistral-nemo&lt;/a&gt;&lt;/strong&gt;: tra i vari provati ha prodotto un buon risultato.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://ollama.com/library/deepseek-r1&quot;&gt;deepseek-r1&lt;/a&gt;: menzione di disonore per deepseek che mi ha generato una roba illegibile impiegando tantissimo tempo. Riporto in fondo il &lt;a href=&quot;#il-ragionamento-di-deepseek&quot;&gt;risultato finale&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qualsiasi consiglio su modelli da testare (ma in realtá su tutto) é sempre bene accetto.&lt;/p&gt;

&lt;h2 id=&quot;show-me-the-code&quot;&gt;Show me the code!&lt;/h2&gt;

&lt;p&gt;Un paio di “pezzi” principali di codice:&lt;/p&gt;

&lt;h3 id=&quot;il-loop-principale&quot;&gt;Il loop principale&lt;/h3&gt;

&lt;p&gt;Al boot il client richiede gli ultimi 10 post, giusto per vedere se mentre era spento (shit happens) sia stato pubblicato qualche articolo.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Starting the bot...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mastodon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;my_toots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mastodon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;account_statuses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_toots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;elaborate_toot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fatto questo, una volta che abbiamo l’ultimo post pubblicato iniziamo a fare un loop su tutti i post nuovi che arrivano ogni 60 secondi&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;last_seen_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_toots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Checking for new toots...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;new_toots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mastodon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;account_statuses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;since_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_seen_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_toots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;elaborate_toot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;last_seen_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;la-chiamata-a-ollama&quot;&gt;La chiamata a ollama&lt;/h3&gt;

&lt;p&gt;Questa funzione utilizza la libreria di ollama per chiamare il servizio locale. Gli passiamo il modello (&lt;code class=&quot;language-html highlighter-rouge&quot;&gt;llava:7b&lt;/code&gt;), il prompt (“&lt;em&gt;describe the image&lt;/em&gt;”) e infine il path dell’immagine.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extract_description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Extracting description from image &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ollama&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;llava:7b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Describe the image&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;images&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;download-e-cancellazione-dellimmagine-temporanea&quot;&gt;Download e cancellazione dell’immagine temporanea&lt;/h3&gt;

&lt;p&gt;Non avevo mai sviluppato una classe che potesse essere usata con &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;with&lt;/code&gt; prima d’ora. Ecco qui!&lt;/p&gt;

&lt;p&gt;La classe &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;ImageDownloader&lt;/code&gt; scarica l’immagine in un file temporaneo all’interno del metodo &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;__enter__&lt;/code&gt;, ripassa il controllo alla funzione chiamante e infine elimina l’immagine temporanea nel metodo &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;__exit__&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ottimo per non lasciare sporcizia in giro.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ImageDownloader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tempfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mktemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__enter__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Downloading image from &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;wb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__exit__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc_val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc_tb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Removing image &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Come si usa poi:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;syntax&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ImageDownloader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://example.com/example.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Qui l&apos;immagine esiste
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;do_suff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Qui non esiste piú
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rage-moment&quot;&gt;Rage moment&lt;/h2&gt;

&lt;p&gt;Non puoi modificare un’immagine collegata a un post. Ho perso un po’ di tempo a usare &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;media_edit&lt;/code&gt; quando invece avrei dovuto utilizzare &lt;code class=&quot;language-html highlighter-rouge&quot;&gt;media_post&lt;/code&gt; e poi modificare il post sostituendo l’immagine.&lt;/p&gt;

&lt;p&gt;Era nella documentazione? Sí, ma scritta in piccolo!&lt;/p&gt;

&lt;h2 id=&quot;risultato-finale&quot;&gt;Risultato finale&lt;/h2&gt;

&lt;p&gt;Ho fatto una foto del mio adorato Cthulhu e l’ho postata &lt;a href=&quot;https://livellosegreto.it/@alorenzi/114196307419000353&quot;&gt;sul mio account Mastodon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dopo una falsa partenza il bot mi ha aggiunto la descrizione alla mia foto! 🎉&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-03-20-un-nuovo-altbot/risultato.jpg&quot; alt=&quot;Una foto del risultato&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;prossimi-passi&quot;&gt;Prossimi passi&lt;/h2&gt;

&lt;p&gt;Un possibile ampliamento di questo progetto é aggiungere hashtag automatici ai miei post.&lt;/p&gt;

&lt;p&gt;Un secondo progetto che sto valutando riguarda il mio archivio di foto. La scorsa settimana ho fatto il setup di &lt;a href=&quot;https://immich.app/&quot;&gt;immich&lt;/a&gt;. Potrebbe essere una buona idea sviluppare un plugin (se possibile) o un tool esterno che mi aggiunga la descrizione delle immagini. Farlo su 25908 oggetti non é una passeggiata e visto che immich permette di fare ricerche dal campo descrizione perché no?&lt;/p&gt;

&lt;h2 id=&quot;il-ragionamento-di-deepseek&quot;&gt;Il ragionamento di deepseek&lt;/h2&gt;

&lt;h3 id=&quot;input&quot;&gt;Input&lt;/h3&gt;

&lt;p&gt;translate in italian: In the center of a cozy living room, a light brown dog sits attentively on the wooden floor. The dog’s gaze is di
… rected towards a red toy airplane that lies next to it. A black chair stands nearby, and a window with white curtains allows soft natur
… al light to filter into the room.&lt;/p&gt;

&lt;h3 id=&quot;reasoning&quot;&gt;Reasoning&lt;/h3&gt;

&lt;p&gt;Okay, I need to translate this sentence into Italian. Let me read through it again to make sure I get all the details right.&lt;/p&gt;

&lt;p&gt;“In the center of a cozy living room, a light brown dog sits attentively on the wooden floor.”&lt;/p&gt;

&lt;p&gt;So “In the center” can be translated as “al centro di.” A cozy living room is “un camino dolcissimo.” The light brown dog would be “un cagnonegno lievo.” Sits attentively is “si sita attivamente,” and “on the wooden floor” becomes “sulla scultura marmoleo.”&lt;/p&gt;

&lt;p&gt;Next part: “The dog’s gaze is directed towards a red toy airplane that lies next to it.”&lt;/p&gt;

&lt;p&gt;Starting with “Il cagnonegno gira la vista” for looking at something. Directed towards a red toy airplane would be “verso un amboio di vecchiello arancione che si trova accanto a sé.” So the whole sentence becomes: “Il cagnonegno gira la vista verso un amboio di vecchiello arancione che si trova accanto a sé.”&lt;/p&gt;

&lt;p&gt;Then, “A black chair stands nearby,” which translates to “e nastra sedia scivolo vicino.” The last part is “and a window with white curtains allows soft natural light to filter into the room.” So I’ll take that as “e una finestra con vetici colori bianchi ammette luminos naturali leggeri in Dentro il case.”&lt;/p&gt;

&lt;p&gt;Putting it all together, making sure the flow is smooth and the translation captures each element accurately.&lt;/p&gt;

&lt;h3 id=&quot;output&quot;&gt;Output&lt;/h3&gt;

&lt;p&gt;Nel centro di un camino dolcissimo, un cagnonegno lievo si sita attivamente sulla scultura marmoleo. Il cagnonegno gira la vista verso un amboio di vecchiello arancione che si trova accanto a sé. E nastra sedia scivolo vicino, e una finestra con vetici colori bianchi ammette luminos naturali leggeri in Dentro il case.&lt;/p&gt;
</description>
        <pubDate>Thu, 20 Mar 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/03/20/un-nuovo-altbot.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/03/20/un-nuovo-altbot.html</guid>
        
        
      </item>
      
    
     
      <item>
        <title>Apriti Sesamo</title>
        <description>&lt;p&gt;Da quando ho la cana faccio avanti e indietro casa per passeggiare almeno quattro volte al giorno: la mattina appena svegli, pausa caffè, pranzo, post lavoro, prima di nanna. Non tutti sempre, ma insomma, mi piace sgranchirmi le gambe di tanto in tanto.&lt;/p&gt;

&lt;p&gt;E ogni volta che ritorno a casa parte la ricerca le chiavi nelle tasche dei pantaloni, giacca, felpa, zaino. Tutto questo con il guinzaglio in mano. Il telefono invece chissà perché so sempre dove sta.&lt;/p&gt;

&lt;h2 id=&quot;domotizziamo-cancelletto-e-portoncino&quot;&gt;Domotizziamo cancelletto e portoncino&lt;/h2&gt;

&lt;p&gt;Un po’ di tempo fa ho preso un oggettino che si attacca al citofono, si collega al wifi e con l’app apri da dove ti pare. Cosí mentre cammino ho tutto il tempo di cercare il telefono e trovarmi con cancello e portoncino aperto.&lt;/p&gt;

&lt;p&gt;Siamo nel 3000, circa.&lt;/p&gt;

&lt;p&gt;L’app e il widget sono carucci, non sempre peró super reattivi. Ogni tanto se tento di aprire dal widget si blocca, dice che non puó raggiungere il dispositivo, poi apri l’app, ci mette un po’ a svegliarsi e va tutto.&lt;/p&gt;

&lt;h2 id=&quot;piú-automazione&quot;&gt;Piú automazione!&lt;/h2&gt;

&lt;p&gt;L’altro giorno mi é venuta questa idea, ma se si aprisse in automatico quando mi avvicino?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-03-18-apriti-sesamo/schema.jpg&quot; alt=&quot;schema&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Si puó fare!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ho reinstallato HomeAssistant dopo molti molti anni che non lo usavo, ho importato tutti gli aggegi domocosi vari che ho in casa e installato l’app sul telefono.&lt;/p&gt;

&lt;p&gt;Da qui é stato abbastanza semplice configurare un trigger:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When: il mio telefono entra in zona “Casa”&lt;/li&gt;
  &lt;li&gt;And if: (niente)&lt;/li&gt;
  &lt;li&gt;Then do: premi il bottone di ingresso&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/media/posts/2025-03-18-apriti-sesamo/screenshot.jpg&quot; alt=&quot;schema&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;come-sta-andando&quot;&gt;Come sta andando&lt;/h2&gt;

&lt;p&gt;Per sicurezza ho attivato le notifiche dell’app di quando si apre il cancello. Nel giro di tre giorni non ho avuto né falsi positivi né falsi negativi.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Non mi ha mai aperto il cancello “a caso”, se non ha la posizione gps e poi la ritrova passa da stato “unknown” a localizzato, ma non apre il cancello. E questa era la cosa piú critica.&lt;/li&gt;
  &lt;li&gt;Arrivato davanti casa il cancello era sempre aperto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Installeró un aggeggio simile anche per la porta di casa? Per ora non penso, finché é il cancelletto e il portone ci pensano giá i miei vicini a lasciarli aperti a caso, quindi un’apertura accidentale non sarebbe grave. Ma per la porta di casa ho qualche remora in piú.&lt;/p&gt;

&lt;p&gt;Sono decisamente soddisfatto della cosa.&lt;/p&gt;
</description>
        <pubDate>Tue, 18 Mar 2025 00:00:00 -0500</pubDate>
        <link>https://alorenzi.eu/2025/03/18/apriti-sesamo.html</link>
        <guid isPermaLink="true">https://alorenzi.eu/2025/03/18/apriti-sesamo.html</guid>
        
        
      </item>
      
    
  </channel>
</rss>