Create GIF from video using ffmpeg

18.02.2025

After developing code for a new approach for handling parameters in FreeCAD I wanted to present it to other FreeCAD users to get some feedback. Of course, the code is still a prototype, but it is working and shows the intended workflow, so I wanted to know if other people also think something like this is useful.

To present it, I wanted to show a small video, but the forum only allows files up to 1MB. So I wanted to create a small GIF showing the essentials.

To capture the video from the FreeCAD window under Windows I used OBS Studio with the FreeCAD window as video source. This way I got a Prototype.mkv video showing the workflow.

Then I converted the video via ffmpeg to get the Prototype.gif file:

ffmpeg -ss 2 -t 50 -i Prototype.mkv -vf "setpts=PTS/2,fps=1,crop=1547:1080:0:0,scale=1024:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 Prototype.gif

I applied filtering to get the file size down:

  • -ss 2 to skip the first two seconds
  • -t 50 to convert the next 50 seconds, so the interval that is converted is [2;52] seconds
  • setpts=PTS/2,fps=1 to make the GIF 2 times faster then the captured video and have 1 image per second in the GIF
  • crop=1547:1080:0:0,scale=1024:-1:flags=lanczos to crop to the main window, scale the image down to 1024 pixels height to get a smaller file size
  • split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse to split the input to two virtual outputs s0 and s1, where s0 is used to generate the GIF color palette and s1 will use the generated GIF color palette
  • -loop 0 to let the GIF loop indefinitely

Now I had everything to create a post in the FreeCAD forum.

Setup Raspberry Pi to serve a Laravel based website

06.02.2025

The official website of Laravel has already a documentation on howto install it on a Linux OS, but it requires to trust the installer script. This would have been run directly on the local machine without prior checking the contents and what is really done. Of course I manually checked the install script and did not like what I found. The installed elements would not be tracked by the package manager, it would install another certificate authority list for the local installation. Things I consider non-maintainable or unsafe. So I wanted to go another (more clean?) way on a Raspberry Pi.

  1. First I needed to install the necessary tools using the commandline.
    • I wanted to use nginx to serve the websites.
    • I wanted to use php-fpm because it is faster than the apache and/or cgi combinations. And of course because it runs on a Raspberry Pi.
    • I needed composer for php packages.
    aptitude install nginx php-fpm composer
    
  2. I then configured nginx to serve a new site by adding a file /etc/nginx/sites-available/laravel-www:

    server {
         listen 80 default_server;
         listen [::]:80 default_server;
    
         root /var/www/laravel-www;
    
         index index.php;
    
         server_name _;
    
         charset utf-8;
    
         location / {
                 try_files $uri $uri/ /index.php?$query_string;
         }
    
         location = /favicon.ico { access_log off; log_not_found off; }
         location = /robots.txt  { access_log off; log_not_found off; }
    
         error_page 404 /index.php;
    
         location ~ \.php$ {
                 fastcgi_pass unix:/run/php/php-fpm.sock;
                 fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
                 include fastcgi.conf;
                 fastcgi_hide_header X-Powered-By;
         }
    }
    

    This already contains the necessary parts for serving on a HTTP server (no SSL here at the moment!) using the installed PHP version. I used the version-free php-fpm symlink so updating/changing to another PHP version is easier later.

  3. The site was then activated to be served already, as it was not public on the internet:
    ln -s /etc/nginx/sites-available/laravel-www /etc/nginx/sites-enabled/laravel-www
    nginx -s reload
    
  4. Now I used composer to get the basic laravel installation:
    cd /var/www/
    mkdir laravel-www
    composer create-project laravel/laravel laravel-www
    
  5. For the installation to work, I needed to setup some access rights, as nginx is running as www-data user:
    chown -R www-data.www-data /var/www/laravel-www
    
  6. For the Laravel project itself, my first start should used the sqlite database to just show that the laravel part is working. So I initialized it using the default configurations in the /var/www/laravel-www/.env file via:
    cd /var/www/laravel-www
    php artisan migrate
    
  7. Now I had the basic laravel project up and running (For later reference: Laravel v11.41.3 (PHP v8.2.7))

Using GNU Screen upon SSH login

06.02.2025

Whenever I log into a remote Linux based machine via SSH, I first start a GNU screen session. Any when I forget, I often regret it when I close the session window, as this also terminates the processes I usually want to continue in the background.

To not be able to forget this, I added

# for SSH sessions which are not already in gnu screen -> attach to a detached one or create a new session
if [[ ! -z "${SSH_CLIENT}" && -z "${STY}" ]]; then screen -RR; fi

at the end of ~/.bashrc to automatically reconnect to a previous screen session, or connect to a new screen session if no detached one is available. It does that only for SSH logins and only if the shell is not already inside a screen session (this avoids recursive loops).

Using nginx combined with Pi-hole to block server site tracking

05.02.2025

Pi-Hole is, in my opinion, a great tool for blocking ads, tracking and malware. But sometimes it seems to be blocking a bit too much. One case I identified were sites that would come up as small ads in my Google searches. I still wanted those links to work. My analysis showed that the needed target URL was nicely encoded in the advertisement URL. So I thought of nginx for a solution.

The easy part with nginx is the redirection of one URL to another URL. Just use rewrite or return filters. This works very well, until the URL uses encoded characters. I also wanted to cover this case and did some research on options. The one I found was using perl to do the encoding/decoding.

After installing nginx, I created the file /etc/nginx/sites-available/googleadservices-redirect, linked it to the sites-enabled and used it in a SSL configured nginx instance:

perl_set $localuri '
  sub {
    my $r = shift;
    my $arg_adurl = $r->variable("arg_adurl");
    my $arg_adurl_decoded = $r->unescape($arg_adurl);
    return $arg_adurl_decoded;
  }
';

server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;

  ssl_certificate /etc/nginx/ssl/nginx-self-signed.crt;
  ssl_certificate_key /etc/nginx/ssl/nginx-self-signed.key;

  gzip off;

  server_name www.googleadservices.com;

  return 301 $localuri;
}

As all redirects are only in local networks, self signed certificates created via openssl were good enough:

openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout /etc/nginx/ssl/nginx-self-signed.key -out /etc/nginx/ssl/nginx-self-signed.crt -subj "/CN=www.googleadservices.com"
  -addext "subjectAltName=DNS:www.googleadservices.com,DNS:googleadservices.com,IP:192.168.0.250"

On the other side, I only needed to support most modern software, so I restricted encryption options in /etc/nginx/nginx.conf and enabled the perl module:

http {
  perl_modules perl/lib;
  ...;
  ssl_protocols TLSv1.3;
  ssl_ecdh_curve X25519:prime256v1:secp384r1;
  ssl_prefer_server_ciphers on;
  ...;
}

I redirected the DNS www.googleadservices.com via Pi-hole to the nginx installation and then I had the necessary redirects working locally. Problem solved.

Icon/emoji in bash prompt for easier machine identification

05.02.2025

Using Linux on various machines, I wanted to have something that helped me to identify on which machine I am currently working. The usual bash prompt settings in PS1 indicate this, but I needed to read the text. I wanted something more intuitive. Searching for a solution I found that modern bash is capable of using unicode. So I found my solution.

To get to the needed unicode I used the Emojipedia. There I selected to use 🍓 for a Raspberry Pi device and 🪟 for a Windows Subsystem Linux installation.

To get the icon into the prompt I just copied the unicode character and pasted it into the PS1 prompt in the ~/.bashrc file.

Example:

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\] 🪟:\[\033[01;34m\]\w\[\033[00m\]\$ '