Working Amiga 500

Got a working amiga again. \o/ woot
Needed to replace Paula chip, cleaning and some TLC.

Modulator
Chip donor

Scart cable i’ve got is one without the resistors, so my monitor isn’t detecting the signal.
Using a A520 modulator works. At least RF, don’t know why RCA/composite video isn’t working.

Even a memory expansion and second drive (5.24 inch) are working.

One of the first disks i tested

To do:

  • Fix something to get disk images from and to my pc.
  • (My old catweasel card only fits in a ISA slot which i don’t have any more)
  • I was wrong .. i’ve got a IV Catweasel .. PCI it is
  • Fix scart
  • Fix my Action Replay, which i soldered into a non working state apparently .. 🙂
  • Get a better mouse!
Catweasel IV

Disks to convert:

  • Personal text files from ages ago
  • My first seka demo
  • My oscillator drawing program
  • Other assembly source files

Got another one running today also:

Gluster and Rhev scripts

List Ovirt/RHV VM’s

( curl -s -u admin@internal:secretpassword -k https://ovirt-engine.lab/ovirt-engine/api/vms/ | grep "^        <name>" | cut -f2 -d\> | cut -f1 -d \< | while read;  do
echo "$REPLY"
done ) > list
echo "NOT IN BACKUP"
cat list | while read ; do ls vmbackup/$REPLY.ova 2>/dev/null >/dev/null || echo $REPLY ;done
echo ""
ls vmbackup/*ova | while read ; do
host=$( echo $REPLY | cut -f2 -d/ | cut -f1 -d.)
age=$(stat -c %y $REPLY  | cut -f1 -d" ")
echo "$age $host"
done

Backup: (UPDATE)
While i made my own backup script for Ovirt, i found this ansible based one.
https://github.com/silverorange/ovirt_ansible_backup

Backup Ovirt Engine using ansible

Usage : ansible-playbook -i ovirt-engine.lab, playbook.yml -u root (-k)

## Playbook
---
- hosts: all
  vars:
    ovirt_backup_mode: 'backup'
    ovirt_backup_archive: '/tmp/engine-backup.gzip'
    ovirt_backup_log_file: '/tmp/engine-backup.log'
    ovirt_backup_scope: 'all'
    ansible_python_interpreter: /usr/bin/python3
  roles:
      - ovirt-engine-backup

## roles/ovirt-engine-backup/tasks/main.yml
---
- name: run engine-backup
  shell: 'engine-backup --mode={{ ovirt_backup_mode }} --file={{ ovirt_backup_archive }} --log={{ ovirt_backup_log_file }} --scope={{ ovirt_backup_scope }}'
  tags:
    - skip_ansible_lint
  register: ovirt_backup_status

- name: download engine backup file
  fetch:
    src: "{{ ovirt_backup_archive }}"
    dest: "{{ ovirt_backup_archive }}"
  when: ovirt_backup_status is succeeded

- name: download log file
  fetch:
    src: "{{ ovirt_log_file }}"
    dest: "{{ ovirt_log_file }}"
  when: ovirt_backup_status is failed

Gluster overview

#!/bin/bash
ansible -i inventory all  -m shell -a "/sbin/gluster v info" --become  -K > output
cat output  | grep "^Volume Name"  | sort | cut -c14- | sort | uniq
cat output  | egrep "^Volume Name|^Brick|^Type"   | grep -v Bricks

Gluster to grafana using influx

#!/bin/bash
export PATH=$PATH:/sbin
(
# Get short shotname
host=$(echo $HOSTNAME | cut -f1 -d.)

echo "-- vg info --"
# Get vg info - pool nog doen
vgs --units k | egrep "brick|data0" | while read brickinfo ; do
name=$(echo $brickinfo | awk '{ print $1}'  )
size=$(echo $brickinfo | awk '{ print $6}' | cut -f1 -d.)
free=$(echo $brickinfo | awk '{ print $7}' | cut -f1 -d. | sed s/k//g)
usage=$(echo $(( $size - $free )))
curl -i -XPOST 'http://grafanaserver:8086/write?db=gluster' --data-binary "$host-$name size=$size,free=$free,usage=$usage"
done
echo "-- vg info done --"
echo "-- lv info --"
# Get lv info - these are mountpoints (not bricks)
#lvs --units k | egrep "brick|data0" | grep -v pool | while read volinfo ; do
df  | egrep "brick|data0" | while read volinfo ; do
name=$(echo $volinfo | awk '{ print $1}' | rev | cut -f1 -d/ | rev  )
size=$(df | grep -v svg |grep "$name" | awk '{ print $2}')
usage=$(df | grep -v svg |grep "$name" | awk '{ print $3}')
free=$(df | grep -v svg |grep "$name" | awk '{ print $4}')
curl -i -XPOST 'http://grafanaserver:8086/write?db=gluster' --data-binary "$host-$name size=$size,free=$free,usage=$usage"
done

echo "-- lv info done --"

# Get gluster volumes without gluster command, due to issues running multiple instances
# One volume on one mountpoint ? Then df == volume metrics
: > /tmp/vollist
find /var/lib/glusterd/| grep $HOSTNAME | grep vol$ | while read brickpath ; do
grep brick-path $brickpath | awk '{print $3 }' >> /tmp/vollist
done
mount | egrep "brick|data0" | awk '{print $3 }' | while read mountpoint ; do
count=$(grep $mountpoint /tmp/vollist | wc -l)
if [ $count -lt 2 ] ; then
echo "lv = brick .. df info"
#brick=$(echo $mountpoint)
#volume=$(echo $mountpoint |rev | cut -f1 -d/ | rev)
#size=$(df $mountpoint | grep -v Filesystem | awk '{ print $2 }')
#free=$(df $mountpoint | grep -v Filesystem | awk '{ print $4 }')
#usage=$(df $mountpoint | grep -v Filesystem | awk '{ print $5 }' | sed s/%//g )


dfinfo=$(df $mountpoint | grep -v ^Filesystem)
name=$(echo $dfinfo | awk '{print $1}' | rev | cut -f1 -d/ | rev)
size=$(echo $dfinfo | awk '{print $2}')
usage=$(echo $dfinfo | awk '{print $3}')
free=$(echo $dfinfo | awk '{print $4}')
perc=$(echo $dfinfo | awk '{print $5}' | sed s/%//g)
curl -i -XPOST 'http://grafanaserver:8086/write?db=gluster' --data-binary "$host-$name size=$size,free=$free,usage=$usage"
#curl -i -XPOST 'http://grafanaserver:8086/write?db=gluster' --data-binary "$host-$brick-$volume size=$size,free=$free,usage=$usage"
else
echo "du script draaien voor $mountpoint"
fi

done

echo "-- data% --"
lvs --units k -a -oname,vg_name,size,vgfree,data_percent,pool_lv | grep -v \\[ | egrep  "brick|data" | grep -v sysdata | grep -v "^  thin" | while read ; do
vg=$(echo $REPLY | awk '{print $2}')
name=$(echo $REPLY | awk '{print $6"-"$1}')
size=$(echo $REPLY | awk '{ print $3 }' | cut -f1 -d.)
free=$(echo $REPLY | awk '{ print $4 }' | cut -f1 -d. | sed s/k//g)
dataperc=$(echo $REPLY | awk '{ print $5 }' | cut -f1 -d. )
if [ "w$dataperc" == "w" ] ; then dataperc=0 ;fi
curl -i -XPOST 'http://grafanaserver:8086/write?db=gluster' --data-binary "$host-$name-$vg size=$size,free=$free,dataperc=$dataperc"
done


) 2> /dev/null >/dev/null

Running Ovirt and want a overview of glustermounts in VMs?

run makeinventory.sh (this creats an list of linux hosts which are UP in RHV/Ovirt)

#!/bin/bash
#ik haal een lijst op van virtual machines die aanstaan en linux draaien
#set -x
mkdir -p tmp
rm -f tmp/linuxup
read -p "Username: " x2
read -s -p "Password: " x1
echo " "
curl -s -X GET -H "Accept: application/xml"  --insecure -u $x2@radlan:$x1 https://ovirtserver/ovirt-engine/api/vms | grep "vm href=" | cut -c37-72 > tmp/vms
cat tmp/vms | while read vm ; do
echo -n "."
curl -s -X GET -H "Accept: application/xml"  --insecure -u $x2@radlan:$x1 https://ovirtserver/ovirt-engine/api/vms/$vm > tmp/$vm
done
echo " "
: > tmp/linuxup
find tmp -type f -mtime 0 | egrep -v "vms$|linuxup" | while read ; do

name=$(cat $REPLY | grep -i "^    <name>"| cut -f2 -d\> | cut -f1 -d \<)
os=$(cat $REPLY | egrep "^        <family>" | egrep -v "svw|SVNT|debian|ubuntu|server|spice|vnc|windows_|native" | cut -f2 -d\> | cut -f1 -d \<)
up=$(cat $REPLY |  grep -A1 start_time | tail -1| cut -f2 -d\> | cut -f1 -d \<)


echo $name,$os,$up | grep -v ",," | grep ",up" >> tmp/linuxup

cat tmp/linuxup
echo ""
echo "staat in tmp/linuxup"

done
echo "[all]" > inventory
cat tmp/linuxup | grep "."| grep -i linux | cut -f1 -d, >> inventory

Run get.sh
* ansible on all hosts (inventory) and fetches gluster mounts
* reorders this info
* generates a dot file (graphviz)
* running dot fot a svg/png output for every gluster host

#!/bin/bash
echo "draai eerst makeinventory.sh voor een nieuwe host lijst"
read d
echo "Kijk ook of ansible alle servers kan bereiken"
read d
ansible -i inventory all -m shell -a cat /etc/mtab | grep gluster | while read; do source=$(echo $REPLY | cut -f1 -d" ");dest=$(echo $REPLY | cut -f2 -d" ") ; echo " " ;echo "$source $HOSTNAME:$dest" ;done > gluster
cat gluster  | grep ^s | grep : > gluster.grep

cat gluster.grep  | cut -f1 -d: | sort | uniq | while read gluster ; do

cat header > $gluster.dot
cat gluster.grep | grep $gluster | cut -f1 -d" "| sort | uniq | while read ; do echo "    \"$REPLY\";" ;done >> $gluster.dot
cat middel >> $gluster.dot
cat gluster.grep | grep $gluster| sed s/^/\"/ | sed s/\ /\"\ \-\>\ \"/ | sed s/$/\"\;/ >> $gluster.dot
cat footer >> $gluster.dot
dot $gluster.dot -Tsvg >$gluster.svg
dot -Gsize=9,15\! -Gdpi=100  $gluster.dot -Tpng >$gluster.png
done

A php select page to few them

<form method="post">
<select name="volume">
    <?PHP
    foreach (glob("*.svg") as $filename) {
        echo "<option value=" . $filename .">" . $filename . "</option>";
    }
    ?>
    </select>
 <input type="submit" value="Submit">
</form>
<?PHP
    if (isset($_POST['volume'])){
            $image=$_POST['volume'];
            echo "<img src=\"$image\">";
    }
?>



example below:

Get a list of RHV snapshots and descriptions

#!/bin/bash
: > outlist
read -p  "Username: " user
read -s -p "Password: " pass

curl -X GET -H "Accept: application/xml" -u $user@internal:$pass -k  https://ovirt-engine:443/ovirt-engine/api/vms   | egrep "<name>|snapshots" | grep -v "           " | sed '$!N;s/\n/ /' > templist
cat templist  | cut -f2,3 -d\> | cut -f1,3 -d\< | sed 's/<link href=\"/ /g' | cut -f1 -d\" > templist2
cat templist2 | while read ; do
host=$(echo $REPLY | awk '{ print $1 }')
link=$(echo $REPLY | awk '{ print $2 }')
echo $host >> outlist
curl -X GET -H "Accept: application/xml" -u $user@radlan:$pass -k  https://ovirt-engine:443/$link | egrep "description|date" | grep -v '            <'  >> outlist ; echo "----" >> outlist
done
cat outlist | awk '/Active VM/ {getline; next} { print }' > /tmp/outlist
grep -B3 date /tmp/outlist  |sed -e 's/<[^>]*>//g' > /tmp/snapshots
cat /tmp/snapshots | awk '/----/ {printf "\n%s\n",$0;next} {printf "%s ",$0}' | sed 's/ --*//g' | grep -v '\-\-\-\-' | grep "  " > snapshots

Output:
svr04.lab         Backup              2019-06-28T07:55:28.909+02:00
svr05.lab         upgrade             2019-06-18T14:18:49.745+02:00
svr33.lab         pre_ansible         2019-06-18T14:04:43.569+02:00

Somewhere i've got a snapshot age warn script.
This information was posted in Mattermost when sending the "/snapshots" command

Ansible Playbook to add virtual nics

---
- name: adnic
  hosts: localhost
  gather_facts: false
  become: no


  vars_prompt:
    - name: "username"
      prompt: "IPA username"
      private: no
    - name: "password"
      prompt: "IPA password"
      private: yes
    - name: "server"
      prompt: "server"
      private: no
    - name: "interface"
      prompt: "interface"
      private: no
      default: 'eth1'
    - name: "nicprofile"
      prompt: "dmz or other"
      private: no
      default: 'dmz'

  tasks:
  - name: Obtain SSO token with using username/password credentials
    ovirt_auth:
      url: https://ovirt-engine.lab/ovirt-engine/api
      username: "{{ username }}@internal"
      insecure: yes
      password: "{{ password }}"
    
  - ovirt_nics:
      auth: "{{ ovirt_auth }}"
      vm: "{{ server }}"
      state: "present"
      name: "{{ interface }}"
      network: "{{ nicprofile }}"
      profile: "{{ nicprofile }}"

Ansible playbook to create snapshots

- name: makesnap
  hosts: localhost
  gather_facts: false

  vars_prompt:
    - name: "username"
      prompt: "IPA username"
      private: no
    - name: "password"
      prompt: "IPA password"
      private: yes
    - name: "hostname"
      prompt: "hostname"
      private: no
    - name: "snapshotname"
      prompt: "snapshotname"
      private: no

  tasks:
  - name: Make snapshot
    ovirt_snapshots:
      auth:
        username: "{{ username }}@internal"
        password: "{{ password }}"
        insecure: True
        url: https://ovirt-engine.lab/ovirt-engine/api
      description: "{{ snapshotname }}"
      use_memory: true
      state: present
      timeout: 600
      vm_name: "{{ hostname }}"

Scripts on my domoticz instance

Script NO1:
Below is a script which checks all sensors and switches available on my domoticz instance, and gives me information about last updates.
For example when a device is out of reach or battery empty.

Usage:

Outputs to console, or you can use it in check_mk monitoring.
(For the latter, create a script

vi /usr/lib/check_mk_agent/local/checkfrontdoor
chmod +x /usr/lib/check_mk_agent/local/checkfrontdoor
put in the script 
#!/bin/bash
cd /path/to/script/
./belowscript "Frontdoor" 300 checkmk

Code:

#!/bin/bash
#set -x
# after running once check stateseconds for names
if [ $# -eq 0 ]; then
echo "$(basename $0) - without options .. getting states"
echo "use $(basename $0) "Sensorname" seconds" for check
echo "Getting all states"
: > stateseconds
curl -s -i -H "Accept: application/json" "http://127.0.0.1:8080/json.htm?type=devices&filter=all&used=true&order=Name" | egrep "Name|Last" | grep -v HardwareName |grep -vi levelnames> states
sed -i 'N;s/\n/,/' states
now=$(date +%s)
cat states  | awk '{ print $3" "$4$7$8$9$10$11$12 }' | sed s/,,/,/g |rev | cut -c2- | rev | while read ; do
name="$(echo $REPLY | cut -f2 -d, )"
dater="$(echo $REPLY | cut -f1 -d, | sed s/\"//g)"
#echo $dater
seen=$(date -d "$dater" +%s)
#echo $seen
echo "$name $(( $now - $seen))" >> stateseconds
echo -n "."
done
fi
echo ""
if [[ ! -z "$1" && ! -z $2 ]]; then
checkold=$(cat stateseconds | grep "$1\"" | head -1 | awk '{ print $2 }')
total=$(( checkold - $2 ))
if [ -z $3 ] ; then
if [ $checkold -gt $2 ] ; then echo "$name lastseen longer than $2 seconds ago ($total sec)" ; exit 1 ;fi
else
if [ $checkold -gt $2 ] ; then echo "2 \"$1\" - Sensor older than $2 seconds" ; exit 1
else
echo "0 \"$1\" - Sensor age ok" ; exit 0
fi
fi
fi

Above to your Mqtt broker?

#!/bin/bash
# change 300 ( age below 5 minutes )
# and $2>=900 ( age above 15 minutes )
./agecheck.sh # Updates statefile
cat stateseconds | tr -d '"-/:"_' | sort -n -k2 | awk '$2<=300' | while read; do
sensorname=$(echo $REPLY | awk '{ print $1 }' )
age=$(echo $REPLY | awk '{ print $2 }' )
mosquitto_pub -h 10.1.0.17 -t sensorsage/$sensorname -m "$age"
done

Script NO:2
This is a mqtt speech script with caching sounds, speech generated for me by google

MQTT Part

#!/usr/bin/python
import paho.mqtt.client as mqttClient
import time
import os
import subprocess
import shlex
Connected = False

def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected to broker")
        global Connected
        Connected =True
    else:
        print("Connection failed")

def on_message(client, userdata, message):
    print "Message received: " + message.topic + " : " + message.payload
    fileName = "/home/pi/domoticz/scripts/speech" + " \"" + message.payload + "\""
    print fileName
    args = shlex.split(fileName)
    time.sleep(1)
    p = subprocess.Popen(args)


broker_address = "mqttbroker"
port = 1883
user = "myuser"
password = "mysecretpass"
client = mqttClient.Client("speechcmd")
client.username_pw_set(user, password=password)
client.on_connect = on_connect
client.on_message = on_message

client.connect(broker_address, port=port)
client.loop_start()

while Connected != True:
    time.sleep(0.1)

client.subscribe('speech/cmd')

try:
    while True:
        time.sleep(1)

except KeyboardInterrupt:
    print "exiting"
    client.disconnect()
    client.loop_stop()

Speech part (uses mpg123 to play sound though speaker)

#!/bin/bash
#set -x

INPUT=$*
input2=$(echo $INPUT | base64)
echo "$input2 = $INPUT" >> /home/pi/cache/files-text-relation
if [ -f /home/pi/cache/$input2.mp3 ] ; then
mpg123 -q /home/pi/cache/$input2.mp3 1>/dev/null 2>/dev/null
else
echo not cached
STRINGNUM=0

ary=($INPUT)
for key in "${!ary[@]}"
  do
    SHORTTMP[$STRINGNUM]="${SHORTTMP[$STRINGNUM]} ${ary[$key]}"
    LENGTH=$(echo ${#SHORTTMP[$STRINGNUM]})
    #echo "word:$key, ${ary[$key]}"
    #echo "adding to: $STRINGNUM"
    if [[ "$LENGTH" -lt "100" ]]; then
      #echo starting new line
      SHORT[$STRINGNUM]=${SHORTTMP[$STRINGNUM]}
    else
      STRINGNUM=$(($STRINGNUM+1))
      SHORTTMP[$STRINGNUM]="${ary[$key]}"
      SHORT[$STRINGNUM]="${ary[$key]}"
    fi
done

for key in "${!SHORT[@]}"
  do
    #echo "line: $key is: ${SHORT[$key]}"

    echo "Playing line: $(($key+1)) of $(($STRINGNUM+1))"
    NEXTURL=$(echo ${SHORT[$key]} | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g')
echo $NEXTURL
    mpg123 -w $input2 -q "http://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&q=$NEXTURL&tl=En-us"
    ffmpeg -i $input2 -codec:a libmp3lame -qscale:a 2 /home/pi/cache/$input2.mp3
mpg123 /home/pi/cache/$input2.mp3
done
fi

set msg.payload to “Doorbell”
and Mqtt topic to “speech/cmd”

To be continued !

Cold smoke

Today some smoking again.

Salmon and cheese

For curing the salmon (500gr) i used:

  • 100 gr seasalt
  • 80gr licht caster sugar
  • 3 teaspoons dille
  • 1 teaspoon crushed juniper berries

Dry salmon, put a layer of above mixture in a container, put the salmon on top, with another layer. Put a heavy weight ontop to squeeze the water out of the salmon, while its in the refrigerator. Next day: Wash the salmon, drying it with paper kitchentowel. Put the salmon back into the refrigerator again to dry some more.
I’ve put the salmon in my smoker with a cold smoke generator for 8 hours, the cheese needed only 2 hours.

Little book with jokes and programs.

A long time ago i took a book about doing funny stuff in dos, and wrote own additions in the sidelines of the book. Or used the empty pages.

It contains jokes using autoexec.bat and config.sys. Additions by me are most of the time things you could do with debug.com, a little program which existed on any pc at that time.

A little program which created static on a CGA or Hercules monitor. Yes, that long ago. CGA provided 16 colors in 80×25 or 40×25 text modes, but only four colors at 320×200 resolution and two colors at 640×200. Hercules was only monochrome and a max resolution of 720×348. It was on a hercules card i made my first copperbar. ( Before the effect was named copperbar ). Due to difference in timing on every machine, you had to get the copperbar timing right by using two keys i’d assigned the timing to.

MOV AL,00                      # Fill AL register with 0
MOV DX,0x03D8 (cga) 03B8 (herc)# DX with address
OUT DX,AL                      # Set address with AL
MOV AL,[0101]                  # Reg AL with contents 
INC AL                         # Increment AL
MOV [0101],AL                  # Address fill with AL
JMP 100                        # Jump to start

The opcodes for the program :

b0 00
66 ba d8 03
ee
a0 41 00 00 00  
fe c0
a2 41 00 00 00 
e9 60 00 00 00

Sometimes i put these little programs in autoexec.bat, so at next restart of the pc, it would do something weird. My little BOFH jokes. Friends and computerstores where not safe.

Another example:

Two drives in a PC ? (Wie A: zegt moet ook B: zeggen)
Use with care, below will f*ck up your drives. (And makes a lot of noise while doing so.)

MOV DX,0x03F2
MOV AL,71
OUT DX,AL
MOV AL,74
OUT DX,AL
JMP 100

( https://en.wikipedia.org/wiki/Floppy-disk_controller )


C64 plus drive running again

20220502: Fixed another C64, PIA (Peripheral Interface Adapter) was dead, luckily i’ve got several spare-part c64’s. So that was a easy fix.

20220504: Got my sd2iec adaptor in, see bottom of this page.

Booting with a power cartridge
None of my old computers was unmodified
Demo by my old friend Sepp

Drive is a 1541model 2

De wires are going to the DOUT pins of the memory chips. Showing activity using leds. Sometimes i monitored CS .. also informative.

SD2IES Cardreader

Little small funky gadget, it replaces a 1541 Floppy drive with a SDCard reader where you can store a lot of floppydisk images on.
More on this later.

NOTE : Doesn’t work together with my KCS Power cartridge.

I’ve tested two cartridges.

Final cartridge III fastload test on a program did ~3 seconds. ( Normal load time ~17 seconds. ) KCS powercartridge didn’t work. Tip: press `runstop` when using FC3 while turning on to get into basic not the desktop.

FFmpeg tricks

Mp4 to gif (resize, cut and convert)

startsecond=0
duration=3
ffmpeg -ss $startsecond -t $duration -i 'input.mp4' -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output.gif

Gif to MP4

ffmpeg -i kanban.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" gifkanban.mp4

Converting MP4 for Davinci MOV

ffmpeg -i input.mp4 -c:v dnxhd -profile:v dnxhr_hq -pix_fmt yuv422p -c:a pcm_s16le -f mov output.mov

And back from Davinci to MP4

ffmpeg -i render.mov -c:v libx264 -pix_fmt yuv420p -crf 16 -force_key_frames 'expr:gte(t,n_forced/2)' -bf 2 -vf yadif -use_editlist 0 -movflags +faststart -c:a aac -q:a 1 -ac 2 -ar 48000 -f mp4 out.mp4

QTVR to png (note number of frames)

ffmpeg -i ../test.mov %02d.png
ffmpeg -i %02d.png -vf "tile=1x24,transpose=1" mh.png

Nikon MOV to mp4 (no reencoding)

ffmpeg -i input.mov -c copy -movflags +faststart  output.mp4

Nikon MOV to mp4 (problems with audio?
“Could not find tag for codec pcm_s16le in stream #1, codec not currently supported in container”

ffmpeg -i input.mov -c copy -c:a aac -b:a 128k -movflags +faststart  output.mp4
Maybe add -strict experimental 

MPG to MP4 (Not happy with this one)

ffmpeg -i vhs-rip.mpg"  -c:v libx264 -crf 10 -strict -2 1993-luv.mp4

FLV to MP4

ffmpeg -i filename.flv -c:v libx264 -crf 19 -strict experimental filename.mp4

Lossless cut with ffmpeg

ffmpeg  -ss 00:$2 -t 00:$3 -i $1 -vcodec copy -an cut_$1  
# an = no sound
# use -acodec copy for same codec as original audio

Timelapse JPG to MP4

ffmpeg -f image2 -r 24 -start_number 8296 -i "750_%04d.JPG"  -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast -vf scale=1920:1080 b.mp4

png to gif from a list

#cat png.list
file off.png
duration 1
file 20.png
duration 1
file 40.png
duration 1
file 60.png
duration 1
file 80.png
duration 1
file 90.png
duration 1
file 100.png
duration 1

# ffmpeg -f concat -i png.list -loop 0 hexlight.gif


Rotate mp4 clockwise/anticlockwise

ffmpeg -i VID20230110132531.mp4 -filter:v transpose=2 -c:v libx264 -preset veryfast -crf 22 -c:a copy -metadata:s:v rotate="" test.mp4

Concat video together

ffmpeg -f concat -i inputs.txt -c copy merge.mp4
inputs.txt
file start.mp4
file end.mp4


Error “width/height not divisible by 2 (1301×933)”

ffmpeg -i input.mp4 -vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" output.mp4

Dvd/DV/Mpg etcetera overviews

I made two scripts, which take a movie, find out its lenght divide by 9. And generates a image montage of snapshots at certain times in the movie. ( A movie of 90 minutes, gets a snapshot every 10 minutes )

Example of snapshots of a movie

Below takes images as above and convert them into animated gifs. All movies in a path or directory structure gets a index page containing all animated gifs.

Example of generated directory index

I’ll post something about my media sorter also.
A ajax website using drag drop viewing/sorting images (png/gifs/jpgs) and movies.

#!/bin/bash
# Uses montage, ffmpeg, convert and mediainfo
rm thumbs/*
rm montage/*
(
set -x
numberofframes=9
find  -type f | egrep -i "flv$|mov$|mkv$|avi$|mpg$|mp4$|VTS_01_1.VOB$|wmv$" |  while read filez; do
        crunchpath=$(echo $filez | sed "s,/,,g" |  sed "s, ,,g" |tr -cd '[:alnum:]' ).gif
        crunchback=$crunchpath
        echo $crunchpath
        if [ -f thumbs/$crunchpath ] ; then
                echo "$file exists"
                else
	mkdir /tmp/thumbs/ 2>/dev/null
	mkdir thumbs 2>/dev/null
	mkdir montage 2>/dev/null
        rm -f /tmp/thumbs/*png
sec=0
                totaltime1=$( mediainfo -f "$filez" | grep ^Dura  | awk '{print $3}' |grep -v "\:" | tail -1 )
                totaltime2=$( mediainfo -f "$filez" | grep ^Dura  | awk '{print $4}' |grep -v "\:" | tail -1 )
totaltime1a=$(echo $totaltime1| tr -d 'a-z')
echo $totaltime1 | grep h && sec=$((3600 * $totaltime1a))
echo $totaltime1 | grep mn && sec=$((60 * $totaltime1a))
echo $totaltime1 | grep s && sec=$totaltime1a
echo "sec : $sec"
echo $totaltime2 | grep -v ms | grep  s && sec=$[ $sec + $(echo $totaltime2 | tr -d 'a-z')]
echo "sec : $sec"
                width=$( mediainfo -f "$filez" | grep "Width"| grep pixels | awk '{ print $3 }' )
                height=$( mediainfo -f "$filez" | grep "Height"| grep pixels | awk '{ print $3 }' )
        if [ "$sec" == "" ] ; then sec=1 ; fi
                timer=$[ $sec / $numberofframes ]
                        echo  "converting step "
                        echo  "timer is $timer"
mark=0
                for f in `seq -w 1 $numberofframes` ; do
                        echo  "$f,$timer"
			echo $[$f*$timer]
                        ffmpeg -ss $[$f*$timer] -i "$filez" -vframes 1 /tmp/thumbs/$f.png 1>/dev/null 2>/dev/null </dev/null
if [ $f -eq 8 ] ; then cp /tmp/thumbs/8.png /tmp/thumbs9.png ;fi
newsizer=$(echo -n $widther ; echo -n "x" ; echo -n $sizeh)
if [ $sizeh -gt $sizew ] ; then mv /tmp/thumbs/$f.png /tmp/ff.png ; convert -resize $newsizer\! /tmp/ff.png /tmp/thumbs/$f.png ; echo aangepast ; echo $newsizer ; mark=1; fi
                done
                        echo " "
                        echo "generating $crunchpath"
	newwidth=$[ $width / 2 ]
	newheight=$[ $height / 2 ]
	newsize=$(echo -n $newwidth ; echo -n "x" ; echo -n $newheight)
	newsize2=$(echo -n $width ; echo -n "x" ; echo -n $newheight)
	echo $newsize
if [ $mark == 0 ] ; then        convert -delay 100 -resize $newsize\! /tmp/thumbs/*.png thumbs/$crunchpath </dev/null ; else
convert -delay 100 -resize $newsize2\! /tmp/thumbs/*.png thumbs/$crunchpath </dev/null 
fi
montage /tmp/thumbs/*png  -geometry +3+3 -tile 3x3 montage/$crunchpath.jpg
	echo "<img src=\"$crunchpath\">" >> thumbs/_index.html
        fi
done
) > /tmp/thumb.log

Project mixer

I made a sound mixer controller for my applications, a while ago.

Some arduino project laying around on my desk. (OBS controller, Mqtt-sound-and-display-with-mute-acknowledge-button and Octoprint monitor, below that my dusty mixer)

I’m probably make a V2 with new functionality:

  • Switching applications which are using sound from speakers to headset and vice versa.
  • Led showing muted channels
  • Rotary buttons? Or motorized sliders?

See my other post ..

https://www.henriaanstoot.nl/2022/03/18/audio-switcher/

Esp32 Epaper and HA (Esphome)

Flashing a TTGO (ESP32) via your browser from ESPHome
esphome:
  name: epaperesp32

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: "xxxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Epaperesp32 Fallback Hotspot"
    password: "xxxxxxxxxxxx"

captive_portal:

font:
  - file: 'fonts/tahoma.ttf'
    id: font1
    size: 16

spi:
  clk_pin: 13
  mosi_pin: 14

display:
  - platform: waveshare_epaper
    cs_pin: 15
    dc_pin: 27
    busy_pin: 25
    reset_pin: 26
    model: 2.13in-ttgo
    full_update_every: 30
    lambda: |-
      it.print(0, 0, id(font1), "Pruts");
      

Mikrotik Mqtt

Today Vincent mentioned a link about mqtt and mikrotiks, i knew about addons, but not mqtt .. lets try this.

When you want to use MQTT with Mikrotik you have to install the iot package from extra_packages.

  • Download correct package zip from ( https://mikrotik.com/download )
    • Download extra packages zip for your system
  • Extract and use file upload
  • Reboot your mikrotik

(i had to upgrade my firmware first, iot package was not build for my version)

Create a entry in IoT > Mqtt to your broker.

save below in a script ending with a .rsc extention, and upload in file manager

# Required packages: iot

################ Configuration #################
# Name of an existing MQTT broker that should be used for publishing, the one you just created
:local broker "10.1.0.17"

# MQTT topic where the message should be published
# i've got mine in a tree called mikrotik/switchtype/
:local topic "mikrotik/rb2011/topic"

############### System ###############
# You can create your own variables below
:put ("[*] Gathering system info...")
:local cpuLoad [/system resource get cpu-load]
:local freeMemory [/system resource get free-memory]
:local usedMemory ([/system resource get total-memory] - $freeMemory)
:local rosVersion [/system package get value-name=version \
    [/system package find where name ~ "^routeros"]]
:local model [/system routerboard get value-name=model]
:local serialNumber [/system routerboard get value-name=serial-number]
:local upTime [/system resource get uptime]

################## MQTT ###################
# create a message
:local message \
    "{\"model\":\"$model\",\
                \"sn\":\"$serialNumber\",\
                \"ros\":\"$rosVersion\",\
                \"cpu\":$cpuLoad,\
                \"umem\":$usedMemory,\
                \"fmem\":$freeMemory,\
                \"uptime\":\"$upTime\"}"

:log info "$message";
:put ("[*] Total message size: $[:len $message] bytes")
:put ("[*] Sending message to MQTT broker...")
/iot mqtt publish broker=$broker topic=$topic message=$message
:put ("[*] Done")

Import script using

import mikrotikmqtt.rsc

Todo’s:

Import is just @ import time, need to “cron” this?

"If something is worth doing, it's worth overdoing."