How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

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

How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

Post by jfabernathy »

Here's how I installed it. You'll note that this is very similar to the Ubuntu 22.10 version. Updated in key places.

You can use Raspberry Pi Imager v1.7.4 or higher and under "Choose OS", select "Other general-purpose OS" -> Ubuntu -> Ubuntu Desktop 23.04 (64-bit). The Imager program will download and flash the OS to your Storage device. Since you are going to need a lot of GBs to record TV, I'd say use a big SATA SSD with a USB3 to SATA adapter.

Plug in the SSD to the RPI4 and boot. The setup and update of Ubuntu is slow and not a good sign but after the upgrade it seems to be very responsive.

If your internet connection is via your RJ45 Ethernet, plug your HDHomerun tuner into your router.

If your internet connection is via your WiFi you can use your RJ45 Ethernet port to directly connect your HDHomerun tuner. If you use this method you will need to use the Network Settings to edit your Ethernet as follows:

In the IPv4 tab:

Set Method to Local-link only
Check the box for "Require IPv4 addressing for this connection to complete"

In the IPv6:
Set the Method to Disabled

When you install MythTV it will create a user account for 'mythtv'. If you want more control over this you can create it ahead of installation. Ubuntu has been known to change the default options of the adduser command between releases, so I use the following commands:

Code: Select all

sudo addgroup --gid 200 mythtv
sudo adduser --ingroup mythtv --home /home/mythtv --shell /bin/bash --uid 200 mythtv
Also if you want to use mariadb instead of mysql this is the time to make that choice. To use mariadb do the following:

Code: Select all

sudo apt install mariadb-server
Next add the MythTV PPA to your list of repositories.

Code: Select all

sudo add-apt-repository ppa:mythbuntu/33
Then install MythTV with:

Code: Select all

sudo apt install mythtv
The first run of mythtv-setup will add your user ($USER) to the 'mythtv' group.

So now run:

Code: Select all

mythtv-setup
It will ask your permission to setup your user as a member of the mythtv group. Once this is done, just reboot to guarantee that your user is now apart of the mythtv group.

You'll need to setup your mythtv directories before completing setup. I use /srv/mythtv as my storage area. Here's a script to do that. Save this as create_directories.sh and make executable:

Code: Select all

#! /bin/bash

# Globals
mythtv_storagegroup_path=/srv/mythtv/ # using /srv/mythtv in preference to /var/lib/mythtv/,
mythtv_storagegroups="banners coverart fanart recordings streaming videos bare-client db_backups  livetv sports screenshots trailers music musicart"

fn_setup_directories()
{
sudo mkdir -p $mythtv_storagegroup_path
cd $mythtv_storagegroup_path
sudo mkdir -p $mythtv_storagegroups
sudo chown -R mythtv:mythtv $mythtv_storagegroup_path
sudo chmod -R  2775 $mythtv_storagegroup_path

}


#main
# make sure we are not root
RUNNINGAS=`whoami`
if [ $RUNNINGAS = "root" ] ; then
    echo "Please run as ordinary user, not with sudo"
    exit 1
fi

#check mythbackend has been installed, if not abort with message
MYTHBACKEND=`which mythbackend`
if [ -z "$MYTHBACKEND" ]; then
    echo -e "mythbackend not found - please install MythTV-Light package"
    echo -e "For official builds (when available) 'https://www.mythtv.org/wiki/MythTV_Light'\n"
    echo -e "For test builds 'https://forum.mythtv.org/viewtopic.php?f=46&t=3221&start=15'\n"
    exit 1
fi

fn_setup_directories


exit 0
If you want to setup an EPG provider do that now or just use EIT Video Source in mythtv-setup.

I use SchedulesDirect via tv_grab_zz_sdjson_sqlite. So I install XMLTV by:

Code: Select all

sudo apt install xmltv
Then I use the instructions at

https://www.mythtv.org/wiki/XMLTV#Setup ... son_sqlite

BUT make sure to run them as user "mythtv" by:

Code: Select all

sudo su mythtv
cd
Exit back to your normal user and complete mythtv-setup.

Code: Select all

mythtv-setup
At this point you can test this out by restarting the backend with:

Code: Select all

sudo systemctl restart mythtv-backend.service
Then you can test out "mythfrontend"

However, for mythtv-backend to start up properly after booting the RPI4, you are going to have to delay the startup of mythtv-backend until the HDHomerun tuners are discoverable.

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.
Last edited by jfabernathy on Sat Apr 29, 2023 10:42 am, edited 1 time in total.
User avatar
jfabernathy
Senior
Posts: 577
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

Post by jfabernathy »

A couple of additions I like to add to my MythTV setup. First is Mythweb. Just install it from the ppa:

Code: Select all

sudo apt install mythweb
Next I like to setup a systemd timer/service to manage mythfilldatabase to my needs. First in mythtv-setup -> General section, I uncheck the box for automatic Program guide update. Then I create a service called:

Code: Select all

sudo --preserve-env systemctl edit --force --full mythfilldatabase.service
Put these options into the edit (nano) window:

Code: Select all

[Unit]
Description=MythTV mythfilldatabase service.
Wants=mythtv-backend.service
After=mythtv-backend.service
 
[Service]
User=mythtv
Group=mythtv
Type=simple
ExecStart=/usr/bin/mythfilldatabase
 
[Install]
WantedBy=multi-user.target
Then create a timer with:

Code: Select all

sudo --preserve-env systemctl edit --force --full mythfilldatabase.timer
Put in these options:

Code: Select all

[Unit]
Description=MythTV mythfilldatabase timer.
 
[Timer]
OnCalendar=05:10:00
OnCalendar=17:10:00
Persistent=true
 
[Install]
WantedBy=timers.target
Note I have this running in the early morning and early evening. You can delete one of those times if you want. I usually only run one.

Finally you need to enable the timer to run the service with :

Code: Select all

sudo systemctl enable --now mythfilldatabase.timer
Last edited by jfabernathy on Sat Apr 29, 2023 11:13 am, edited 2 times in total.
User avatar
jfabernathy
Senior
Posts: 577
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

Post by jfabernathy »

To keep your mythconverg database in tip top condition I like to optimize it and back it up daily. I disable the weekly cron job that does that now and use a systemd service/timer and a shell script.

Here the command to put in /usr/local/bin/mythtv-database-backup.sh. Make sure you edit the 'USER=jim' to match your username.

Code: Select all

#!/bin/sh
# /etc/cron.weekly/mythtv-database script - check and backup mythconverg tables
# Copyright 2005/12/02 2006/10/08 Paul Andreassen
#                      2010 Mario Limonciello

set -e -u

DBNAME="mythconverg"
USER=jim
EMAILADDRESS="your-email-here@gmail.com"

/usr/bin/mysqlcheck -s $DBNAME

BKUP_LOG=/tmp/backup-mythconverg.log

export MYTHCONFDIR=/home/$USER/.mythtv/

/usr/share/doc/mythtv-backend/contrib/maintenance/optimize_mythdb.pl | grep -v "^Analyzed:" 2>&1 >> $BKUP_LOG

sudo --preserve-env --user=$USER /usr/share/mythtv/mythconverg_backup.pl --rotate=5 --verbose 2>&1 >> $BKUP_LOG

if [ $? -eq 0 ]; then
    MSG="den-pc $DBNAME Checked and Backed Up, RC=$?"
else
    MSG="den-pc $DBNAME Back Up Failed, RC=$?"
fi

cd /srv/mythtv/db_backups
ls -l --directory --block-size=K * | tail -10 >> $BKUP_LOG

#mail -s "$MSG" $EMAILADDRESS < $BKUP_LOG
Make the scripts executable.

Setup a service with

Code: Select all

 sudo --preserve-env systemctl edit --force --full mythtv-database-backup.service
Put these options in the edit (nano) window:

Code: Select all

# This service unit is for backing up the mythtv database called mythconverg
#
[Unit]
Description=Backup MythTV Database 'mythconverg'
Requires=mysql.service
After=mysql.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/mythtv-database-backup.sh 
Next setup the timer with

Code: Select all

sudo --preserve-env systemctl edit --force --full mythtv-database-backup.timer
Put these options in:

Code: Select all

# This timer unit is for mythtv-database-backup
# by Jim Abernathy
# Licensed under GPL V2
#

[Unit]
Description=start mythtv-database-backup

[Timer]
Unit=mythtv-database-backup.service
OnCalendar=*-*-* 05:30:00
AccuracySec=5minutes
RandomizedDelaySec=10minutes
Persistent=true

[Install]
WantedBy=timers.target
Next enable the timer with:

Code: Select all

sudo systemctl enable --now mythtv-database-backup.timer
Note that the mythtv-database-backup.sh script can be easily made to email your external mail account if you have that setup on your system. Otherwise you can look at the file that would be emailed in the /tmp directory.
Last edited by jfabernathy on Sat Apr 29, 2023 12:15 am, edited 3 times in total.
User avatar
heyted
Senior
Posts: 301
Joined: Sun Jun 08, 2014 2:14 am
Location: South Florida
Contact:
United States of America

Re: How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

Post by heyted »

I copied the installation steps shown in the first post above to the wiki. Thanks for the excellent write up Jim.
Ted | My blog
User avatar
jfabernathy
Senior
Posts: 577
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

Post by jfabernathy »

heyted wrote:
Sat Apr 29, 2023 7:24 pm
I copied the installation steps shown in the first post above to the wiki. Thanks for the excellent write up Jim.
This forums editor makes it easy to document code. IMHO the Wiki's do not. It reminds me of using Wordperfect back on IBM DOS 2.0

Thanks for taking the time and effort to put it in the wiki.
User avatar
jfabernathy
Senior
Posts: 577
Joined: Wed Feb 18, 2015 2:37 pm
Location: Raleigh, NC
United States of America

Re: How to build MythTV on Ubuntu 23.04 on a RPI4 4GB

Post by jfabernathy »

As a way to improve performance of my RPI4 with Ubuntu 23.04, I decided to test it with snapd removed. It worked fine and at least Firefox works better. I followed the Ubuntu distro instructions at:
https://itsfoss.com/remove-snap/#remove ... e-caution-
Post Reply