Category Archives: small things

Converting lots of audio files to lower quality with soundKonverter

Notes for myself but maybe useful for *you* too?

https://github.com/dfaust/soundkonverter

Add your directory or directories, let it scan.

For music select Opus with 48 kbps if that’s enough for your use case.

Create the file list, then fix special characters with https://github.com/dfaust/soundkonverter/issues/96: sed -i 's/file:\/\///; s/%20/ /g; s/%23/#/g' ~/.local/share/soundkonverter/filelist.xml

For audiobooks use Opus with a low bitrate of 16 kbps and the Additional encoder argument -ac 1 for mono.

Copy directory structure will create full path directories in the destination directory, e.g. if you convert /home/foo/music/ to /tmp/, it will create the output in /tmp/home/foo/music/.

For future updates: Select the same directories, fix the xml again, make sure that Settings -> General -> Conversion -> Conflict Handling is set to “Skip File”.

A Klaus Schulze inspired, animated QGIS geometry generator doodle

Found this

Made that

With an empty inverted polygon layer, the canvas on 0 0,

with_variable(
  'line_star',
  collect_geometries(
    with_variable(
      'buffered_point_array',
      geometries_to_array(
        nodes_to_points(  
          buffer(make_point(0,0), distance:=100, segments:=42),
          ignore_closing_nodes:=True
        )
      ),
      array_foreach(
        @buffered_point_array,
        make_line(
          @canvas_cursor_point,
          @element
        )
      )
    )
  ),
  with_variable(
    'donut_line_star',
    difference(
      @line_star,
      buffer(
        @canvas_cursor_point,
        distance:=sin(scale_linear(epoch(now())%10000/100, 0, 100, -pi(), pi()))*30+30,  -- %10000/100 = 0-100
        segments:=42
      )
    ),
    collect_geometries(
      @donut_line_star,
      intersection(
        rotate(@donut_line_star, 1),
        translate(
          buffer(
            @canvas_cursor_point, 
            distance:=sin(scale_linear(epoch(now())%10000/100, 0, 100, -pi(), pi()))*50+50,  -- %10000/100 = 0-100
            segments:=42
          ),
          sin(scale_linear(epoch(now())%10000/100, 0, 100, -pi(), pi())),  -- %10000/100 = 0-100
          0
        )
      )
    )
  )
)

and an arrow style with feature blending.

Backing up Hetzner snapshots locally

Hetzner is a nice, cheap host for server. Unfortunately they do not let you download backups and snapshots of cloud servers locally. So you are kind of locked in with them.

Here is how I create full disk backups for e.g. standard CX11 servers with default images.

Make sure you understand everything before you attempt this. Pay special attention to your own partitions and make sure you archive what you really need. Consider imaging the whole device instead of just a partition.

Create a backup

  • Create a new snapshot of your server
  • Create a new server from it
  • Boot said server in rescue mode
  • Use good old dd and gzip to image the main disk to a local archive
  • ssh root@SERVERIP "dd if=/dev/sda1 bs=1M status=progress | gzip -" | dd of=SERVERIP.sda1.dd.gz bs=1M
    • The bs=1M is fairly random by me, worked well, didn’t care to optimize
    • gzip (with the default compression level) kind of maxed out the server CPU but still enabled me to almost max out my download bandwidth. Of course the ratio between remote CPU compression speed vs download bandwidth depends on your specific situation. You might want to use xz or zstd instead.
  • Don’t be stupid, do it twice and compare the checksums

If you do not need your server to be live during backup, you can skip the snapshotting and second server of course, just boot your server in rescue mode instead.

Build a new server from a backup

  • Create a new server using the same or a similar configuration as the backed up one
  • Boot said server in rescue mode
  • cat SERVERIP.sda1.dd.gz | ssh root@SERVERIP "gunzip -c | dd of=/dev/sda1 bs=1M status=progress conv=fsync"
  • Reboot to leave rescue mode

If you want to restore your server because of a breakage, just boot it into rescue mode and do the same as above otherwise.

10 year old posts from an older blog at enjoys.it

Just for save-keeping, probably irrelevant nowadays but who knows what kind of travelers search engines might send here. Tread lightly!

Remove the huge margins from PDF papers

Remove the huge margins from PDF papers eg. prior to printing with pdfcrop from the pdftk suite. For example:

pdfcrop --margins -80 input.pdf output.pdf

edit, much better:

$ pdfimages -j file.pdf file
$ mogrify -crop 800x1300+220+220 +repage file-0*.jpg
$ convert file-0*.jpg cropped.pdf

+repage makes IM not write the offset to the files but actually crop “properly”. Maybe pdfcrop has such parameter too?

Installing a printer in Cups via a USB->Serial adapter

Make sure to “modprobe usbserial“. dmesg should show a printer being connected if you plug it in now. Then Cups should see it too.

RTTY with SDR# and fldigi (for the german DWD stations)

In SDR#: Use USB, filter bandwidth 1000. center the RTTY in your window.

In fldigi: Op Mode -> RTTY -> Custom. Set the carrier shift to custom and then enter 450 in the custom shift field below. Baud rate: 50, 5 bits per character, no parity, 1.5 stop bits. Save and Close. Make sure the Rv button is green!

CW decoding with SDR# and fldigi

In SDR#: Use the CW-L or CW-U preset. Tune so the morse code is right in the middle of your “reception window”.

In fldigi: Op Mode -> CW. Turn off squelch by making the SQL button not green but grey.

It works very well for non-human morse for me. Radio amateur morse is harder and so far full of “spelling errors”. :)

PDF to image with imagemagick/graphicsmagick

If you want to create images from PDF files, use for example mogrify -verbose -geometry 1600 -density 300 -format png *.pdf Without a decent “-density” parameter, you will probably get a blurry image as result.

Making your Ryzen CPU less hot by throttling boost on Linux

echo 0 | tee /sys/devices/system/cpu/cpufreq/boost

Might work, might not, depending on unknown factors. Whatever, I just wanted to make some all-core-but-unimportant process to run without going 95°C. For that it worked perfectly well. CPU temps of a Ryzen 5 3600 after many hours of full utilization were at ~65°C. CPU frequencies were capped to 3.6GHz with this while jumping up to 4.2GHz (and ~94°C) without.

Obviously this has an impact on performance.

To re-enable just echo a 1 instead. This is reset anyways when you reboot your system.

Using a Tiardey USB Single Foot Pedal (PCsensor FootSwitch) on Linux

This post’s purpose is to link “Tiardey USB Single Foot Pedal Optical Switch Control One Key Programm Computer Tastatur Maus Game Action HID” to “PCsensor” and the footswitch tool on search engines so others who wonder if the device is easy to use on Linux learn that this is the case. Hope it helps!

I bought this https://www.amazon.de/dp/B09TQFBS3C which came with a chinese/manual saying “FS2007 User Manual” and also says “FS2007U1SW (mechanical switch)” (mine clicks, so I guess it is not the “FS2007U1IR (silent photoelectric switch)”. The manual links to pcsensor.com for Windows drivers.

Plugin the device. dmesg should show something like:

[Sun Jan 8 20:25:05 2023] usb 1-4: new full-speed USB device number 7 using xhci_hcd
[Sun Jan 8 20:25:05 2023] usb 1-4: New USB device found, idVendor=1a86, idProduct=e026, bcdDevice= 0.00
[Sun Jan 8 20:25:05 2023] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[Sun Jan 8 20:25:05 2023] usb 1-4: Product: FootSwitch
[Sun Jan 8 20:25:05 2023] usb 1-4: Manufacturer: PCsensor
[Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:1A86:E026.0001/input/input19
[Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch Mouse as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:1A86:E026.0001/input/input20
[Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:1A86:E026.0001/input/input21
[Sun Jan 8 20:25:06 2023] hid-generic 0003:1A86:E026.0001: input,hidraw0: USB HID v1.11 Keyboard [PCsensor FootSwitch] on usb-0000:00:14.0-4/input0
[Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.1/0003:1A86:E026.0002/input/input22
[Sun Jan 8 20:25:06 2023] hid-generic 0003:1A86:E026.0002: input,hidraw1: USB HID v1.10 Device [PCsensor FootSwitch] on usb-0000:00:14.0-4/input1
[Sun Jan 8 20:25:06 2023] usbcore: registered new interface driver usbhid
[Sun Jan 8 20:25:06 2023] usbhid: USB HID core driver
[Sun Jan 8 20:25:10 2023] usb 1-4: reset full-speed USB device number 7 using xhci_hcd

Sweet, so it is just some rebranded PCsensor device.

lsusb says ID 1a86:e026 QinHeng Electronics FootSwitch btw.

There is a great little tool for configuring those on Linux: https://github.com/rgerganov/footswitch

footswitch -m ctrl -k 1 will configure it to send Ctrl+1 when pressed for example. See the readme for usage and more examples.

You can use more than 3 of these devices via this pull request. I have four connected via a USB hub 1a40:0101 (“Terminus Technology Inc. Hub (branded “hama”), https://www.amazon.de/dp/B08YRZT1RL) and they work just fine.

Converting a whole directory tree of FLAC files to opus/vorbis and deleting the originals

Because I just did it and might need to do it again, e.g.:
fd -t f -e flac -x bash -c 'ffmpeg -i "$1" -b:a 64k "$1".ogg && echo rm "$1"' bash {}

Remove the echo to make it actually delete the originals.

via https://wiki.archlinux.org/title/Convert_FLAC_to_MP3#Parallel_with_recursion

Or to write them to another directory, keeping the original structure intact:

cd /dir/to/convert && fd -t f -e flac -x bash -c 'D=$(dirname "{}"); B=$(basename "{}"); mkdir -p "/dir/to/write/to/$D"; ffmpeg -i "{}" "/dir/to/write/to/$D/${B%.*}.opus"' bash {}

via https://quantixed.org/2021/11/20/convertible-using-ffmpeg-to-convert-audio-files/

^ Nope, that seems to miss files…

You should probably use beets or something…

soundKonverter is a nice tool too.

Waggawaggawaggawagga animated ducks in QGIS

I used ne_110m_admin_0_countries.

Rendering updates for the layer at 0.1 seconds.

Geometry Generator for a Point for the marker location via line_interpolate_point:

with_variable(
  'biggest_geom',
  geometry_n(order_parts($geometry, 'area($geometry)', ascending:=False), 1),
  line_interpolate_point(
    boundary(@biggest_geom), 
    perimeter(@biggest_geom)*(round(epoch(now())/100)%100/100)
  )
)

Raster Image Marker with https://opengameart.org/content/character-spritesheet-duck, vertical anchor at bottom, sprite choice between walking and running (doesn’t actually work) plus the frame via

with_variable(
  'biggest_geom',
  geometry_n(order_parts($geometry, 'area($geometry)', ascending:=False), 1),
  '/your/path/Duck/Sprites/Walking-Running/'
  || if(perimeter(@biggest_geom) < 10, 'Walking', 'Running')
  || ' 00'
  || to_string(round(epoch(now())/200)%2+1)
  || '.png'
)

Rotation did not work, I tried line_interpolate_angle:

with_variable(
  'biggest_geom',
  geometry_n(order_parts($geometry, 'area($geometry)', ascending:=False), 1),
  line_interpolate_angle(
    boundary(@biggest_geom), 
    perimeter(@biggest_geom)*(round(epoch(now())/100)%100/100)
  )
)

Steps via two more Geometry Generators, both for Lines using line_substring and some nice style (inspired by the wonderful built-in cat trail preset):

with_variable(
	'biggest_geom',
	geometry_n(order_parts($geometry, 'area($geometry)', ascending:=False), 1),
  	line_substring(
	  boundary(@biggest_geom), 
	  0,
	  perimeter(@biggest_geom)*(round(epoch(now())/100)%100/100)
	)
)

Could be improved if (for example) Raster Image Marker would support:

  • Choice of resampling algorithm
  • Flipping
  • Rotation would work, no idea what’s wrong with my expression, it works with random values, so …
  • Whatever is broken with the choice between ‘Walking’ and ‘Running’ in the file path expression

Tablets supported by Lineage OS in 2021

Looking for a 10 inch tablet with proper, official Lineage OS support I ended up on the device database. Unfortunately they do not have a simple list of device types. So I wrote some code to extract the tablets with support of at least version 17. The list is short…:

7 inch tablets supported by Lineage OS in 2021

Google Nexus 7 2013 (Wi-Fi, Repartitioned) [flox]

10 inch tablets supported by Lineage OS in 2021

Samsung Galaxy Tab S5e (LTE) [gts4lv]
Samsung Galaxy Tab S5e (Wi-Fi) [gts4lvwifi]
Samsung Galaxy Tab S6 Lite (Wi-Fi) [gta4xlwifi]

Comment if you need an update in the future.