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

Your inputs and ideas are greatly appreciated, @Fofer. :smiley:

Please see this thread to contribute to and/or follow the progression of the project:

I love your idea of the recently added channels and I want it so it will happen. I will be working on it but if somebody beats me to it, that's perfectly fine. :slightly_smiling_face:

I’m having trouble accessing the Olive Tin page after deploying the stack. The page doesn’t exist at https://10.0.0.37:1337. I’m using Docker via Portainer on Synology. Channels is running locally on the same server (not in Docker). I’m sure it’s probably an environmental variable that isn’t set correctly. Logs from the container are below. Any suggestions?

Stack environmental variables:

The OliveTin URL is http:// not https://

Also:

Leave CHANNELS_DVR2_HOST and CHANNELS_DVR2_PORT empty if you don't have another CDVR server you want to use OliveTin with.

Otherwise, things look good.

Got it. I mistakenly heard https in the demo video. The DVR2 lines are commented out in the compose, so it isn’t looking at them. Thanks!

Works great. I don't believe you need to ask for the mlb.tv username and password now as it authenticates like the other applications now as well.

2 Likes

New bnhf/olivetin:latest (aka bnhf/olivetin:2024.09.16) pushed with new Project One-Click support for creating docker-based Channels DVR servers.

This can be used for a primary CDVR server, secondary special purpose CDVR servers -- or just to spin one up to experiment on something where you'd prefer not to use your "production" server. Up to 11 servers can be created, with host or bridge networking, and support for Intel Quick Sync transcoding. Your DVR recordings directory can be set to be local, or a network share:

I am hosting Channels on a Synology NAS. What version of OliveTin do I need to install? Any special installation instructions to be aware of?

You'll need to install Portainer -- and, I believe there are several online guides for doing that on Synology. No special version of OliveTin, which is one of the beauties of Docker, as the idea is to be cross-platform.

One unique thing about Synology, is that any directories that need to be created when deploying a Docker container need to be created prior to deploying the container, or deployment will fail. Other than that, it's pretty standard.

@bnhf Is it possible creating a way like you have it for manual recordings but be for schedule recordings. For example, Dallas Stars went to streaming only on Victory Plus. I have a script setup in Home Assistant to open the app and start to play but I haven't found a way to automate the schedule of the games. Like if I had all the dates that they were playing I could input them in or pull from a set of data like a Google Sheet or something but just an easier way of automating recordings that don't have guide data. Thanks!

Since the games would be at various times on an irregular set of days, it's not like we could just setup a schedule to record every Monday at 8:00pm, right?

I wonder if you could create a custom channel source, that would be just be a channel for the Dallas Stars, and then simply provide your own XML guide data -- which probably could be done with a Google Sheet, although there are likely more elegant ways. That way, a CDVR recording pass could be set up as usual.

OliveTin has a built-in static file server which could host such an XML file locally on your LAN, and be used in a custom channel source.

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.