Difference between revisions of "Radio Channel Logger"

From W9CR
Jump to navigation Jump to search
 
(21 intermediate revisions by the same user not shown)
Line 1: Line 1:
It seems to be a common requirement to make recordings of a radio or scanner output.  I've not found much decent Free Software that can do this, and do it reliably in a headless configuration.  What I've used is documented here, and will do 4 audio channels reliably.  
+
It seems to be a common requirement to make recordings of a radio or scanner output.  I've not found much decent Free Software that can do this, and do it reliably in a headless configuration.  What I've used is documented here, and will do 4 audio channels reliably.  This soultion is unique as it uses OpenAI's API to transcribe the audio files to easily searchable text.  
  
 
My concept is based around a RPI 5 with Cmedia USB audio dongles as pictured below.  This is compact and low power, while a full Linux environment allows you to do many other things as needed.  
 
My concept is based around a RPI 5 with Cmedia USB audio dongles as pictured below.  This is compact and low power, while a full Linux environment allows you to do many other things as needed.  
Line 21: Line 21:
 
* 4 usb jumpers
 
* 4 usb jumpers
 
* PSU
 
* PSU
* Cmedia Dongles
+
* [https://www.ebay.com/itm/131905878673 Cmedia Dongles]
  
 
== Radio ==
 
== Radio ==
Line 66: Line 66:
 
  lvcreate --name SWAP --size 8GiB vg0
 
  lvcreate --name SWAP --size 8GiB vg0
  
Now make a the rest into a pool for the thin volumes
+
Now make a the rest into a pool for the thin volumes, but leave some free space in the VG, it will be needed if repairs must be made. 
  lvcreate --type thin-pool --extents +100%FREE --name alberca vg0
+
  lvcreate --type thin-pool --extents +99%FREE --name alberca vg0
  
 
Last make a root volume and then one for storing the recordings
 
Last make a root volume and then one for storing the recordings
Line 80: Line 80:
 
   alberca    vg0 twi-aotz-- <911.77g                1.14  10.75
 
   alberca    vg0 twi-aotz-- <911.77g                1.14  10.75
 
   recordings vg0 Vwi-aotz--  50.00g alberca        2.37
 
   recordings vg0 Vwi-aotz--  50.00g alberca        2.37
 +
 
=== Filesystem setup ===  
 
=== Filesystem setup ===  
 
Make some file systems on the root  
 
Make some file systems on the root  
Line 135: Line 136:
  
 
== udev rules for ports ==  
 
== udev rules for ports ==  
I identify the ports as upper and lower, left and right on the RPI.  It's not possible to rename these, but you can make symlinks.  Based on the max of 32 devices and 2 being used for onboard hdmi, this means we could support up to 14 devicestechnically we may be able to go to pulse audio and do more, or figure out a way to do this that is not using udev and scale up to 30 since we'd not need to burn 2 devices per real device, but I didn't mess with that. if you do, please let me know.
+
I identify the ports as upper and lower, left and right on the RPI.  This should scale up to 32 devices max.   
 +
 
 +
this will set the device properly using the name as below
 +
  plughw:top-left,0
  
 
<pre>
 
<pre>
 
/etc/udev/rules.d/50-alsa.rules
 
/etc/udev/rules.d/50-alsa.rules
# snd 31 is bottom right port 3-2:1.0
+
SUBSYSTEM!="sound", GOTO="my_usb_audio_end"
KERNEL=="controlC[0-9]*", DRIVERS=="snd-usb-audio", KERNELS=="3-2:1.0", ACTION=="add", SYMLINK+="snd/controlC31"
+
ACTION!="add", GOTO="my_usb_audio_end"
#KERNEL=="hwC[D0-9]*", DRIVERS=="snd-usb-audio", KERNELS=="3-2:1.0", ACTION=="add", SYMLINK+="snd/hwC31"
+
# top right port 1-2:1.0
#KERNEL=="midiC[D0-9]*", DRIVERS=="snd-usb-audio", KERNELS=="3-2:1.0", ACTION=="add", SYMLINK+="snd/midiC31"
+
DEVPATH=="*/1-2:1.0/sound/card*", ATTR{id}="top-right"
KERNEL=="pcmC[0-9]*D0p", DRIVERS=="snd-usb-audio", KERNELS=="3-2:1.0", ACTION=="add", SYMLINK+="snd/pcmC31D0p"
+
# bottom right 3-2:1.0
KERNEL=="pcmC[0-9]*D0c", DRIVERS=="snd-usb-audio", KERNELS=="3-2:1.0", ACTION=="add", SYMLINK+="snd/pcmC31D0c"
+
DEVPATH=="*/3-2:1.0/sound/card*", ATTR{id}="bottom-right"
 
+
# top left port 3-1:1.0
# snd 30 is top right port 1-2:1.0
+
DEVPATH=="*/3-1:1.0/sound/card*", ATTR{id}="top-left"
KERNEL=="controlC[0-9]*", DRIVERS=="snd-usb-audio", KERNELS=="1-2:1.0", ACTION=="add", SYMLINK+="snd/controlC30"
+
# bottom left port 1-1:1.0
KERNEL=="pcmC[0-9]*D0p", DRIVERS=="snd-usb-audio", KERNELS=="1-2:1.0", ACTION=="add", SYMLINK+="snd/pcmC30D0p"
+
DEVPATH=="*/1-1:1.0/sound/card*", ATTR{id}="bottom-left"
KERNEL=="pcmC[0-9]*D0c", DRIVERS=="snd-usb-audio", KERNELS=="1-2:1.0", ACTION=="add", SYMLINK+="snd/pcmC30D0c"
 
 
 
# snd 29 is bottom left port 1-1:1.0
 
KERNEL=="controlC[0-9]*", DRIVERS=="snd-usb-audio", KERNELS=="1-1:1.0", ACTION=="add", SYMLINK+="snd/controlC29"
 
KERNEL=="pcmC[0-9]*D0p", DRIVERS=="snd-usb-audio", KERNELS=="1-1:1.0", ACTION=="add", SYMLINK+="snd/pcmC29D0p"
 
KERNEL=="pcmC[0-9]*D0c", DRIVERS=="snd-usb-audio", KERNELS=="1-1:1.0", ACTION=="add", SYMLINK+="snd/pcmC29D0c"
 
 
 
# snd 28 is top left port 3-1:1.0
 
KERNEL=="controlC[0-9]*", DRIVERS=="snd-usb-audio", KERNELS=="3-1:1.0", ACTION=="add", SYMLINK+="snd/controlC28"
 
KERNEL=="pcmC[0-9]*D0p", DRIVERS=="snd-usb-audio", KERNELS=="3-1:1.0", ACTION=="add", SYMLINK+="snd/pcmC28D0p"
 
KERNEL=="pcmC[0-9]*D0c", DRIVERS=="snd-usb-audio", KERNELS=="3-1:1.0", ACTION=="add", SYMLINK+="snd/pcmC28D0c"
 
</pre>
 
 
 
  
 +
LABEL="my_usb_audio_end"
 +
</pre>
  
 
= Software =  
 
= Software =  
Line 168: Line 161:
  
 
compile and install it as /usr/loca/bin/svar  
 
compile and install it as /usr/loca/bin/svar  
 +
 +
== apt-get scripts ==
 +
 +
Install the following packages
 +
apt-get install screen vim nvme-cli netcat-traditional lvm2 zfsutils-linux uml-utilities bridge-utils frr strongswan-swanctl strongswan isc-dhcp-client snmpd snmp locate xinetd snmpd php perl curl xinetd snmp libsnmp-dev libwww-perl ifupdown-extra ifupdown ifupdown-multi rsyslog cmake libopusenc-dev libalsa-ocaml-dev libsndfile1-dev lame libmp3lame-dev samba smbclient wsdd2 git opus-tools jq telnet libstrongswan-extra-plugins mtools
  
 
== systemd scripts ==
 
== systemd scripts ==
 
This runs as a script under systemd which will set the mic gain and the then invoke svar on each channel per it's config file.  if it crashes, it waits 5 seconds and restarts it.  
 
This runs as a script under systemd which will set the mic gain and the then invoke svar on each channel per it's config file.  if it crashes, it waits 5 seconds and restarts it.  
 
<pre>
 
<pre>
/etc/systemd/system/svar@.service
+
cat << EOF >/etc/systemd/system/svar@.service
 
[Unit]
 
[Unit]
 
Description=Start recording from %i
 
Description=Start recording from %i
Line 180: Line 178:
 
User=svar
 
User=svar
 
EnvironmentFile=/etc/default/svar@%i
 
EnvironmentFile=/etc/default/svar@%i
ExecStartPre=/usr/bin/amixer -D hw:${HW} -n sset Mic capture ${CAPLEVEL}
+
ExecStartPre=/usr/bin/amixer -D hw:%i -n sset Mic capture \${CAPLEVEL}
ExecStart=/usr/local/bin/svar -v --device=plughw:${HW},0 -l${VOXLEVEL} --rate=${RATE} -s ${SEC} --fadeout-lag ${FOLAG} ${DIR}/${FNAME}
+
ExecStart=/usr/local/bin/svar -v --device=plughw:%i,0 -l\${VOXLEVEL} --rate=\${RATE} -s \${SEC} --fadeout-lag \${FOLAG} \${DIR}/\${FNAME}
 
# Restart every >2 seconds to avoid StartLimitInterval failure
 
# Restart every >2 seconds to avoid StartLimitInterval failure
 
RestartSec=5
 
RestartSec=5
 
Restart=always
 
Restart=always
 +
SyslogIdentifier=svar@%i
  
 
[Install]
 
[Install]
 
WantedBy=multi-user.target
 
WantedBy=multi-user.target
 +
EOF
 
</pre>
 
</pre>
  
Line 202: Line 202:
 
== service config file ==  
 
== service config file ==  
  
for each channel being recorded a seperate service is used with it's own config
+
for each channel being recorded a separate service is used with it's own config
  
 
<pre>
 
<pre>
/etc/default/svar@top-right
+
export filename=''
#HW is the mixer id that maps to this channel
+
 
#31 - Bottom Right
+
cat << EOF > /etc/default/svar@$filename
#30 - Top Right
 
#29 - Bottom Left
 
#28 - Top Left
 
HW="30"
 
 
#audio level for capture
 
#audio level for capture
 
CAPLEVEL="0"  
 
CAPLEVEL="0"  
 
#directory to put the files in
 
#directory to put the files in
DIR="/home/svar/rec/top-right/current"
+
DIR="/home/svar/rec/$filename/current"
#filename BR/TR/TL/BL based on port
+
FNAME="$filename-%Y-%m-%d-%H%M.%S"
FNAME="TR-%Y-%m-%d-%H%M.%S"
 
 
#this sets the VOX level  
 
#this sets the VOX level  
 
VOXLEVEL="1"
 
VOXLEVEL="1"
Line 226: Line 221:
 
SEC="10"
 
SEC="10"
 
FOLAG="10000"
 
FOLAG="10000"
 +
EOF
 
</pre>
 
</pre>
  
Line 329: Line 325:
 
Feb 13 09:49:39 DonPie svar[6874]: info: Creating new output file: /home/svar/rec/bottom-left/current/BL-2025-02-13-0949.39.wav
 
Feb 13 09:49:39 DonPie svar[6874]: info: Creating new output file: /home/svar/rec/bottom-left/current/BL-2025-02-13-0949.39.wav
 
</pre>
 
</pre>
 +
 +
= SAMBA Config =
 +
This makes a file share so that you can access the recordings on the system from another computer/windoze.
 +
 +
Install software
 +
apt-get install samba smbclient wsdd
 +
 +
'''Windoze 11 note'''
 +
If you're running windoze 11, you will need to enable this in powershell.  M$ has fucked their shit up once again for no good reason.
 +
Set-SmbClientConfiguration -RequireSecuritySignature $false
 +
 +
 +
 +
 +
== /etc/samba/smb.conf ==
 +
<pre>
 +
[global]
 +
  workgroup = WORKGROUP
 +
  security = user
 +
  netbios name = RecPie
 +
  server string = RECORDER
 +
  client min protocol = SMB2
 +
  server signing = mandatory
 +
  client signing = mandatory
 +
  interfaces = 127.0.0.0/8 eth0
 +
  bind interfaces only = yes
 +
  log file = /var/log/samba/log.%m
 +
  max log size = 1000
 +
  logging = file
 +
  panic action = /usr/share/samba/panic-action %d
 +
  server role = standalone server
 +
  obey pam restrictions = yes
 +
  unix password sync = yes
 +
  passwd program = /usr/bin/passwd %u
 +
  passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
 +
  pam password change = yes
 +
  map to guest = Bad Password
 +
  usershare allow guests = yes
 +
[recorded]
 +
    comment = recorder files
 +
    path = /home/svar/rec
 +
    read only = yes
 +
    public = yes
 +
    available = yes
 +
    browsable = yes
 +
    guest ok = yes
 +
</pre>
 +
 +
= Transcription via OpenAI service =
 +
 +
I've made a script that will use the wisperAI service to transcribe files into plain text and json format.  It also sorts them into a year/month/day directory hierarchy, and converts the wave files to 24 kbit/s Opus format which is about 20% the size of the wave format.  This allows up to a 2:22.22 long file to be automatically transcribed.  Anything longer will fail, and there's no support to split them up, so it's suggested that the $SEC and $FOLAG be touched to break files up. 
 +
 +
This is then automated via systemd scripts that monitor the directories and fire off the transcription script in the background.  The only process that takes some CPU is opus encoding, but this is run with a 15 nice value to ensure there's no dropping of audio. 
 +
 +
== transcribe.sh ==
 +
 +
This is the script, it takes the basedir as it's only argument.  It's designed so that the source files will not be moved until all operations complete.
 +
 +
https://github.com/W9CR/radiologger
 +
 +
== Systemd config ==
 +
 +
There are two files needed, one to monitor the path and another to run when the path changes
 +
 +
=== transcribe@.path ===
 +
 +
<pre>
 +
cat >/etc/systemd/system/transcribe@.path <<'EOF'
 +
[Unit]
 +
Description=Monitor folder %i/current for changes and transcribe files
 +
 +
[Path]
 +
PathChanged=/home/svar/rec/%i/current/
 +
 +
[Install]
 +
WantedBy=multi-user.target
 +
EOF
 +
</pre>
 +
 +
=== transcribe@.service ===
 +
<pre>
 +
cat >/etc/systemd/system/transcribe@.service <<'EOF'
 +
[Unit]
 +
Description=Transcribe recording from /home/svar/rec/%i/current/
 +
 +
[Service]
 +
Type=oneshot
 +
User=svar
 +
#EnvironmentFile=/etc/default/
 +
ExecStart=/bin/bash /home/svar/scripts/transcriber.sh /home/svar/rec/%i
 +
SyslogIdentifier=transcribe@%i
 +
EOF
 +
</pre>
 +
 +
=== Enable Service ===
 +
 +
<pre>
 +
systemctl enable transcribe@top-left.path
 +
systemctl enable transcribe@top-right.path
 +
systemctl enable transcribe@bottom-left.path
 +
systemctl enable transcribe@bottom-right.path
 +
 +
systemctl start transcribe@top-left.path
 +
systemctl start transcribe@top-right.path
 +
systemctl start transcribe@bottom-left.path
 +
systemctl start transcribe@bottom-right.path
 +
 +
journalctl -f -u transcribe@top-left.service
 +
 +
</pre>
 +
 +
= todo =
 +
 +
* <S>opus support - opusenc --speech --bitrate 24 gives almost the same audio for 20% of the file size. </S>
 +
 +
* <s>speech to text</s>
 +
 +
* <s>moving files into other directories via cron</s>
 +
 +
* script to make searching text files easier
 +
 +
* script to compute the number of seconds per day/week/month/year on a channel

Latest revision as of 19:35, 25 October 2025

It seems to be a common requirement to make recordings of a radio or scanner output. I've not found much decent Free Software that can do this, and do it reliably in a headless configuration. What I've used is documented here, and will do 4 audio channels reliably. This soultion is unique as it uses OpenAI's API to transcribe the audio files to easily searchable text.

My concept is based around a RPI 5 with Cmedia USB audio dongles as pictured below. This is compact and low power, while a full Linux environment allows you to do many other things as needed.


Features

  • 4 audio channels
  • Date/time logging down to the seconds
  • Configuration of settings per channel
  • Recordings are 8000 samples per second 16 bit WAV
  • VOX activated recording with VOX level set per channel
  • Low Overhead on as no voice coding is taking place, should run on a pi0 for at least one channel (not tested)
  • 1tb ssd used for recording.

Hardware

RPI 5

Radio

Per channel

  • CDM radio
  • CDM radio interface cable

radio setup

ensure the low level expansion is set in the personality and that demphasis is selected.

Linux

The system is standard raspbian Linux

What is different is that we are booting off the nvme directly.

Disk Setup

This is not a complete howto, but rather enough to figure it out. You may want to do it differently.

GPT table

Part 1 is /boot/firmware

Part 2 is lvm Leave a little at the end free, I picked 11gb

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   0700  Microsoft basic data
   2         1050624      1930430463   920.0 GiB   8E00  Linux LVM

LVM config

From here I make that part 2 a LVM phsyical volume with 'pvcreate', then make the entire thing a volume group with vgcreate

pvcreate /dev/nvme0n1p2
vgcreate vg0 /dev/nvme0n1p2

# pvs
  PV             VG  Fmt  Attr PSize    PFree
  /dev/nvme0n1p2 vg0 lvm2 a--  <920.00g    0

# vgs
  VG  #PV #LV #SN Attr   VSize    VFree
  vg0   1   4   0 wz--n- <920.00g    0

Next we need make the swap thick LV of 8gb

lvcreate --name SWAP --size 8GiB vg0

Now make a the rest into a pool for the thin volumes, but leave some free space in the VG, it will be needed if repairs must be made.

lvcreate --type thin-pool --extents +99%FREE --name alberca vg0

Last make a root volume and then one for storing the recordings

lvcreate --type thin --virtualsize 128GiB --name ROOT --thinpool alberca vg0
lvcreate --type thin --virtualsize 128GiB --name recordings --thinpool alberca vg0

# lvs
  LV         VG  Attr       LSize    Pool    Origin Data%  Meta%  Move Log Cpy%Sync Convert
  ROOT       vg0 Vwi-aotz--  128.00g alberca        7.18
  SWAP       vg0 -wi-ao----    8.00g
  alberca    vg0 twi-aotz-- <911.77g                1.14   10.75
  recordings vg0 Vwi-aotz--   50.00g alberca        2.37

Filesystem setup

Make some file systems on the root

mkfs.ext4 /dev/mapper/vg0-ROOT
mkfs.ext4 /dev/mapper/vg0-recordings
mkswap /dev/mapper/SWAP

Copy the sdcard to the filesystems

so you can use cp or rsync to copy the file systems into the new place, but i used dd. dd is not ideal as you need to tune the file systems to change the UUID's.

dd bs=4M conv=sparse if=/dev/mmblockroot of=/dev/mapper/ROOT
dd bs=4M  if=/dev/mmblockboot of=/dev/nvme0n1p1

Change the UUID's of the file systems

tune2fs -U $(uuidgen) /dev/vg0/ROOT
mlabel -n -i /dev/nvme0n1p1
resize2fs /dev/vg0/ROOT

get the new UUID's

lsblk -f

mount these in /mnt and chroot to them

mount /dev/vg0/ROOT /mnt
mount /dev/nvme0n0p1 /mnt/boot/firmware
mount -t proc /proc /mnt/proc/
mount --rbind /sys /mnt/sys/
mount --rbind /dev /mnt/dev/
chroot /mnt

Change fstab to boot off nvme

cat /etc/fstab
proc            /proc           proc    defaults          0       0
UUID=1B01-6969  /boot/firmware  vfat    defaults          0       2
UUID=d185ebc1-68df-4065-afe6-5ed288b28e32  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that
UUID=01b68d2f-9577-4e63-b79f-6eaea8bbd61c       swap    swap    defaults        0       0
UUID=d5d62f0a-054b-4f9b-a615-4c1b02373fdc       /home/svar      ext4    defaults,noatime  0       1

disable swap in the chroot

sudo systemctl disable dphys-swapfile.service

exit the chroot and reboot. remove the sdcard and confirm you're booting off the LVM.

Linux config

I set the timezone to local time and then configure the users/ssh keys. If this will be remote it's a good idea to setup the ssh remote service for remote access. I have a page on this here Secure Tunnel Service

The user I use for this is 'svar' and must be added to the audio group

usermod svar -a -G audio 

# groups svar
svar : svar audio users

udev rules for ports

I identify the ports as upper and lower, left and right on the RPI. This should scale up to 32 devices max.

this will set the device properly using the name as below

plughw:top-left,0
/etc/udev/rules.d/50-alsa.rules
SUBSYSTEM!="sound", GOTO="my_usb_audio_end"
ACTION!="add", GOTO="my_usb_audio_end"
# top right port 1-2:1.0
DEVPATH=="*/1-2:1.0/sound/card*", ATTR{id}="top-right"
# bottom right 3-2:1.0
DEVPATH=="*/3-2:1.0/sound/card*", ATTR{id}="bottom-right"
# top left port 3-1:1.0
DEVPATH=="*/3-1:1.0/sound/card*", ATTR{id}="top-left"
# bottom left port 1-1:1.0
DEVPATH=="*/1-1:1.0/sound/card*", ATTR{id}="bottom-left"

LABEL="my_usb_audio_end"

Software

This uses this great software 'svar' https://github.com/arkq/svar

compile and install it as /usr/loca/bin/svar

apt-get scripts

Install the following packages

apt-get install screen vim nvme-cli netcat-traditional lvm2 zfsutils-linux uml-utilities bridge-utils frr strongswan-swanctl strongswan isc-dhcp-client snmpd snmp locate xinetd snmpd php perl curl xinetd snmp libsnmp-dev libwww-perl ifupdown-extra ifupdown ifupdown-multi rsyslog cmake libopusenc-dev libalsa-ocaml-dev libsndfile1-dev lame libmp3lame-dev samba smbclient wsdd2 git opus-tools jq telnet libstrongswan-extra-plugins mtools

systemd scripts

This runs as a script under systemd which will set the mic gain and the then invoke svar on each channel per it's config file. if it crashes, it waits 5 seconds and restarts it.

cat << EOF >/etc/systemd/system/svar@.service
[Unit]
Description=Start recording from %i
After=network.target

[Service]
User=svar
EnvironmentFile=/etc/default/svar@%i
ExecStartPre=/usr/bin/amixer -D hw:%i -n sset Mic capture \${CAPLEVEL}
ExecStart=/usr/local/bin/svar -v --device=plughw:%i,0 -l\${VOXLEVEL} --rate=\${RATE} -s \${SEC} --fadeout-lag \${FOLAG} \${DIR}/\${FNAME}
# Restart every >2 seconds to avoid StartLimitInterval failure
RestartSec=5
Restart=always
SyslogIdentifier=svar@%i

[Install]
WantedBy=multi-user.target
EOF

Config

directory config

as svar you will need to make the following directories

mkdir -p /home/svar/rec/top-right/current
mkdir -p /home/svar/rec/top-left/current 
mkdir -p /home/svar/rec/bottom-right/current
mkdir -p /home/svar/rec/bottom-left/current

service config file

for each channel being recorded a separate service is used with it's own config

export filename=''

cat << EOF > /etc/default/svar@$filename
#audio level for capture
CAPLEVEL="0" 
#directory to put the files in
DIR="/home/svar/rec/$filename/current"
FNAME="$filename-%Y-%m-%d-%H%M.%S"
#this sets the VOX level 
VOXLEVEL="1"
RATE="8000"
#seconds is the number of seconds to break up
#FOLAG is the lag in milliseconds and needs to match the seconds to ensure there is no
# clipping of silence in the output
SEC="10"
FOLAG="10000"
EOF

Start your services

systemctl enable svar@top-right.service
systemctl start  svar@top-right.service
systemctl status svar@top-right.service

systemctl enable svar@top-left.service
systemctl start  svar@top-left.service
systemctl status svar@top-left.service

systemctl enable svar@bottom-right.service
systemctl start  svar@bottom-right.service
systemctl status svar@bottom-right.service

systemctl enable svar@bottom-left.service
systemctl start  svar@bottom-left.service
systemctl status svar@bottom-left.service

you should see all the audio dongles blinking if svar is active.

# service svar@* status
● svar@top-left.service - Start recording from top-left
     Loaded: loaded (/etc/systemd/system/svar@.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-02-12 18:24:38 CST; 1 day 5h ago
   Main PID: 6873 (svar)
      Tasks: 3 (limit: 9574)
        CPU: 17min 46.500s
     CGroup: /system.slice/system-svar.slice/svar@top-left.service
             └─6873 /usr/local/bin/svar -v --device=plughw:28,0 -l1 --rate=8000 -s 10 --fadeout-lag 10000 /home/svar/rec/top-left/current/TL-%Y-%m-%d-%H%M.%S

Feb 12 18:24:38 DonPie systemd[1]: Starting svar@top-left.service - Start recording from top-left...
Feb 12 18:24:38 DonPie amixer[6871]: Simple mixer control 'Mic',0
Feb 12 18:24:38 DonPie amixer[6871]:   Capabilities: pvolume pvolume-joined cvolume cvolume-joined pswitch pswitch-joined cswitch cswitch-joined
Feb 12 18:24:38 DonPie amixer[6871]:   Playback channels: Mono
Feb 12 18:24:38 DonPie amixer[6871]:   Capture channels: Mono
Feb 12 18:24:38 DonPie amixer[6871]:   Limits: Playback 0 - 127 Capture 0 - 16
Feb 12 18:24:38 DonPie amixer[6871]:   Mono: Playback 0 [0%] [0.00dB] [off] Capture 0 [0%] [0.00dB] [on]
Feb 12 18:24:38 DonPie systemd[1]: Started svar@top-left.service - Start recording from top-left.
Feb 13 09:50:00 DonPie svar[6873]: info: Creating new output file: /home/svar/rec/top-left/current/TL-2025-02-13-0950.00.wav

● svar@bottom-right.service - Start recording from bottom-right
     Loaded: loaded (/etc/systemd/system/svar@.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-02-13 12:18:21 CST; 11h ago
    Process: 12137 ExecStartPre=/usr/bin/amixer -D hw:${HW} -n sset Mic capture 0 (code=exited, status=0/SUCCESS)
   Main PID: 12138 (svar)
      Tasks: 3 (limit: 9574)
        CPU: 7min 3.715s
     CGroup: /system.slice/system-svar.slice/svar@bottom-right.service
             └─12138 /usr/local/bin/svar -v --device=plughw:31,0 -l1 --rate=8000 -s 10 --fadeout-lag 10000 /home/svar/rec/bottom-right/current/BR-%Y-%m-%d-%H%M.%S

Feb 13 12:18:21 DonPie systemd[1]: Starting svar@bottom-right.service - Start recording from bottom-right...
Feb 13 12:18:21 DonPie amixer[12137]: Simple mixer control 'Mic',0
Feb 13 12:18:21 DonPie amixer[12137]:   Capabilities: pvolume pvolume-joined cvolume cvolume-joined pswitch pswitch-joined cswitch cswitch-joined
Feb 13 12:18:21 DonPie amixer[12137]:   Playback channels: Mono
Feb 13 12:18:21 DonPie amixer[12137]:   Capture channels: Mono
Feb 13 12:18:21 DonPie amixer[12137]:   Limits: Playback 0 - 127 Capture 0 - 16
Feb 13 12:18:21 DonPie amixer[12137]:   Mono: Playback 0 [0%] [0.00dB] [off] Capture 0 [0%] [0.00dB] [on]
Feb 13 12:18:21 DonPie systemd[1]: Started svar@bottom-right.service - Start recording from bottom-right.

● svar@top-right.service - Start recording from top-right
     Loaded: loaded (/etc/systemd/system/svar@.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-02-12 18:24:38 CST; 1 day 5h ago
   Main PID: 6864 (svar)
      Tasks: 3 (limit: 9574)
        CPU: 18min 6.667s
     CGroup: /system.slice/system-svar.slice/svar@top-right.service
             └─6864 /usr/local/bin/svar -v --device=plughw:30,0 -l1 --rate=8000 -s 10 --fadeout-lag 10000 /home/svar/rec/top-right/current/TR-%Y-%m-%d-%H%M.%S

Feb 13 20:45:52 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2045.52.wav
Feb 13 20:54:56 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2054.56.wav
Feb 13 22:54:15 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2254.15.wav
Feb 13 22:56:06 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2256.06.wav
Feb 13 23:03:24 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2303.24.wav
Feb 13 23:11:22 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2311.22.wav
Feb 13 23:12:33 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2312.33.wav
Feb 13 23:16:16 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2316.16.wav
Feb 13 23:18:50 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2318.50.wav
Feb 13 23:21:41 DonPie svar[6864]: info: Creating new output file: /home/svar/rec/top-right/current/TR-2025-02-13-2321.41.wav

● svar@bottom-left.service - Start recording from bottom-left
     Loaded: loaded (/etc/systemd/system/svar@.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-02-12 18:24:38 CST; 1 day 5h ago
   Main PID: 6874 (svar)
      Tasks: 3 (limit: 9574)
        CPU: 16min 49.254s
     CGroup: /system.slice/system-svar.slice/svar@bottom-left.service
             └─6874 /usr/local/bin/svar -v --device=plughw:29,0 -l1 --rate=8000 -s 10 --fadeout-lag 10000 /home/svar/rec/bottom-left/current/BL-%Y-%m-%d-%H%M.%S

Feb 12 18:24:38 DonPie systemd[1]: Starting svar@bottom-left.service - Start recording from bottom-left...
Feb 12 18:24:38 DonPie amixer[6872]: Simple mixer control 'Mic',0
Feb 12 18:24:38 DonPie amixer[6872]:   Capabilities: pvolume pvolume-joined cvolume cvolume-joined pswitch pswitch-joined cswitch cswitch-joined
Feb 12 18:24:38 DonPie amixer[6872]:   Playback channels: Mono
Feb 12 18:24:38 DonPie amixer[6872]:   Capture channels: Mono
Feb 12 18:24:38 DonPie amixer[6872]:   Limits: Playback 0 - 127 Capture 0 - 16
Feb 12 18:24:38 DonPie amixer[6872]:   Mono: Playback 0 [0%] [0.00dB] [off] Capture 0 [0%] [0.00dB] [on]
Feb 12 18:24:38 DonPie systemd[1]: Started svar@bottom-left.service - Start recording from bottom-left.
Feb 13 09:49:39 DonPie svar[6874]: info: Creating new output file: /home/svar/rec/bottom-left/current/BL-2025-02-13-0949.39.wav

SAMBA Config

This makes a file share so that you can access the recordings on the system from another computer/windoze.

Install software

apt-get install samba smbclient wsdd

Windoze 11 note If you're running windoze 11, you will need to enable this in powershell. M$ has fucked their shit up once again for no good reason.

Set-SmbClientConfiguration -RequireSecuritySignature $false



/etc/samba/smb.conf

[global]
   workgroup = WORKGROUP
   security = user
   netbios name = RecPie
   server string = RECORDER
   client min protocol = SMB2 
   server signing = mandatory
   client signing = mandatory
   interfaces = 127.0.0.0/8 eth0
   bind interfaces only = yes
   log file = /var/log/samba/log.%m
   max log size = 1000
   logging = file
   panic action = /usr/share/samba/panic-action %d
   server role = standalone server
   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
   pam password change = yes
   map to guest = Bad Password
   usershare allow guests = yes
[recorded]
    comment = recorder files
    path = /home/svar/rec
    read only = yes
    public = yes
    available = yes
    browsable = yes
    guest ok = yes

Transcription via OpenAI service

I've made a script that will use the wisperAI service to transcribe files into plain text and json format. It also sorts them into a year/month/day directory hierarchy, and converts the wave files to 24 kbit/s Opus format which is about 20% the size of the wave format. This allows up to a 2:22.22 long file to be automatically transcribed. Anything longer will fail, and there's no support to split them up, so it's suggested that the $SEC and $FOLAG be touched to break files up.

This is then automated via systemd scripts that monitor the directories and fire off the transcription script in the background. The only process that takes some CPU is opus encoding, but this is run with a 15 nice value to ensure there's no dropping of audio.

transcribe.sh

This is the script, it takes the basedir as it's only argument. It's designed so that the source files will not be moved until all operations complete.

https://github.com/W9CR/radiologger

Systemd config

There are two files needed, one to monitor the path and another to run when the path changes

transcribe@.path

cat >/etc/systemd/system/transcribe@.path <<'EOF' 
[Unit]
Description=Monitor folder %i/current for changes and transcribe files

[Path]
PathChanged=/home/svar/rec/%i/current/

[Install]
WantedBy=multi-user.target
EOF

transcribe@.service

cat >/etc/systemd/system/transcribe@.service <<'EOF'
[Unit]
Description=Transcribe recording from /home/svar/rec/%i/current/

[Service]
Type=oneshot
User=svar
#EnvironmentFile=/etc/default/
ExecStart=/bin/bash /home/svar/scripts/transcriber.sh /home/svar/rec/%i
SyslogIdentifier=transcribe@%i
EOF

Enable Service

systemctl enable transcribe@top-left.path
systemctl enable transcribe@top-right.path
systemctl enable transcribe@bottom-left.path
systemctl enable transcribe@bottom-right.path

systemctl start transcribe@top-left.path
systemctl start transcribe@top-right.path
systemctl start transcribe@bottom-left.path
systemctl start transcribe@bottom-right.path

journalctl -f -u transcribe@top-left.service

todo

  • opus support - opusenc --speech --bitrate 24 gives almost the same audio for 20% of the file size.
  • speech to text
  • moving files into other directories via cron
  • script to make searching text files easier
  • script to compute the number of seconds per day/week/month/year on a channel