Harnessing Raspberry Pi 4 Model B with 8GB RAM
I’ve been using LGE webOS smart TV since 2014. It has been working seemingly well. Except for some nuisances like inability to play Classic FM. Raspberry Pi 4 with 8 GB RAM seems a tempting choice for a smart TV set-top box. But here is an issue: hardware accelerated video decoding only works in a 32-bit OS that can only operate 4GB RAM at most. It’s more than just trading precious RAM for CPU cycles, videos don’t play smoothly at all without hardware decoding.
So here is how I set it up with very little to no compromise:
- Install
aarch64
Manjaro as a main OS to utilize the whole RAM - Setup a 32-bit Raspberry Pi OS container to run hardware-accelerated VLC, Kodi as well as other Raspberry Pi goodies like Wolfram Mathematica
- Create a couple of bash scripts to simplify launching contained applications.
While it’s trivial to download and boot the Manjaro image, let me describe
how to run raspios in more detail. First we need to download an image and
extract its root file system into /var/lib/machines/raspios
. The partition
table doesn’t allow using losetup
. So some manual calculation will be
necessary using the following commands:
fdisk -l
mount -v -o loop,offset=$((512*start2)) -t ext4 raspios.img /mnt
mount -v -o loop,offset=$((512*start1)),sizelimit=$((512*size1)) -t vfat raspios.img /mnt/boot
Then the files could be just copied over the desired location:
sudo rsync -raP /mnt/* /var/lib/machines/raspios/
The following configuration files for systemd-nspawn need be created as recorded in the repository sakhnik/chbox:
./etc/polkit-1/rules.d/49-nopasswd_limited.rules
./etc/systemd/nspawn/raspios.nspawn
./etc/systemd/system/systemd-nspawn@raspios.service.d/override.conf
The machine could be started at this point with machinectl start raspios
.
The startup may take a bit of time because of slow dhcpcd
service. It can
be profiled and improved later with systemd-analyze blame
.
The machine could be configured to be started automatically: systemctl enable
systemd-nspawn@raspios
.
The real magic happens in the script to execute programs from the container.
Here we can define whatever is necessary in the container environment to
allow accessing host graphics and audio:
pserver=/tmp/pulse-host/$USER
if ! (machinectl -q shell $USER@raspios /bin/mount | grep -q $pserver); then
# Allow Arch accessing pulseaudio
machinectl -q shell $USER@raspios /bin/mkdir -p $pserver
machinectl bind --read-only raspios /run/user/$UID/pulse $pserver
fi
# Allow local connections from the container to the host X11 server
xhost +local: || true
machinectl -q shell \
--setenv=DISPLAY=$DISPLAY \
--setenv=PULSE_SERVER=unix:$pserver/native \
$USER@raspios "$@"
Having defined a polkit rule earlier allows us executing some machinectl
commands without elevation. And thus, the empowered $USER
can obtain a
shell in the container and will be able to launch GUI apps there. For
instance, to launch VLC capable of hardware-accelerated decoding, we could
put the following script into /usr/local/bin/vlc
:
#!/bin/bash -x
# Quote parameters into one interpretable string.
input=
for i in "${@}"; do
input="${input} ${i@Q}"
done
$HOME/bin/raspios.sh /bin/bash -xc "cd '$(pwd)'; vlc ${input}"
To take one step further, we can copy the vlc.desktop
file from the
container to the host, and modify the lines Exec=
and TryExec=
to point
to /usr/local/bin/vlc
.
Finally, we can create a script to watch the clipboard. When a new YouTube (or whatever other service youtube-dl supports) URL is noticed, it could be played automatically. Thus, the script yt-watch.sh was created. Now we can browse the playlist and just highlight the desired URL or copy it to the clipboard to have it played in a couple of seconds.