Postprocessing SSTV Images

This is a little update for my ancient post about post morten decoding SSTV images received and recorded from the ISS. This time I could not decode the pictures live but instead recorded all passes to SD card in order to decode them later. Instead of editing and cutting files and file names by hand I wrote some bash script magic that calculates the real receive date and time from the timestamp the audio file was created and decode all pictures in a row.

First you need a kind of virtual audio cable that paplay can output the recorded wav file to and qsstv can decode it from the other end. On an Ubuntu system you can use the null-sink module for pulse audio. It created an audio device which satisfies the purpose mentioned above. The module is loaded with:

# pactl load-module module-null-sink sink_name=virtual-cable

From here on I use a simple (apart from the regexes) script to calculate the effective reception date and time and rename the files accordingly after re-decoding them with qsstv. In order for qsstv to read from the null-sink device you have to start it once and select it as audio device. Do not forget to save qsstv’s configuration afterwards.

The script is here:

#!/bin/bash
SAMPLERATE="48000"
MODE="PD120"
QSSTV_RX_PATH="/home/user/qsstv/rx"
UTC_OFFSET="0"
FILETYPE="png"

for FILE in *.wav; do
	# Determine file creation date and time
	TIMESTAMP=$(stat -c %y  $FILE | sed -e "s/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\) \([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\).*$/\1-\2-\3 \4:\5:\6/" | date -f - '+%s')
	echo "TIMESTAMP: $TIMESTAMP"
	NR=$(echo $FILE | sed -e "s/^.\{6\}_\([0-9]\{4\}\).*$/\1/")
	# Use clear text date and time for filename
	TIME=$(date -d @${TIMESTAMP} '+%Y%m%d_%H%M%S')
	sox $FILE -V1 -r ${SAMPLERATE} ${NR}_${TIME}.wav
	LENGTH=$(soxi -D ${NR}_${TIME}.wav | sed -e 's/\..*//')
	echo "Length: ${LENGTH}"
	sleep 2
	qsstv &
	sleep 5
	NOW=$(date '+%s')
	echo "NOW: ${NOW}"
	UTCNOW=$((${NOW} - (${UTC_OFFSET} * 3600)))
	echo "UTCNOW: ${UTCNOW}"
	paplay -d virtual-cable ${NR}_${TIME}.wav
	sleep 3
	killall qsstv
	# Now find recently decoded files (qsstv uses the time when the file is written to disk for timestamp)
	for SSTV_FILE in $(find ${QSSTV_RX_PATH} -maxdepth 1 -type f -name "${MODE}_*.${FILETYPE}" -newermt @${NOW}); do
		echo "File: ${SSTV_FILE}"
		FILE_NAME=$(basename ${SSTV_FILE} .${FILETYPE})	
		FILE_DATE=$(echo ${FILE_NAME} | sed -e "s/^PD120_\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)_\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\).*/\1-\2-\3 \4:\5:\6/")
		FILE_TIMESTAMP=$(date -d "${FILE_DATE}" '+%s')
		echo "file timestamp: ${FILE_TIMESTAMP}"
		DIFF=$((${FILE_TIMESTAMP}-${UTCNOW}))
		echo "Diff: ${DIFF}"
		NEW_TIME=$((${TIMESTAMP}-${LENGTH}+${DIFF}))
		cp ${SSTV_FILE} ./${MODE}_$(date -d @${NEW_TIME} '+%Y%m%d_%H%M%S').${FILETYPE}
	done
done

exit 0;

There is a UTC offset parameter which can be used to adjust the offset or daylight saving offsets.

References

[1] https://www.chonky.net/hamradio/decoding-sstv-from-a-file-on-a-linux-system
[2] https://www.reddit.com/r/SSTV/comments/fzlpi8/sstv_decode_recorded_wav_file_using_linux_command/