OliveTin for Channels: An Interface for Misc Channels DVR Scripts & Tricks

That is correct.

That sounds like a great idea. How would I go about creating my own XML guide data?

I don't have the experience creating XMLTV files but if I wanted to try, I would ask for help from an AI, such as chatGPT. :wink:

Here is an example created by chatGPT:

<?xml version="1.0" encoding="UTF-8"?>
<tv>
  <channel id="channel1">
    <display-name>Channel 1</display-name>
  </channel>
  <channel id="channel2">
    <display-name>Channel 2</display-name>
  </channel>
  <programme start="20240917180000 +0000" stop="20240917190000 +0000" channel="channel1">
    <title>News</title>
    <desc>Evening news program</desc>
  </programme>
  <programme start="20240917190000 +0000" stop="20240917200000 +0000" channel="channel2">
    <title>Movie</title>
    <desc>Action movie</desc>
  </programme>
</tv>

I'm guessing you probably need the channel IDs in there so that Channels DVR can match them with the channels that it knows about.

What @mjitkop posted above looks reasonable as a starting point, and although you could use a regular editor or spreadsheet to manage it, something along these lines would probably be easiest:

1 Like

Also, for the complete format that definitely works in Channels, open one XMLTV file used in one custom channel source, if you have one.

@bnhf @mjitkop thank y’all! I just asked ChatGPT to and it created it. I didn’t realize AI was this useful to understanding how all of this works.

I'm having trouble installing SLM via olivetin. My configuration is I have Channels running on a Synology NAS. Channels is installed from Package Manager (not in a docker container). I have Tailscale installed on the NAS with MagicDNS running a "cjynas" maps to the IP of the NAS (192.189.0.11).

If I shell into the NAS, here is where my Channels installed:

If I run Olivetin and attempt an install of SLM, I fill out the form like this:

When it runs it gets an error that it cannot resolve the host "cjynas". Here is standard error output:

Summary
exit status 1

++ basename /config/slm.sh
+ extension=slm.sh
+ extension=slm
+ cp /config/slm.env /tmp
+ envFile=/tmp/slm.env
+ envVars=("TAG=$1" "SLM_PORT=$2" "TIMEZONE=$3" "CHANNELS_FOLDER=$4")
+ printf '%s\n' TAG=latest SLM_PORT=5000 TIMEZONE=US/Pacific CHANNELS_FOLDER=/volume1/ChannelsDVR
+ sed -i /=#/d /tmp/slm.env
+ /config/portainerstack.sh slm
+ stackName=slm
+ portainerHost=cjynas
+ curl -s -o /dev/null http://cjynas:9000
+ portainerURL='https://cjynas:9443/api/stacks?type=2&method=string&endpointId=2'
+ portainerToken=ptr_mCoUK4hpSQnjOh42V0qeZsrfdOX0hmPEV0HkVoQ/LnY=
+ cp /config/slm.yaml /tmp
+ stackFile=/tmp/slm.yaml
+ envFile=/tmp/slm.env
++ grep DVR_SHARE= /tmp/slm.env
++ grep -v /
++ awk -F= '{print $2}'
+ dockerVolume=
++ grep VOL_EXTERNAL= /tmp/slm.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ volumeExternal=
++ grep VOL_NAME= /tmp/slm.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ volumeName=
++ grep NETWORK_MODE= /tmp/slm.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ networkMode=
++ grep DEVICES= /tmp/slm.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ transcoderDevice=
++ grep CDVR_CONTAINER= /tmp/slm.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ stackNumber=
+ [[ -n '' ]]
+ [[ -n '' ]]
+ [[ -n '' ]]
+ [[ -n '' ]]
++ sed 's/\\/\\\\/g' /tmp/slm.yaml
++ sed 's/"/\\"/g'
++ awk '{printf "%s\\n", $0}'
+ stackContent='version: '\''3.9'\''\nservices:\n  # 2024.09.12\n  # GitHub home for this project with setup instructions: https://github.com/babsonnexus/stream-link-manager-for-channels\n  # Docker container home for this project: https://ghcr.io/babsonnexus/stream-link-manager-for-channels\n  slm:\n    image: ghcr.io/babsonnexus/stream-link-manager-for-channels:${TAG:-latest}\n    container_name: slm\n    ports:\n      - ${SLM_PORT:-5000}:5000\n    environment:\n      - TZ=${TIMEZONE:-UTC}\n    volumes:\n      - slm_files:/app/program_files\n      - ${CHANNELS_FOLDER}:/app/channels_folder\n    restart: unless-stopped\nvolumes:\n  slm_files:\n\n# Default Environment variables can be found below under stderr -- copy and paste into Portainer-Stacks Environment variables section in Advanced mode\n'
+ stackEnvVars='['
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "SLM_PORT", "value": "5000"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "SLM_PORT", "value": "5000"},{"name": "TIMEZONE", "value": "US/Pacific"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "SLM_PORT", "value": "5000"},{"name": "TIMEZONE", "value": "US/Pacific"},{"name": "CHANNELS_FOLDER", "value": "/volume1/ChannelsDVR"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "latest"},{"name": "SLM_PORT", "value": "5000"},{"name": "TIMEZONE", "value": "US/Pacific"},{"name": "CHANNELS_FOLDER", "value": "/volume1/ChannelsDVR"}]'
++ cat
+ stackJSON='{
  "Name": "slm",
  "SwarmID": "",
  "StackFileContent": "version: '\''3.9'\''\nservices:\n  # 2024.09.12\n  # GitHub home for this project with setup instructions: https://github.com/babsonnexus/stream-link-manager-for-channels\n  # Docker container home for this project: https://ghcr.io/babsonnexus/stream-link-manager-for-channels\n  slm:\n    image: ghcr.io/babsonnexus/stream-link-manager-for-channels:${TAG:-latest}\n    container_name: slm\n    ports:\n      - ${SLM_PORT:-5000}:5000\n    environment:\n      - TZ=${TIMEZONE:-UTC}\n    volumes:\n      - slm_files:/app/program_files\n      - ${CHANNELS_FOLDER}:/app/channels_folder\n    restart: unless-stopped\nvolumes:\n  slm_files:\n\n# Default Environment variables can be found below under stderr -- copy and paste into Portainer-Stacks Environment variables section in Advanced mode\n",
  "Env": [{"name": "TAG", "value": "latest"},{"name": "SLM_PORT", "value": "5000"},{"name": "TIMEZONE", "value": "US/Pacific"},{"name": "CHANNELS_FOLDER", "value": "/volume1/ChannelsDVR"}]
}'
+ echo 'JSON response from https://cjynas:9443/api/stacks?type=2&method=string&endpointId=2:'
++ curl -k -X POST -H 'Content-Type: application/json' -H 'X-API-Key: ptr_mCoUK4hpSQnjOh42V0qeZsrfdOX0hmPEV0HkVoQ/LnY=' -d '{
  "Name": "slm",
  "SwarmID": "",
  "StackFileContent": "version: '\''3.9'\''\nservices:\n  # 2024.09.12\n  # GitHub home for this project with setup instructions: https://github.com/babsonnexus/stream-link-manager-for-channels\n  # Docker container home for this project: https://ghcr.io/babsonnexus/stream-link-manager-for-channels\n  slm:\n    image: ghcr.io/babsonnexus/stream-link-manager-for-channels:${TAG:-latest}\n    container_name: slm\n    ports:\n      - ${SLM_PORT:-5000}:5000\n    environment:\n      - TZ=${TIMEZONE:-UTC}\n    volumes:\n      - slm_files:/app/program_files\n      - ${CHANNELS_FOLDER}:/app/channels_folder\n    restart: unless-stopped\nvolumes:\n  slm_files:\n\n# Default Environment variables can be found below under stderr -- copy and paste into Portainer-Stacks Environment variables section in Advanced mode\n",
  "Env": [{"name": "TAG", "value": "latest"},{"name": "SLM_PORT", "value": "5000"},{"name": "TIMEZONE", "value": "US/Pacific"},{"name": "CHANNELS_FOLDER", "value": "/volume1/ChannelsDVR"}]
}' 'https://cjynas:9443/api/stacks?type=2&method=string&endpointId=2'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: cjynas
+ portainerResponse=
+ [[ -z '' ]]
+ exit 1
+ [[ 1 == 1 ]]
+ exit 1

Any ideas what to check?

I believe what you're seeing is unrelated to slm, so we should probably move this discussion. Could you run the OliveTin Post-Install Healthcheck, and post the results in the OliveTin thread?

Thanks. Here it is.

Standard Output
Checking your OliveTin installation...
(extended_check=false)

----------------------------------------

Checking that your selected Channels DVR server (192.168.0.11:8089) is reachable by URL:
HTTP Status: 200 indicates success...

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  1276  100  1276    0     0  1246k      0 --:--:-- --:--:-- --:--:-- 1246k
HTTP Status: 200
Effective URL: http://192.168.0.11:8089/

----------------------------------------

Checking that your selected Channels DVR server's data files (/mnt/192.168.0.11-8089) are accessible:
Folders with the names Database, Images, Imports, Logs, Movies, Streaming and TV should be visible...

total 20
drwxrwxrwx 1 root   root      22 May 29 06:00 #recycle
drwx------ 1 242120 root     170 Sep 20 16:50 .
drwxr-xr-x 1 root   root      78 Sep 19 14:54 ..
-rwxrwx--- 1   1026 users  18436 Jul 24 06:25 .DS_Store
drwxrwxrwx 1 root   root     334 Apr 24 10:09 @eaDir
drwxrwx--- 1   1026 users   1350 Sep 19 19:51 Database
drwxrwx--- 1   1026 users 230598 Sep 20 18:30 Images
drwxrwx--- 1   1026 users     58 Mar 18  2022 Imports
drwxrwx--- 1   1026 users     62 Feb  1  2021 Logs
drwxrwx--- 1   1026 users  25932 Sep 20 16:50 Movies
drwxrwx--- 1   1026 users  10162 Sep 20 18:30 Streaming
drwxrwx--- 1   1026 users   8232 Sep 20 16:50 TV
drwxrwx--- 1   1026 users     50 Jan 16  2023 strmlnkTemplates
drwxrwx--- 1   1026 users      0 Jan 21  2024 temp

----------------------------------------

Checking that your selected Channels DVR server's log files (/mnt/192.168.0.11-8089_logs) are accessible:
Folders with the names data and latest should be visible...

total 4
drwxr-xr-x 1 242120 242120  200 Sep 16 19:50 .
drwxr-xr-x 1 root   root     78 Sep 19 14:54 ..
drwxr-xr-x 1 242120 242120  154 Sep  4 19:28 2024.09.05.0212
drwxr-xr-x 1 242120 242120  134 Sep 10 15:31 2024.09.10.2115
drwxr-xr-x 1 242120 242120  154 Sep 11 15:32 2024.09.11.1846
drwxr-xr-x 1 242120 242120  154 Sep 12 10:02 2024.09.12.1557
drwxr-xr-x 1 242120 242120  154 Sep 13 09:32 2024.09.13.1554
drwxr-xr-x 1 242120 242120  154 Sep 16 19:50 2024.09.17.0218
drwxr-xr-x 1 242120 242120 4506 Sep 20 18:22 data
lrwxrwxrwx 1 242120 242120   15 Sep 16 19:50 latest -> 2024.09.17.0218

----------------------------------------

Here's a list of your current OliveTin-related settings:

HOSTNAME=olivetin
CHANNELS_DVR=192.168.0.11:8089
CHANNELS_DVR_ALTERNATES=
CHANNELS_CLIENTS=apple-tv
ALERT_SMTP_SERVER=smtp.gmail.com:587
ALERT_EMAIL_FROM=[Redacted]@gmail.com
ALERT_EMAIL_PASS=[Redacted]
ALERT_EMAIL_TO=[Redacted]@gmail.com
UPDATE_YAMLS=true
UPDATE_SCRIPTS=true
PORTAINER_TOKEN=[Redacted]
PORTAINER_HOST=cjynas

----------------------------------------

Here's the contents of /etc/resolv.conf from inside the container:

search tail[Redacted].ts.net
nameserver 127.0.0.11
options ndots:0

----------------------------------------

Here's the contents of /etc/hosts from inside the container:

127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.31.0.3	olivetin

OK, a couple of ideas:

First in your OliveTin DOMAIN env var, I'd try adding your local search domain (mine is localdomain), in addition to your tailnet domain. These should be space separated, and in the order you'd like them searched. Something like this:

DOMAIN=localdomain tailxxxxx.ts.net

For this to be effective, cjynas needs to resolve locally (cjynas.localdomain), as well as via MagicDNS on your tailnet.

Second, if you don't want to mess with why local DNS resolution isn't working properly, you could simply use 192.168.0.11 as your PORTAINER_HOST value rather than the MagicDNS name.

If you're looking for a quick resolution, this is probably the way to go. Otherwise, as you know :slight_smile:, I'll hang in there with you to get to the bottom of LAN DNS resolution issues, but that's probably not the easy, expedient path.

I got it working with changing PORTAINER_HOST to 192.168.0.11 instead of the magicDNS name of cjynas. But prior to this I tried the following which both failed to resolve cjynas:

  1. In Synology world it's localhost so I tried DOMAIN=localhost tailxxxxx.ts.net.
  2. Then I noticed that I was not using the full Tailscale domain name. According to the Tailscale control panel it is cjynas.tailxxxx.ts.net. So I tried DOMAIN=localhost cjynas.tailxxxxx.ts.net. Did not work.

So this this is the third thing I tried that works:
DOMAIN=localhost tailxxxxx.ts.net
PORTAINER_HOST=192.168.0.11

SLM is running with this config but if you would like to find out why cjynas was not resolving, I'm game to troubleshoot.

Edited: To note that I have not starting using SLM so I'm not sure if I have everything working properly. I'm still plugging through the SLM installation video but will try to finish viewing the install video tomorrow morning.

@bnhf

Is it possible to add an OLIVETIN alert to see if the ChannelsDVR service/app is running if not to send an alert ?

That's actually what the "Ping Channels DVR Server" Action does. It does a curl of the Channels DVR URL, and then confirms success via healthchecks.io. If that confirmation is missed, then healthchecks.io will inform you by e-mail or other notifications platform (they support many).

I use it for both of my CDVR servers, one local and one remote. It's worked really well for me, by way of letting me know there's some sort of issue, often long before I would find out otherwise, through missed recordings and the like:

screenshot-channels-2024_09_24-08_28_35

I tried with a fake IP did not get an alert .... my server is at 192.168.50.162 oops maybe I have to wait 30 m

Background script initiated, with 30 between runs for 192.168.50.163:8089
foreground.sh is exiting for pingcdvr with exit code 0


Tue Sep 24 07:41:43 PDT 2024
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:03 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:04 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:05 --:--:--     0
curl: (28) Connection timed out after 5001 milliseconds
HTTP Status: 000
Effective URL: http://192.168.50.163:8089/

What does it show on the healthchecks.io website under "Last Ping" for the ping URL you set up? The frequency you set in the OliveTin Action should match the frequency you set on the healthchecks.io site (there's also a grace period in healthchecks.io, which I usually set to 5 minutes).

1 Like

I have the default never changed that ?

[type or paste code here](https://hc-ping.com/your_custom_uuid)

That's just an example of the format, and is the equivalent of "none".

You need to go to the healthchecks.io website, and set up a free account. Then for each "ping" you want to monitor, you set up a "check" with a unique name. If healthchecks.io fails to hear from OliveTin in the prescribed time period it'll send you an e-mail or other notification.

The same process is used in several OliveTin Actions as a way to notify you if they're no longer running. One of the nice things about this approach is that you know something's amiss even if OliveTin itself, or the host it runs on, is down.

1 Like

@bnhf is it currently possible to setup multiple email log alerts at the same time? I have multiple servers and they all show in the drop-down but it seems I can only choose one of them.

You can set up as many as you like using your defined servers (one set of alerts per server) -- but they are done one at a time. Each creates its own background process. To kill any, or all of them, reverse the process by selecting each server and entering 0 for the interval.

Due to a bug in the current version of the base OliveTin project, you'll want to refresh your browser tab between establishing (or killing) each log alert. Hopefully, next time I upgrade the underlying version of OliveTin, this will be addressed.

@bnhf Do I have to use Portainer, as I have an Unraid server and can use the Compose file in there. If so, how would the compose file and Env file look not using portainer? Right now I tried it and I'm getting a websocket error. Any ideas??

Yes. This project is supported only via Portainer. Project One-Click, in particular, uses the Portainer API for deployments.