How to install mythtv-light v33 on RPI OS 64 bit Bookworm

For discussion of topics specific to MythTV on Raspberry Pi devices
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

This topic will give the instructions to install MythTV v33 for running on a 4GB Raspberry Pi 4 (RPI4) running the latest Bookworm 64 bit based on Debian 12 either as a Frontend only or a combination Frontend/Backend (FE/BE). The MythTV developer team and the Raspberry Pi OS team both have made huge improvments to video routines and drivers. So this doc will only concentrate on v33 and Bookworm 64 bit which means you must have a v33 backend or do the combination build so you will have one on the RPI4. The RPI4 has no issues being a backend. You can easily record 4 TV HD programs from the networked tuners at once while playing back a previously recorded program on the frontend section of the RPI4.

I created this document while installing a combo FE/BE so the instructions should be as accurate as possible.

The first part is common to both, so we will start there. We are going to build from source so the latest will always be available for the version we want to work with.

We will be installing 'mythtv-light' so the software is packaged as a .deb file that can be easily installed and upgraded.

You can find the version of v33 that you want from the link https://dl.orangedox.com/pCBmBm page for mythtv-light and you can use that. The latest are at: https://dl.orangedox.com/pCBmBm/1bO1JOe ... gB0yPsaTHe

Pick the Bookworm version,

I'll try to keep the v33 Bookworm folders up to date.

The hardware being used in this example is:
RPI4 4GB RAM
USB3 to SATA Adapter based on the ASMedia ASM1153E controller
1TB SATA SSD
USB keyboard
FHD HDMI monitor
SiliconDust HDHomeRun Quatro networked ATSC 1.0 tuner (4 tuners) (HDHR)
Ethernet connected to the same network as HDHR with Cat-5e, but WiFi can work if yours is a very good connection.

Using the Raspberry Pi Imager 1.7.5 or newer, select the Bookworm 64bit. Flash the image directly to the SATA SSD using the adapter.

The version of Bookworm that I installed had as default a locale that uses the ISO settings. Previous versions uses UTF-8. You may need to change this.
You need to download the mythtv-ight and install similar to the command below:

Code: Select all

sudo apt install ./mythtv-light_33.1-22-g26e76a3949_arm64_bookworm.deb
On Bookworm you will see some notifications and permissions issues, but they don't appear to affect the install of mythtv-light.

At this point the MythTV software is installed and if you only want a frontend then you are done.

If you want a combo FE/BE, then we have to setup the backend now.

There is a utility to make this easier so clone the following repository:

Code: Select all

cd
git clone https://github.com/MikeB2013/pi-utils.git
cd pi-utils
edit pi-mythbackend-helper.sh

Make the following changes:

Code: Select all

mythtv_git_branch=fixes/33
php_version="8.2"
Now run the script (do not use sudo as that is included in commands in the script that need sudo):

Code: Select all

./pi-mythbackend-helper.sh
reboot
The Electronic Program Guides (EPG) received over-the-air (OTA) are not ideal and we will not be using them here. We will be using SchedulesDirect (SD) EPG. XMLTV will be used to gather the EPG from SD. In this case, it will be for OTA ATSC 1.0 TV. We will use the XMLTV grabber called 'tv_grab_zz_sdjson_sqlite' and follow the instructions at:https://www.mythtv.org/wiki/XMLTV.

This must be run as user 'mythtv'

Code: Select all

sudo su mythtv
cd
tv_grab_zz_sdjson_sqlite --manage-lineups --config-file $HOME/.mythtv/SD.xmltv
You can at this point add a lineup to your account or use your existing lineup.

Then select the "Initialize/update the local database"
Take the defaults on the next several questions until it exits.

Code: Select all

tv_grab_zz_sdjson_sqlite --configure --config-file $HOME/.mythtv/SD.xmltv
Take the default on database name/location.

Select the Lineup. If you only have one it will be listed and you can reply yes.

Take the defaults until the command exits.

Code: Select all

tv_grab_zz_sdjson_sqlite --days 0 --config-file $HOME/.mythtv/SD.xmltv
tv_grab_zz_sdjson_sqlite --manage-lineups --config-file $HOME/.mythtv/SD.xmltv
Select 'Manage database lineup channel selection'
Confirm your lineup.
Choose which channels are selected. Walk thru the channels and select yes or no.

When you're done with the list of channels, just exit.
Exit back to user 'pi' with 'exit'

Now setup the backend with:

Code: Select all

mythtv-setup
Under 1. General -> Host Address Backend Setup set Security PIN to 0000 and Primary IP Address/DNS Name to the IP address of the RPI4 which you can find out by hitting enter and just select it.

Under Job Queue (Backend-Specific) I uncheck 'Allow Transcoding Jobs' and 'Allow Commerical Detection Jobs'. The RPI4 is not good at transcoding and Commerical detection also affects performance. Your mileage may vary.

You can make other changes if you want.

Under 2. Capture cards, select New Capture Card 4 times since we have a 4 tuner HDHomerun. The first select of New Capture Card takes some time comparied to the next 3, so wait.

At each New Capture Card entry select HDHomeRun Networked Tuner then press the right arrow and check the tuner you want to use and then right arrow on Recording Options and uncheck Use HDHomeRun for active EIT scan since we are using SchedulesDirect for EPG.

Repeat for the other tuner entries.

Under 4. Video Sources, select New Video Source. It will take a few seconds.Then select the new entry for New Video Source and then select Video Source Name and enter 'SD' which is what we used in our XMLTV setup. Note upper-case 'SD'

For Listings Grabber select Multinational (Schedules Direct JSON Web Service with SQLite D...
Then ESC and save and exit.

Under 5. Input connections select 'MPEG2TS' under Input Name and select 'SD' under Video Source.
Then only on the first Input Connections go to Scan for Channels and go to the bottom and select Scan.
Insert All

ESC and save. Then set the other Input conections up the same, but don't scan for them.

The rest of the default settings of Input connections should work and also allow multi-channel recording for subchannels like 5.1 and 5.2 on the same tuner.

Use 6. Channel Editor if you have some channels you don't want displayed.

Under 7. Storage Group you should fill out at least Default but can do more to suit your needs. Walk the folders for Default to /srv/mythtv/recordings. All of our storage directories in this case are under /srv/mythtv/.

reboot

Now we need to put in some delay mechanism to make sure the HDHomerun tuners are on the network before mythtv-backend.service starts up.

You are going to have to delay the startup of mythtv-backend until the HDHomerun tuners are discoverable.
You will need to install a utility to communicate with the HDHR tuners:

Code: Select all

sudo apt install hdhomerun-config
Add an override to the mythtv-backend.service with:

Code: Select all

sudo --login systemctl edit mythtv-backend.service
Add or adjust the override file to include:

Code: Select all

[Service]
ExecStartPre=-/usr/local/bin/hdhomerun_check.py
Note the dash in the line above. That means that if the command fails, the backend will still start (so you
can watch recordings etc.) If you want to prevent the backend from starting, remove the dash.

You'll need to put the hdhomerun_check.py in /usr/local/bin and make it executable, owner/group root.

hdhomerun_check.py

Code: Select all

#!/usr/bin/python3
# -*- coding: utf-8 -*-

""" See if the HD Homerun box(s) are accessible and running

Requires Python 3.6 or later.

For backends started by systemd, use:

    sudo --preserve-env systemctl edit --force mythtv-backend.service

and enter or add as needed by your service:

    [Service]
    ExecStartPre=-/usr/local/bin/hdhomerun_check.py

Can be called with optional IP address(s) for users that
have multiple HDHRs that have STATIC addresses.

Use --help to see all options.

If run from the command line, then output will be to the screen.
Otherwise, a log file in /tmp named hdhr_discovery.log is made.
Changable with the --logfile switch.

Exit codes:

    0 = success (for *ALL* HDHRs if multiple IPs were specified)
    1 = no output from the hdhomerun_config discover command
    2 = IPv4 and IPv6 addresses found, disable IPv6 on NIC
    3 = logfile isn't writable, delete it and try again
    4 = keyboard interrupt
    5 x the number of HDHRs = HDHR is most likely not up

"""

__version__ = '1.28'

import argparse
import signal
import subprocess
import sys
from datetime import datetime
from os.path import basename
from os import _exit
from time import sleep


# pylint: disable=too-many-arguments,unused-argument
def keyboard_interrupt_handler(sigint, frame):
    ''' Handle all KeyboardInterrupts here. And, just leave. '''
    _exit(4)
# pylint: enable=unused-argument


def get_program_arguments():
    ''' Process the command line. '''

    parser = argparse.ArgumentParser(description='HDHR Access Test',
                                     epilog='*  Default values are in ()s')

    parser.add_argument('HOSTS', type=str,  default=None, nargs='*',
                        help='optional hostname(s)/IP(s) (%(default)s)')

    parser.add_argument('--attempts', default=20, type=int, metavar='<num>',
                        help='number of tries to find HDHRs (%(default)i)')

    parser.add_argument('--debug', action='store_true',
                        help='output additional information (%(default)s)')

    parser.add_argument('--logfile', default='/tmp/hdhomerun_check.log',
                        type=str, metavar='<lf>',
                        help='optional path + name of log file (%(default)s)')

    parser.add_argument('--sleep', default=1.5, type=float, metavar='<sec>',
                        help='seconds betweem attempts (%(default)s)')

    parser.add_argument('--version', action='version',
                        version='%(prog)s ' + __version__)

    return parser.parse_args()


def get_elapsed_time(start):
    ''' Calculate the time spent waiting for the HDHR to come up. '''

    delta = datetime.utcnow() - start
    rounded_delta = f'{delta.seconds + (delta.microseconds / 1000000):.3f}'
    return rounded_delta


def log_or_print(loglevel, message, output):
    ''' Add timestamp, log level then print to the selected location. '''

    print(datetime.now().strftime("%F %T.%f")[:-3], f'{loglevel:8}', message,
          file=output)


def last_message(loglevel, result, host, start, attempt, output):
    ''' Common success or failure message text. '''

    log_or_print(loglevel, f'{result} {"at " + host  + " " if host else ""}'
                 f'in {get_elapsed_time(start)} seconds '
                 f'and {attempt} attempt{"s"[attempt == 1:]}\n', output)


def check_one_device(host, args, output):
    ''' Try to discover the HDHR(s). '''

    attempt = 0
    command = ['hdhomerun_config', 'discover']
    start = datetime.utcnow()

    if host:
        command.append(host)

    for attempt in range(1, args.attempts+1):

        try:
            discovery_response = subprocess.check_output(
                command, text=True, stderr=subprocess.STDOUT).split()
        except subprocess.CalledProcessError:
            log_or_print('WARNING', f'{command[0]}: got no response, attempt: '
                         f'{attempt:2}', output)
            sleep(args.sleep)
            continue

        if not discovery_response:
            log_or_print('ERROR', f'No output from {command[0]}, aborting!',
                         output)
            sys.exit(1)

        if args.debug:
            log_or_print('DEBUG', f'Got: {" ".join(discovery_response)}',
                         output)

        if discovery_response.count('hdhomerun') > 1:
            log_or_print('ERROR', f'{command[0]}: more than 1 IP, aborting!',
                         output)
            sys.exit(2)

        if discovery_response[0] != 'hdhomerun':
            # Consider making this an ERROR and exiting not sleeping...
            log_or_print('WARNING', f'{command[0]} got an unexpected response:'
                         f' {" ".join(discovery_response)}',
                         output)
            sleep(args.sleep)
        else:
            last_message('INFO', f'Found HDHR {discovery_response[2]}', host,
                         start, attempt, output)
            return 0

    last_message('ERROR', 'No HDHR found', host, start, attempt, output)

    return 5


def main(args, output=None):
    ''' Control checking of one or more devices. '''

    log_or_print('INFO', f'Starting {basename(__file__)} v{__version__}, '
                 f'attempts={args.attempts}, sleep={args.sleep:.2f}', output)

    if args.HOSTS:

        return_value = 0

        for host in args.HOSTS:
            return_value += check_one_device(host, args, output)

    else:
        return_value = check_one_device(None, args, output)

    return return_value


if __name__ == '__main__':

    signal.signal(signal.SIGINT, keyboard_interrupt_handler)

    ARGS = get_program_arguments()

    if sys.stdin and sys.stdin.isatty():
        RETURN_VALUE = main(ARGS)
    else:
        try:
            with open(ARGS.logfile, encoding='ascii', mode='a') as file_obj:
                RETURN_VALUE = main(ARGS, output=file_obj)
        except PermissionError:
            print(f'Can\'t write to {ARGS.logfile}, aborting!')
            sys.exit(3)

    sys.exit(RETURN_VALUE)

# vim: set expandtab tabstop=4 shiftwidth=4 smartindent colorcolumn=80:
At this point you should be able to boot the RPI4 and mythtv-backend.service should start and find the HDHR tuner.
You can run mythfrontend as on any system and configure it for the RPI4 as has been documented elsewhere on this forum catefory.

Now we can execute "mythfrontend" and setup and Audio and Video as below:

In Setup -> Audio -> Audio Output Device select "ALSA:hdmi:CARD=vc4hdmi0,DEV=0"
Setup Digital Audio and speakers base on your audio system.

In Setup -> Video -> Playback change what you want but the critical ones are:
Change the Current Video Playback Profile to OpenGL Normal and drill down to change Max CPUs to 4 and Deinterlacer Quality (single rate) to Low quality. Do the same for Deinterlacer quality (double rate).

Performance settings.

The RPI4 standard settings are all you need for a good picture. However, you can improve the FPS jitter statistics by overclocking. I have found that the RPI4 can be overclocked and still be reliable. Most all RPI4s can overclock to 2.0 Ghz. The unit in this case is the newest RPI4 stepping and by default on Bullseye runs at 1.85Ghz. More RPI4 overclocking information at https://magpi.raspberrypi.com/articles/ ... erry-pi-4

I overclocked it as follows:

edit /boot/config.txt
add these lines to the file:

Code: Select all

arm_freq=2147
over_voltage=6
gpu_freq=750
Setup fstrim for the SSD

Since we are using a SSD we need to setup automatic trim once a week. The service that controls this is fstrim.service/timer.

Use 'lsusb' to find the vendor and product IDs for your USB3-SATA adapter. Mine is an ASMedia ASM1153E controller (Eluteng adapters) and "lsusb" shows:

Code: Select all

Bus 002 Device 002: ID 174c:55aa ASMedia Technology Inc. ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge...
So I need to create a file in /etc/udev/rules.d/ called 01-asmedia-trim.rules containing:

Code: Select all

# ASMedia ASM1153E controller (Eluteng adapters)
ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="55aa", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"
Enable and start fstrim:

Code: Select all

sudo systemctl enable --now fstrim.timer
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

When I run
mythtv-setup

I get an error

Could not connect to display
Could not load the Qt platform plugin "xcb" in "" even though it was found.
This aplication failed to start because no Qt plugin could be Initialised
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

Are you running a desktop environment?
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

No
But it worked ok this way on my previous install
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

it did, but that was then, this is now. I installed and tested that on a standard Raspberry Pi OS 64 bit Bookworm with the standard desktop. All console commands were run using the console app not without a DE.
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

Ok installed with a desktop and on a second pi4 with just mythtv-light.
Have a couple of issues.
My remote frontend wont connect to the backend.
If I run the frontend on the master server it will only connect to local host. If I tell it to connect to the IP address it fails

Also when I do run the frontend and go to system status for the Inputs all my inputs say errored and if i try to watch tv it says they are all busy.
But I can scan for channels in the setup
Any Ideas?
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

The busy tuners are mostly caused by you not putting in the wait into the systemd. Look in this thread for:

"Add an override to the mythtv-backend.service "

Otherwise you will have to restart the backend systemd service after you are booted.

As the connecting to a remote backend you need to edit some mariadb files on the backend.

I have a file in /etc/mysql/mariadb.conf.d called mythtv.cnf that contains

Code: Select all

[mysqld]
bind-address=*
max_connections=100
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

The busy tuners are mostly caused by you not putting in the wait into the systemd. Look in this thread for:

"Add an override to the mythtv-backend.service "
I had trouble with that part when run
sudo --login systemctl edit mythtv-backend.service
and add the text and then try to save it I get
Editing "/etc/systemd/system/mythtv-backend.service.d/override.conf" canceled: temporary file is empty.
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

As the connecting to a remote backend you need to edit some mariadb files on the backend.

I have a file in /etc/mysql/mariadb.conf.d called mythtv.cnf that contains

Code: Select all

[mysqld]
bind-address=*
max_connections=100
Thanks I can now connect :D
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

Did you add the text :

Code: Select all

[Service]
ExecStartPre=-/usr/local/bin/hdhomerun_check.py
Where is says to place the override text?

Code: Select all

### Editing /etc/systemd/system/mythtv-backend.service.d/override.conf
### Anything between here and the comment below will become the new contents of>

------>>>>    put it right here

### Lines below this comment will be discarded
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

No I'd put it in the wrong place.
Have done now and it lets me save it.

No change to tuner status
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

Make sure you create the hdhomerun_check.py command and make it executeable
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

jfabernathy wrote:
Sun Feb 11, 2024 6:35 pm
Make sure you create the hdhomerun_check.py command and make it executeable
I had. Just redone it for no change
User avatar
jfabernathy
Senior
Posts: 612
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by jfabernathy »

Either run

Code: Select all

hdhomerun_check.py
manually and look for errors or check the log with either:

Code: Select all

systemctl status mythtv-backend.service
or

Code: Select all

sudo jounalctl -b -u mythtv-backend.service
Make sure you have installed hdhomerun-config

Code: Select all

sudo apt install hdhomerun-config
Do you only have 1 HDHomerun network tuner? If you have more then the hdhomerun_check command needs the IP address of the tuner you want.
keef256
Junior
Posts: 43
Joined: Fri Apr 22, 2022 3:38 pm
Great Britain

Re: How to install mythtv-light v33 on RPI OS 64 bit Bookworm

Post by keef256 »

It's working. :D
For some reason the hdhomerun_check.py file was not executable.
Post Reply