AndroidHDMI for Channels (ah4c): A virtual channel tuner using HDMI Encoder(s) + streaming stick(s)

It's summer again (almost), more free time to muck about. I

have been trying to figure out how to get ah4c to have a unified m3u play list with different sources (YouTube tv, sling, Hulu, etc). Booted up my back up server and Managed to come with something but could do with some help to make it better. This is what I have working so far with some pay per view channels from YouTube tv and from the HBO max app combined into one m3u.

I am not using the docker version, to be clear.

Sample of "masterppv_contentid.txt" :

501 hbo a903ca8a-6d5e-559b-a027-f82997397694/452e5d78-1cca-59a9-8508-21b25d813874
502 hbo2 0326bb1d-35a8-5e10-a73e-52f75a74dce2/9aa33f8e-4e7e-53e6-843c-370732e42960
503 hbosig a4c770bb-eeab-5236-bad0-c4e3bdcfb67c/b7622186-b110-58be-922f-a42a2dafe29e
506 hbocom 300dbdc3-db0a-513c-8b25-2341eb00c469/0e95ada4-129a-5759-9d8a-d04ac349223b
509 hbozone 5c541620-277c-53fc-9197-763e16d93e4d/aca066fb-98bb-576b-b86a-3d4afed7fb8e
835 showmhd KAQmQyFLRes?onboard=1
836 shofmhd JZjBftgl8WY?onboard=1
837 sho2hd igHq_WgPO8A?utm?onboard=1
838 shonext WkNYP-Sa8qQ?onboard=1
842 stzhd -Y5vv28gO_I?onboard=1
843 stzedge 0aFRvqZJMw8?onboard=1
844 stzhdw Dpm6GnzDtdI?onboard=1
845 stzblk XT6u3OnJWgs?onboard=1
846 stzkds&fam O7ROqxJ8g5I?onboard=1
847 stzcomdedy qsx6OIn4b8M?onboard=1
848 stzcinema Rjr3Yp9kSWc?onboard=1
852 univkids Atjp6gLhvmo?onboard=1

Sample of "masterppv.m3u" :

 #EXTM3U
#EXTINF:-1 channel-id="501" tvc-guide-stationid="" tvg-group="" tvg-logo="",HBO
http://{{ .IPADDRESS }}:7654/play/tuner/501
#EXTINF:-1 channel-id="502" tvc-guide-stationid="" tvg-group="" tvg-logo="",HBO2
http://{{ .IPADDRESS }}:7654/play/tuner/502
#EXTINF:-1 channel-id="503" tvc-guide-stationid="" tvg-group="" tvg-logo="",HBOSIG
http://{{ .IPADDRESS }}:7654/play/tuner/503
#EXTINF:-1 channel-id="506" tvc-guide-stationid="" tvg-group="" tvg-logo="",HBOCOM
http://{{ .IPADDRESS }}:7654/play/tuner/506
#EXTINF:-1 channel-id="509" tvc-guide-stationid="" tvg-group="" tvg-logo="",HBOZONE
http://{{ .IPADDRESS }}:7654/play/tuner/509
#EXTINF:-1 channel-id="206" tvc-guide-stationid="67237" tvg-group="" tvg-logo="",SZENHP
http://{{ .IPADDRESS }}:7654/play/tuner/206
#EXTINF:-1 channel-id="800" tvc-guide-stationid="36225" tvg-group="" tvg-logo="",STZENHD
http://{{ .IPADDRESS }}:7654/play/tuner/800
#EXTINF:-1 channel-id="801" tvc-guide-stationid="83404" tvg-group="" tvg-logo="",SZECLHD
http://{{ .IPADDRESS }}:7654/play/tuner/801
#EXTINF:-1 channel-id="830" tvc-guide-stationid="21868" tvg-group="" tvg-logo="",SHOHD
http://{{ .IPADDRESS }}:7654/play/tuner/830
#EXTINF:-1 channel-id="831" tvc-guide-stationid="22532" tvg-group="" tvg-logo="",SHOHDP
http://{{ .IPADDRESS }}:7654/play/tuner/831
#EXTINF:-1 channel-id="832" tvc-guide-stationid="68340" tvg-group="" tvg-logo="",SHOxBET
http://{{ .IPADDRESS }}:7654/play/tuner/832
#EXTINF:-1 channel-id="833" tvc-guide-stationid="60947" tvg-group="" tvg-logo="",SHOXHD
http://{{ .IPADDRESS }}:7654/play/tuner/833
#EXTINF:-1 channel-id="834" tvc-guide-stationid="61001" tvg-group="" tvg-logo="",SHOCSHD
http://{{ .IPADDRESS }}:7654/play/tuner/834
#EXTINF:-1 channel-id="835" tvc-guide-stationid="68338" tvg-group="" tvg-logo="",SHOWMHD
http://{{ .IPADDRESS }}:7654/play/tuner/835

"bmitune.sh" with edits to make it work with master list as it stands. :

#!/bin/bash

echo "$1"  > /tmp/temp.txt
echo "$2" >> /tmp/temp.txt
echo "$3" >> /tmp/temp.txt

STATION="$1"
TUNERIP="$2"
CONTENT_FILE="contentid.txt"
CONTENT_ID=""
URL=""
PROVIDER=""
STATUS="notplaying"
ADBSTATUS=""
PID=""
RESULT=""
EXE=""
ISPKG=""
WHICH_PROVIDER=""
APP_NAME="com.google.android.apps.youtube.tvunplugged.activity.MainActivity"
APP_LAUNCH="com.google.android.youtube.tvunplugged"

content_file="masterppv_contentid.txt"
content_id=""

#Make Sure adb is up and connected
#sh /home/moisebuntu/Scripts/startadb.sh

if (( 500 <= $1 && $1 <= 509 ));then
        echo "Yes"
    else
        echo "No"
    fi

#Read content_id from file
if [ -f "$content_file" ]; then
  content_id=$(grep -w "^$1" "$content_file" | cut -d " " -f3)
fi

#Check if content_id is empty
if [ -z "$content_id" ]; then
  echo "Invalid option or content_id not found in $content_file"
  exit 1
fi

if (( 500 <= $1 && $1 <= 509 ));then
        adb -s $2 shell "am start -a android.intent.action.VIEW -d https://play.max.com/channel/watch/"$content_id""
        adb -s $2 shell "input keyevent 22; input keyevent 66"
    else
        adb -s $TUNERIP shell "am start -a android.intent.action.VIEW -d  https://tv.youtube.com/watch/"$content_id"" -n $APP_LAUNCH/$APP_NAME
    fi

So if the channels is in the 500 range and thus HBO according to the guide data I am using then the script triggers the HBO Max app. If it is anything above that then it will trigger YouTube tv.

I was wondering though if it would be better to add a column for provider (youtubetv, sling, Hulu, hbomax etc) in the contentid.txt file and then have the script check the number selected when tuning against that data field and launching the relevant app based on this. A line from the contentid.txt would in that case look like this:

836 shofmhd youtubetv JZjBftgl8WY?onboard=1

And that third block would trigger the relevant app via the appropriate adb command.

Anyway, any help with making this better will be appreciated.

Rather than having an additional data file to maintain, I'd suggest having the values you need passed to the script embedded in the M3U's URL. I'm already doing this in a couple of cases where an additional value is needed for tuning. The idea is to use a separator character that's very unlikely to be part of a channel's unique identifier -- to date, I've been using the tilde (~). I'd suggest an M3U that looks like this in your case:

#EXTM3U

#EXTINF:-1 channel-id="501" tvc-guide-stationid="" tvg-group="" tvg-logo="",HBO
http://{{ .IPADDRESS }}/play/tuner/hbomax~a903ca8a-6d5e-559b-a027-f82997397694/452e5d78-1cca-59a9-8508-21b25d813874

#EXTINF:-1 channel-id="835" tvc-guide-stationid="68338" tvg-group="" tvg-logo="",SHOWMHD
http://{{ .IPADDRESS }}/play/tuner/youtubetv~KAQmQyFLRes

Note that I'm also suggesting you remove the hardcoded port after $IPADDRESS, and instead include the port in the $IPADDRESS value.

In bmitune.sh, you can parse these values similar to this:

contentID=$(echo $1 | awk -F~ '{print $2}')
appName=$(echo $1 | awk -F~ '{print $1}')
streamerIP="$2"
adbTarget="adb -s $streamerIP"

Then if you're using Bash functions, you could have a tuning function for each appName, like:

hbomaxTuneChannel() {
  packageName=play.max.com
  packageAction=android.intent.action.VIEW
  $adbTarget shell am start -a $packageAction -d https://"$packageName"/channel/watch/"$contentID"
  $adbTarget shell "input keyevent KEYCODE_DPAD_RIGHT; input keyevent KEYCODE_ENTER"
}

youtubetvTuneChannel() {
  packageName=tv.youtube.com
  packageAction=android.intent.action.VIEW 
  packageLaunch=com.google.android.youtube.tvunplugged
  packageTarget=com.google.android.apps.youtube.tvunplugged.activity.MainActivity
  $adbTarget shell am start -a $packageAction -d https://"$packageName"/watch/"$contentID" -n $packageLaunch/$packageTarget

main() {
  eval "${appName}TuneChannel"
}

main

Having the M3U be the one and only data source I think is advantageous, especially given the M3U editor that's part ah4c. Also, by writing everything in function form, whatever is specific to tuning for a particular app can be included in its function. This keeps the script very readable, even if it grew to include many apps.

1 Like

@spammedeeper
@kprice

How do you enable adb on osprey boxes?

Never mind - found it

Any way to tune using deep links with osprey box? I have the resource ID and callsign. NESN and NESN PLUS channels are identical channel numbers.

No way tune with deep links I have found for DirecTV channels.

Review posts 312-334 of this thread. They demonstrate how it was handled when the Olympics were using the sub-channels of the USA channel.
It might give you some ideas on how to accomplish your task.

@bnhf

Haven’t given up on the "Keep Watching" screen on dtvstream on Firestick yet but am moving that to my test NAS after I get OliveTin installed there.

I did pick up an Osprey device and installed that on my main server. I edited the m3u to add an additional channel that I wanted. Plan to fully edit the m3u adding all of my desired channels then lock it down.

Everything is working as expected. Tuning takes about 11-12 secs and it plays forever (9+hrs).

1 Like

Anybody using the USA Network android app? I am trying to figure out the commands to automatically get to live tv channels.

I am able to access its live tv using my current slingtv credentials. It appears to have much better audio than sling tv and better frame rates when watching SYFY and USA through it. Should be a better option for live sports on USA network than Sling.

You'll have to check the manifest file inside the apk for that.

Got my new 5 port LinkPi today (Just trying to swap out my single port URay). As expected, the interfaces are different and confusing. Stopped my stack and edited the environments. Stack deploys but I get the 404 error. Tried hunting and pecking without luck. Reset encoder back to factory specs.

Below are portainer log and environment variables after reset.

I'm going to be out for several hours but any advice to get back up and running would be appreciative.

Portainer log

2025-06-05T15:29:17.470050328Z 127.0.0.1	localhost
2025-06-05T15:29:17.470690285Z ::1	localhost ip6-localhost ip6-loopback
2025-06-05T15:29:17.470736259Z fe00::0	ip6-localnet
2025-06-05T15:29:17.470764133Z ff00::0	ip6-mcastprefix
2025-06-05T15:29:17.470792714Z ff02::1	ip6-allnodes
2025-06-05T15:29:17.470819386Z ff02::2	ip6-allrouters
2025-06-05T15:29:17.470852892Z 172.21.0.2	ah4c
2025-06-05T15:29:17.755162981Z * daemon not running; starting now at tcp:5037
2025-06-05T15:29:17.764687391Z * daemon started successfully
2025-06-05T15:29:17.764722510Z List of devices attached
2025-06-05T15:29:17.765216963Z 
2025-06-05T15:29:17.796768521Z connected to 10.0.1.76:5555
2025-06-05T15:29:17.824372348Z connected to 10.0.1.29:5555
2025-06-05T15:29:17.828059393Z No existing ./scripts/firetv/directv/prebmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T15:29:17.829967251Z No existing ./scripts/osprey/directv/prebmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T15:29:17.831168320Z No existing ./scripts/firetv/directv/bmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T15:29:17.832494124Z No existing ./scripts/osprey/directv/bmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T15:29:17.833851128Z No existing ./scripts/firetv/directv/stopbmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T15:29:17.835021663Z No existing ./scripts/osprey/directv/stopbmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T15:29:17.841671686Z Existing directv.m3u found, and will be preserved
2025-06-05T15:29:17.841794763Z Existing dtvdeeplinks.m3u found, and will be preserved
2025-06-05T15:29:17.841851484Z Existing dtvosprey.m3u found, and will be preserved
2025-06-05T15:29:17.841890637Z Existing dtvstream.m3u found, and will be preserved
2025-06-05T15:29:17.841966203Z Existing dtvstreamdeeplinks.m3u found, and will be preserved
2025-06-05T15:29:17.842003659Z Existing foo-fighters.m3u found, and will be preserved
2025-06-05T15:29:17.842032266Z Existing fubo.m3u found, and will be preserved
2025-06-05T15:29:17.842059274Z Existing hulu.m3u found, and will be preserved
2025-06-05T15:29:17.842125449Z Existing livetv.m3u found, and will be preserved
2025-06-05T15:29:17.842177156Z Existing nbc.m3u found, and will be preserved
2025-06-05T15:29:17.842205408Z Existing npo.m3u found, and will be preserved
2025-06-05T15:29:17.842231726Z Existing pbs-seatac.m3u found, and will be preserved
2025-06-05T15:29:17.842297710Z Existing pbs-worcester.m3u found, and will be preserved
2025-06-05T15:29:17.842329679Z Existing silicondust.m3u found, and will be preserved
2025-06-05T15:29:17.842359335Z Existing sling.m3u found, and will be preserved
2025-06-05T15:29:17.842384715Z Existing spectrum.m3u found, and will be preserved
2025-06-05T15:29:17.842449468Z Existing xfinity.m3u found, and will be preserved
2025-06-05T15:29:17.842480350Z Existing youtubetv_shield.m3u found, and will be preserved
2025-06-05T15:29:17.842511145Z Existing youtubetv.m3u found, and will be preserved
2025-06-05T15:29:18.002487239Z [START] ah4c is starting
2025-06-05T15:29:18.002710734Z [ENV] Not loading env
2025-06-05T15:29:18.002755505Z [ENV] IPADDRESS                  10.0.1.65:7654
2025-06-05T15:29:18.002800759Z [ENV] ALERT_SMTP_SERVER          
2025-06-05T15:29:18.002843781Z [ENV] ALERT_AUTH_SERVER          
2025-06-05T15:29:18.002869147Z [ENV] ALERT_EMAIL_FROM           
2025-06-05T15:29:18.002948146Z [ENV] ALERT_EMAIL_PASS           
2025-06-05T15:29:18.003083233Z [ENV] ALERT_EMAIL_TO             
2025-06-05T15:29:18.003110445Z [ENV] ALERT_WEBHOOK_URL          
2025-06-05T15:29:18.003134783Z [ENV] ALLOW_DEBUG_VIDEO_PREVIEW  
2025-06-05T15:29:18.003160638Z [ENV] Creating tuner             1
2025-06-05T15:29:18.003193264Z [ENV] ENCODER1_URL               http://10.0.1.34/stream0.ts
2025-06-05T15:29:18.003223325Z [ENV] TUNER1_IP                  10.0.1.76:5555
2025-06-05T15:29:18.003250240Z [ENV] CMD1                       
2025-06-05T15:29:18.003275023Z [ENV] TEECMD1                    
2025-06-05T15:29:18.003307532Z [ENV] PRE SCRIPT                 ./scripts/osprey/directv/prebmitune.sh
2025-06-05T15:29:18.003337363Z [ENV] START SCRIPT               ./scripts/osprey/directv/bmitune.sh
2025-06-05T15:29:18.003362730Z [ENV] STOP SCRIPT                ./scripts/osprey/directv/stopbmitune.sh
2025-06-05T15:29:18.003389385Z [ENV] REBOOT SCRIPT              ./scripts/osprey/directv/reboot.sh
2025-06-05T15:29:18.003421541Z [ENV] Creating tuner             2
2025-06-05T15:29:18.003505251Z [ENV] ENCODER2_URL               http://10.0.1.34/stream1.ts
2025-06-05T15:29:18.003535152Z [ENV] TUNER2_IP                  10.0.1.29:5555
2025-06-05T15:29:18.003563886Z [ENV] CMD2                       
2025-06-05T15:29:18.003587905Z [ENV] TEECMD2                    
2025-06-05T15:29:18.003614001Z [ENV] PRE SCRIPT                 ./scripts/osprey/directv/prebmitune.sh
2025-06-05T15:29:18.003640376Z [ENV] START SCRIPT               ./scripts/osprey/directv/bmitune.sh
2025-06-05T15:29:18.003666347Z [ENV] STOP SCRIPT                ./scripts/osprey/directv/stopbmitune.sh
2025-06-05T15:29:18.003696511Z [ENV] REBOOT SCRIPT              ./scripts/osprey/directv/reboot.sh
2025-06-05T15:29:18.003723676Z [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
2025-06-05T15:29:18.003760034Z  - using env:	export GIN_MODE=release
2025-06-05T15:29:18.003791239Z  - using code:	gin.SetMode(gin.ReleaseMode)
2025-06-05T15:29:18.003819119Z 
2025-06-05T15:29:18.003857388Z [GIN-debug] GET    /favicon.ico              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
2025-06-05T15:29:18.003910535Z [GIN-debug] HEAD   /favicon.ico              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
2025-06-05T15:29:18.009239024Z [GIN-debug] Loaded HTML Templates (11): 
2025-06-05T15:29:18.009352910Z 	- status_and_logs.html
2025-06-05T15:29:18.009390300Z 	- 
2025-06-05T15:29:18.009414443Z 	- edit.html
2025-06-05T15:29:18.009439910Z 	- routes.html
2025-06-05T15:29:18.009466341Z 	- logs.html
2025-06-05T15:29:18.009491742Z 	- m3us.html
2025-06-05T15:29:18.009515610Z 	- status.html
2025-06-05T15:29:18.009542426Z 	- stream.html
2025-06-05T15:29:18.009571820Z 	- config.html
2025-06-05T15:29:18.009596601Z 	- editm3u.html
2025-06-05T15:29:18.009621049Z 	- index.html
2025-06-05T15:29:18.009649566Z 
2025-06-05T15:29:18.009671234Z [GIN-debug] GET    /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
2025-06-05T15:29:18.009777858Z [GIN-debug] HEAD   /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
2025-06-05T15:29:18.009832681Z [GIN-debug] GET    /                         --> main.run.func1 (2 handlers)
2025-06-05T15:29:18.009868066Z [GIN-debug] GET    /routes                   --> main.run.func2 (2 handlers)
2025-06-05T15:29:18.009904294Z [GIN-debug] GET    /play/tuner:tuner/:channel --> main.run.func3 (2 handlers)
2025-06-05T15:29:18.009951974Z [GIN-debug] GET    /m3u/:channel             --> main.run.func4 (2 handlers)
2025-06-05T15:29:18.009984570Z [GIN-debug] GET    /env                      --> main.run.func5 (2 handlers)
2025-06-05T15:29:18.010015150Z [GIN-debug] GET    /logs/text                --> main.run.func6 (2 handlers)
2025-06-05T15:29:18.010045250Z [GIN-debug] GET    /logs                     --> main.run.func7 (2 handlers)
2025-06-05T15:29:18.010076930Z [GIN-debug] GET    /status/andlogs           --> main.run.func8 (2 handlers)
2025-06-05T15:29:18.010106509Z [GIN-debug] GET    /logs/json                --> main.run.func9 (2 handlers)
2025-06-05T15:29:18.010134739Z [GIN-debug] GET    /video                    --> main.run.func10 (2 handlers)
2025-06-05T15:29:18.010164736Z [GIN-debug] GET    /status                   --> main.statusPageHandler (2 handlers)
2025-06-05T15:29:18.010193361Z [GIN-debug] GET    /api/status               --> main.apiStatusHandler (2 handlers)
2025-06-05T15:29:18.010223393Z [GIN-debug] GET    /stream                   --> main.run.func11 (2 handlers)
2025-06-05T15:29:18.010250873Z [GIN-debug] GET    /test/webhook             --> main.run.func12 (2 handlers)
2025-06-05T15:29:18.010279554Z [GIN-debug] GET    /test/email               --> main.run.func13 (2 handlers)
2025-06-05T15:29:18.010308143Z [GIN-debug] GET    /status/channelsactivity  --> main.run.func14 (2 handlers)
2025-06-05T15:29:18.010348626Z [GIN-debug] GET    /edit                     --> main.run.func15 (2 handlers)
2025-06-05T15:29:18.010378284Z [GIN-debug] POST   /save                     --> main.run.func16 (2 handlers)
2025-06-05T15:29:18.010406121Z [GIN-debug] POST   /m3usave/:file            --> main.run.func17 (2 handlers)
2025-06-05T15:29:18.010434513Z [GIN-debug] GET    /m3us                     --> main.run.func18 (2 handlers)
2025-06-05T15:29:18.010460789Z [GIN-debug] GET    /editm3u/:file            --> main.run.func19 (2 handlers)
2025-06-05T15:29:18.010488946Z [GIN-debug] GET    /config                   --> main.run.func20 (2 handlers)
2025-06-05T15:29:18.010516758Z [GIN-debug] POST   /configsave               --> main.run.func21 (2 handlers)
2025-06-05T15:29:18.010543962Z [START] ah4c is ready
2025-06-05T15:29:18.010569595Z [GIN-debug] Listening and serving HTTP on :7654
2025-06-05T15:29:18.990573015Z 
2025-06-05T15:29:18.990693510Z > [email protected] start
2025-06-05T15:29:18.990737473Z > node ./index.js
2025-06-05T15:29:18.990766426Z 
2025-06-05T15:29:19.891122451Z Listening on:
2025-06-05T15:29:19.891727987Z 	http://ah4c:8000 http://localhost:8000
2025-06-05T15:29:19.891785592Z 	http://127.0.0.1:8000 http://172.21.0.2:8000
2025-06-05T15:30:19.730930971Z Attempting network tune for device http://10.0.1.34/stream0.ts 10.0.1.76:5555 273 
2025-06-05T15:30:19.733128985Z [ERR] Failed to fetch source: 404 Not Found
2025-06-05T15:30:19.733204298Z Attempting network tune for device http://10.0.1.34/stream1.ts 10.0.1.29:5555 273 
2025-06-05T15:30:19.735494061Z [ERR] Failed to fetch source: 404 Not Found
2025-06-05T15:30:19.735565185Z [ERR] Failed to tune device(s) not available
2025-06-05T15:30:19.735629363Z [GIN-debug] Request: 172.21.0.1 GET /play/tuner/273, latency: 4.729306ms, status: 500

Environment Variables

TAG=latest
DOMAIN=local
ADBS_PORT=5037
HOST_PORT=7654
WSCR_PORT=7655
IPADDRESS=10.0.1.65:7654
NUMBER_TUNERS=2
TUNER1_IP=10.0.1.76:5555
ENCODER1_URL=http://10.0.1.34/stream0.ts
TUNER2_IP=10.0.1.29:5555
ENCODER2_URL=http://10.0.1.34/stream1.ts
TUNER3_IP=
ENCODER3_URL=
TUNER4_IP=
ENCODER4_URL=
TUNER5_IP=
ENCODER5_URL=
STREAMER_APP=scripts/osprey/directv
CHANNELSIP=10.0.1.65:7654
ALERT_SMTP_SERVER=
ALERT_AUTH_SERVER=
ALERT_EMAIL_FROM=
ALERT_EMAIL_PASS=
ALERT_EMAIL_TO=
UPDATE_SCRIPTS=true
UPDATE_M3US=false
TZ=US/CENTRAL
SPEED_MODE=false
KEEP_WATCHING=4h
HOST_DIR=/volume1/data
1 Like

The LinkPi Encoder URL should look like this (the way you're trying to do it uses a redirect -- which will fail):

http://10.0.1.34:8090/stream0

This should be just the IP address (or resolvable hostname) of your Channels DVR server. Like:

CHANNELSIP=10.0.1.65

Will do when I get back later today.

@bnhf

Made those changes and then was getting a 503 error. But I did get it working like this.

On the LinkPi interface, I changed the overall config on the Stream page to http and saved. Changed the encoder url by coping the url from the LP interface.

There's probably a lot of settings that I need to tweak to perfect it. There sure are a lot of settings!!!!
The encoder is the "WayPonDev Link Pi Enc5-V2 5 Port NDI HDM........"

Any other things I can provide you to optimize before I add the 3rd tuner?

Environment Variables:

DOMAIN=local
ADBS_PORT=5037
HOST_PORT=7654
WSCR_PORT=7655
IPADDRESS=10.0.1.65:7654
NUMBER_TUNERS=2
TUNER1_IP=10.0.1.76:5555
ENCODER1_URL=http://10.0.1.34/live/stream0
TUNER2_IP=10.0.1.29:5555
ENCODER2_URL=http://10.0.1.34/live/stream1
TUNER3_IP=
ENCODER3_URL=
TUNER4_IP=
ENCODER4_URL=
TUNER5_IP=
ENCODER5_URL=
STREAMER_APP=scripts/osprey/directv
CHANNELSIP=10.0.1.65
ALERT_SMTP_SERVER=
ALERT_AUTH_SERVER=
ALERT_EMAIL_FROM=
ALERT_EMAIL_PASS=
ALERT_EMAIL_TO=
UPDATE_SCRIPTS=true
UPDATE_M3US=false
TZ=US/CENTRAL
SPEED_MODE=false
KEEP_WATCHING=4h
HOST_DIR=/volume1/data

Portainer Log:

2025-06-05T22:23:07.582577484Z 127.0.0.1	localhost
2025-06-05T22:23:07.583069110Z ::1	localhost ip6-localhost ip6-loopback
2025-06-05T22:23:07.583105418Z fe00::0	ip6-localnet
2025-06-05T22:23:07.583133896Z ff00::0	ip6-mcastprefix
2025-06-05T22:23:07.583162062Z ff02::1	ip6-allnodes
2025-06-05T22:23:07.583188147Z ff02::2	ip6-allrouters
2025-06-05T22:23:07.583215597Z 172.23.0.2	ah4c
2025-06-05T22:23:07.844437979Z * daemon not running; starting now at tcp:5037
2025-06-05T22:23:07.852961163Z List of devices attached
2025-06-05T22:23:07.853172183Z 
2025-06-05T22:23:07.853241948Z * daemon started successfully
2025-06-05T22:23:07.883913861Z connected to 10.0.1.76:5555
2025-06-05T22:23:07.913572029Z connected to 10.0.1.29:5555
2025-06-05T22:23:07.917453795Z No existing ./scripts/firetv/directv/prebmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T22:23:07.918953359Z No existing ./scripts/osprey/directv/prebmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T22:23:07.920808959Z No existing ./scripts/firetv/directv/bmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T22:23:07.922364765Z No existing ./scripts/osprey/directv/bmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T22:23:07.923694076Z No existing ./scripts/firetv/directv/stopbmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T22:23:07.924923273Z No existing ./scripts/osprey/directv/stopbmitune.sh found or UPDATE_SCRIPTS set to true
2025-06-05T22:23:07.931191254Z Existing directv.m3u found, and will be preserved
2025-06-05T22:23:07.931377927Z Existing dtvdeeplinks.m3u found, and will be preserved
2025-06-05T22:23:07.931429442Z Existing dtvosprey.m3u found, and will be preserved
2025-06-05T22:23:07.931499249Z Existing dtvstream.m3u found, and will be preserved
2025-06-05T22:23:07.931534100Z Existing dtvstreamdeeplinks.m3u found, and will be preserved
2025-06-05T22:23:07.931600082Z Existing foo-fighters.m3u found, and will be preserved
2025-06-05T22:23:07.931632864Z Existing fubo.m3u found, and will be preserved
2025-06-05T22:23:07.931699942Z Existing hulu.m3u found, and will be preserved
2025-06-05T22:23:07.931731801Z Existing livetv.m3u found, and will be preserved
2025-06-05T22:23:07.931776190Z Existing nbc.m3u found, and will be preserved
2025-06-05T22:23:07.931846171Z Existing npo.m3u found, and will be preserved
2025-06-05T22:23:07.931878176Z Existing pbs-seatac.m3u found, and will be preserved
2025-06-05T22:23:07.931933105Z Existing pbs-worcester.m3u found, and will be preserved
2025-06-05T22:23:07.931972478Z Existing silicondust.m3u found, and will be preserved
2025-06-05T22:23:07.932027346Z Existing sling.m3u found, and will be preserved
2025-06-05T22:23:07.932054746Z Existing spectrum.m3u found, and will be preserved
2025-06-05T22:23:07.932107509Z Existing xfinity.m3u found, and will be preserved
2025-06-05T22:23:07.932136754Z Existing youtubetv_shield.m3u found, and will be preserved
2025-06-05T22:23:07.932165797Z Existing youtubetv.m3u found, and will be preserved
2025-06-05T22:23:08.051571486Z [START] ah4c is starting
2025-06-05T22:23:08.051773034Z [ENV] Not loading env
2025-06-05T22:23:08.051818307Z [ENV] IPADDRESS                  10.0.1.65:7654
2025-06-05T22:23:08.051925311Z [ENV] ALERT_SMTP_SERVER          
2025-06-05T22:23:08.051957600Z [ENV] ALERT_AUTH_SERVER          
2025-06-05T22:23:08.051986268Z [ENV] ALERT_EMAIL_FROM           
2025-06-05T22:23:08.052015356Z [ENV] ALERT_EMAIL_PASS           
2025-06-05T22:23:08.052085980Z [ENV] ALERT_EMAIL_TO             
2025-06-05T22:23:08.052111960Z [ENV] ALERT_WEBHOOK_URL          
2025-06-05T22:23:08.052136502Z [ENV] ALLOW_DEBUG_VIDEO_PREVIEW  
2025-06-05T22:23:08.052161208Z [ENV] Creating tuner             1
2025-06-05T22:23:08.052190113Z [ENV] ENCODER1_URL               http://10.0.1.34/live/stream0
2025-06-05T22:23:08.052219983Z [ENV] TUNER1_IP                  10.0.1.76:5555
2025-06-05T22:23:08.052245705Z [ENV] CMD1                       
2025-06-05T22:23:08.052269695Z [ENV] TEECMD1                    
2025-06-05T22:23:08.052295482Z [ENV] PRE SCRIPT                 ./scripts/osprey/directv/prebmitune.sh
2025-06-05T22:23:08.052324559Z [ENV] START SCRIPT               ./scripts/osprey/directv/bmitune.sh
2025-06-05T22:23:08.052349157Z [ENV] STOP SCRIPT                ./scripts/osprey/directv/stopbmitune.sh
2025-06-05T22:23:08.052374980Z [ENV] REBOOT SCRIPT              ./scripts/osprey/directv/reboot.sh
2025-06-05T22:23:08.052417103Z [ENV] Creating tuner             2
2025-06-05T22:23:08.052443797Z [ENV] ENCODER2_URL               http://10.0.1.34/live/stream1
2025-06-05T22:23:08.052469601Z [ENV] TUNER2_IP                  10.0.1.29:5555
2025-06-05T22:23:08.052493265Z [ENV] CMD2                       
2025-06-05T22:23:08.052517256Z [ENV] TEECMD2                    
2025-06-05T22:23:08.052539458Z [ENV] PRE SCRIPT                 ./scripts/osprey/directv/prebmitune.sh
2025-06-05T22:23:08.052563804Z [ENV] START SCRIPT               ./scripts/osprey/directv/bmitune.sh
2025-06-05T22:23:08.052588093Z [ENV] STOP SCRIPT                ./scripts/osprey/directv/stopbmitune.sh
2025-06-05T22:23:08.052614947Z [ENV] REBOOT SCRIPT              ./scripts/osprey/directv/reboot.sh
2025-06-05T22:23:08.052639050Z [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
2025-06-05T22:23:08.052672029Z  - using env:	export GIN_MODE=release
2025-06-05T22:23:08.052703046Z  - using code:	gin.SetMode(gin.ReleaseMode)
2025-06-05T22:23:08.052760509Z 
2025-06-05T22:23:08.052783904Z [GIN-debug] GET    /favicon.ico              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
2025-06-05T22:23:08.052847998Z [GIN-debug] HEAD   /favicon.ico              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
2025-06-05T22:23:08.072264264Z [GIN-debug] Loaded HTML Templates (11): 
2025-06-05T22:23:08.072399362Z 	- config.html
2025-06-05T22:23:08.072431068Z 	- editm3u.html
2025-06-05T22:23:08.072458513Z 	- status_and_logs.html
2025-06-05T22:23:08.072488525Z 	- logs.html
2025-06-05T22:23:08.072518950Z 	- m3us.html
2025-06-05T22:23:08.072545464Z 	- routes.html
2025-06-05T22:23:08.072571155Z 	- status.html
2025-06-05T22:23:08.072595110Z 	- stream.html
2025-06-05T22:23:08.072618491Z 	- 
2025-06-05T22:23:08.072639358Z 	- edit.html
2025-06-05T22:23:08.072662669Z 	- index.html
2025-06-05T22:23:08.072689411Z 
2025-06-05T22:23:08.072711428Z [GIN-debug] GET    /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
2025-06-05T22:23:08.072747655Z [GIN-debug] HEAD   /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
2025-06-05T22:23:08.072778800Z [GIN-debug] GET    /                         --> main.run.func1 (2 handlers)
2025-06-05T22:23:08.072807065Z [GIN-debug] GET    /routes                   --> main.run.func2 (2 handlers)
2025-06-05T22:23:08.072849330Z [GIN-debug] GET    /play/tuner:tuner/:channel --> main.run.func3 (2 handlers)
2025-06-05T22:23:08.072896953Z [GIN-debug] GET    /m3u/:channel             --> main.run.func4 (2 handlers)
2025-06-05T22:23:08.072923266Z [GIN-debug] GET    /env                      --> main.run.func5 (2 handlers)
2025-06-05T22:23:08.072949888Z [GIN-debug] GET    /logs/text                --> main.run.func6 (2 handlers)
2025-06-05T22:23:08.072976581Z [GIN-debug] GET    /logs                     --> main.run.func7 (2 handlers)
2025-06-05T22:23:08.073004847Z [GIN-debug] GET    /status/andlogs           --> main.run.func8 (2 handlers)
2025-06-05T22:23:08.073030889Z [GIN-debug] GET    /logs/json                --> main.run.func9 (2 handlers)
2025-06-05T22:23:08.073057022Z [GIN-debug] GET    /video                    --> main.run.func10 (2 handlers)
2025-06-05T22:23:08.073085400Z [GIN-debug] GET    /status                   --> main.statusPageHandler (2 handlers)
2025-06-05T22:23:08.073111800Z [GIN-debug] GET    /api/status               --> main.apiStatusHandler (2 handlers)
2025-06-05T22:23:08.073209136Z [GIN-debug] GET    /stream                   --> main.run.func11 (2 handlers)
2025-06-05T22:23:08.073248041Z [GIN-debug] GET    /test/webhook             --> main.run.func12 (2 handlers)
2025-06-05T22:23:08.073276059Z [GIN-debug] GET    /test/email               --> main.run.func13 (2 handlers)
2025-06-05T22:23:08.073306069Z [GIN-debug] GET    /status/channelsactivity  --> main.run.func14 (2 handlers)
2025-06-05T22:23:08.073338266Z [GIN-debug] GET    /edit                     --> main.run.func15 (2 handlers)
2025-06-05T22:23:08.073368462Z [GIN-debug] POST   /save                     --> main.run.func16 (2 handlers)
2025-06-05T22:23:08.073395604Z [GIN-debug] POST   /m3usave/:file            --> main.run.func17 (2 handlers)
2025-06-05T22:23:08.073422586Z [GIN-debug] GET    /m3us                     --> main.run.func18 (2 handlers)
2025-06-05T22:23:08.073448525Z [GIN-debug] GET    /editm3u/:file            --> main.run.func19 (2 handlers)
2025-06-05T22:23:08.073476185Z [GIN-debug] GET    /config                   --> main.run.func20 (2 handlers)
2025-06-05T22:23:08.073504281Z [GIN-debug] POST   /configsave               --> main.run.func21 (2 handlers)
2025-06-05T22:23:08.073531248Z [START] ah4c is ready
2025-06-05T22:23:08.073556197Z [GIN-debug] Listening and serving HTTP on :7654
2025-06-05T22:23:09.155337763Z 
2025-06-05T22:23:09.155721412Z > [email protected] start
2025-06-05T22:23:09.155769337Z > node ./index.js
2025-06-05T22:23:09.155804256Z 
2025-06-05T22:23:09.981665336Z Listening on:
2025-06-05T22:23:09.981794450Z 	http://ah4c:8000 http://localhost:8000
2025-06-05T22:23:09.981940696Z 	http://127.0.0.1:8000 http://172.23.0.2:8000
2025-06-05T22:23:49.867040976Z Attempting network tune for device http://10.0.1.34/live/stream0 10.0.1.76:5555 273 
2025-06-05T22:23:49.871916146Z [EXECUTE] Running [./scripts/osprey/directv/prebmitune.sh 10.0.1.76:5555 273]
2025-06-05T22:23:55.101232591Z [EXECUTE] Stdout: 'already connected to 10.0.1.76:5555
2025-06-05T22:23:55.103916120Z Waking 10.0.1.76:5555
2025-06-05T22:23:55.104200394Z prebmitune.sh is exiting for 10.0.1.76:5555 with exit code 0
2025-06-05T22:23:55.104280139Z '
2025-06-05T22:23:55.104320200Z [EXECUTE] Stderr: '+ streamerIP=10.0.1.76:5555
2025-06-05T22:23:55.104358139Z + streamerNoPort=10.0.1.76
2025-06-05T22:23:55.104503244Z + adbTarget='adb -s 10.0.1.76:5555'
2025-06-05T22:23:55.104535321Z + mkdir -p 10.0.1.76
2025-06-05T22:23:55.104576462Z + trap finish EXIT
2025-06-05T22:23:55.104605286Z + main
2025-06-05T22:23:55.104629668Z + adbConnect
2025-06-05T22:23:55.104662167Z + adb connect 10.0.1.76:5555
2025-06-05T22:23:55.104687561Z + local -i adbMaxRetries=3
2025-06-05T22:23:55.104797644Z + local -i adbCounter=0
2025-06-05T22:23:55.104922505Z + true
2025-06-05T22:23:55.104950896Z + adb -s 10.0.1.76:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:23:55.104996023Z + local adbEventSuccess=0
2025-06-05T22:23:55.105022270Z + [[ 0 -eq 0 ]]
2025-06-05T22:23:55.105053582Z + break
2025-06-05T22:23:55.105078275Z + adbWake
2025-06-05T22:23:55.105101975Z + adb -s 10.0.1.76:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:23:55.105134732Z + sleep 2
2025-06-05T22:23:55.105160165Z + echo 'Waking 10.0.1.76:5555'
2025-06-05T22:23:55.105185738Z + touch 10.0.1.76/adbAppRunning
2025-06-05T22:23:55.105221640Z + finish
2025-06-05T22:23:55.105244592Z + echo 'prebmitune.sh is exiting for 10.0.1.76:5555 with exit code 0'
2025-06-05T22:23:55.105279615Z '
2025-06-05T22:23:55.105302449Z [EXECUTE] Finished running ./scripts/osprey/directv/prebmitune.sh in 5.229371464s
2025-06-05T22:23:55.105351138Z [EXECUTE] Running [./scripts/osprey/directv/bmitune.sh 273 10.0.1.76:5555]
2025-06-05T22:23:56.684450221Z [EXECUTE] Stdout: 'bmitune.sh is exiting for 10.0.1.76:5555 with exit code 0
2025-06-05T22:23:56.684592510Z '
2025-06-05T22:23:56.684622636Z [EXECUTE] Stderr: '+ channelID='"273"'
2025-06-05T22:23:56.684652116Z + specialID=273
2025-06-05T22:23:56.684677915Z + streamerIP=10.0.1.76:5555
2025-06-05T22:23:56.684702868Z + streamerNoPort=10.0.1.76
2025-06-05T22:23:56.684726619Z + adbTarget='adb -s 10.0.1.76:5555'
2025-06-05T22:23:56.684752123Z + m3uName=directv.m3u
2025-06-05T22:23:56.684778250Z + trap finish EXIT
2025-06-05T22:23:56.684802102Z + main
2025-06-05T22:23:56.684833183Z + matchEncoderURL
2025-06-05T22:23:56.684858052Z + case "$streamerIP" in
2025-06-05T22:23:56.684882874Z + encoderURL=http://10.0.1.34/live/stream0
2025-06-05T22:23:56.684919186Z + tuneChannel
2025-06-05T22:23:56.684942260Z + adb -s 10.0.1.76:5555 shell input text '"273"'
2025-06-05T22:23:56.684968093Z + finish
2025-06-05T22:23:56.684990051Z + echo 'bmitune.sh is exiting for 10.0.1.76:5555 with exit code 0'
2025-06-05T22:23:56.685015650Z '
2025-06-05T22:23:56.685124556Z [EXECUTE] Finished running ./scripts/osprey/directv/bmitune.sh in 1.583430117s
2025-06-05T22:24:23.250206143Z Tuner 0 is active - skipping
2025-06-05T22:24:23.250688611Z Attempting network tune for device http://10.0.1.34/live/stream1 10.0.1.29:5555 674 
2025-06-05T22:24:23.255337915Z [EXECUTE] Running [./scripts/osprey/directv/prebmitune.sh 10.0.1.29:5555 674]
2025-06-05T22:24:23.389995872Z [IO] io.Copy: write tcp 172.23.0.2:7654->172.23.0.1:56326: write: broken pipe
2025-06-05T22:24:23.390159370Z [IOINFO] Successfully copied 15801024 bytes
2025-06-05T22:24:23.390236990Z [IOINFO] Transfer speed: 4.468502942877164 Mbits/second
2025-06-05T22:24:23.390286818Z Performing Close() for 10.0.1.76:5555
2025-06-05T22:24:23.390318661Z [EXECUTE] Running [./scripts/osprey/directv/stopbmitune.sh 10.0.1.76:5555 273]
2025-06-05T22:24:24.566099210Z [EXECUTE] Stdout: 'Sleep initiated for 10.0.1.76:5555
2025-06-05T22:24:24.566239347Z 10.0.1.76/stream_stopped written with epoch stop time
2025-06-05T22:24:24.566277472Z '
2025-06-05T22:24:24.566300680Z [EXECUTE] Stderr: '+ streamerIP=10.0.1.76:5555
2025-06-05T22:24:24.566329239Z + streamerNoPort=10.0.1.76
2025-06-05T22:24:24.566353072Z + adbTarget='adb -s 10.0.1.76:5555'
2025-06-05T22:24:24.566389418Z + main
2025-06-05T22:24:24.566412070Z + adbSleep
2025-06-05T22:24:24.566436424Z + sleep='input keyevent KEYCODE_SLEEP'
2025-06-05T22:24:24.566463391Z + adb -s 10.0.1.76:5555 shell input keyevent KEYCODE_SLEEP
2025-06-05T22:24:24.566489591Z + echo 'Sleep initiated for 10.0.1.76:5555'
2025-06-05T22:24:24.566515412Z + date +%s
2025-06-05T22:24:24.566540612Z + echo '10.0.1.76/stream_stopped written with epoch stop time'
2025-06-05T22:24:24.566565910Z '
2025-06-05T22:24:24.566586901Z [EXECUTE] Finished running ./scripts/osprey/directv/stopbmitune.sh in 1.17600059s
2025-06-05T22:24:28.325664000Z [EXECUTE] Stdout: 'already connected to 10.0.1.29:5555
2025-06-05T22:24:28.326195297Z Waking 10.0.1.29:5555
2025-06-05T22:24:28.326405779Z prebmitune.sh is exiting for 10.0.1.29:5555 with exit code 0
2025-06-05T22:24:28.326463672Z '
2025-06-05T22:24:28.326493577Z [EXECUTE] Stderr: '+ streamerIP=10.0.1.29:5555
2025-06-05T22:24:28.326537563Z + streamerNoPort=10.0.1.29
2025-06-05T22:24:28.326565483Z + adbTarget='adb -s 10.0.1.29:5555'
2025-06-05T22:24:28.326655192Z + mkdir -p 10.0.1.29
2025-06-05T22:24:28.326728653Z + trap finish EXIT
2025-06-05T22:24:28.326802967Z + main
2025-06-05T22:24:28.326850438Z + adbConnect
2025-06-05T22:24:28.326876240Z + adb connect 10.0.1.29:5555
2025-06-05T22:24:28.326917202Z + local -i adbMaxRetries=3
2025-06-05T22:24:28.327016212Z + local -i adbCounter=0
2025-06-05T22:24:28.327122478Z + true
2025-06-05T22:24:28.327149796Z + adb -s 10.0.1.29:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:24:28.327300709Z + local adbEventSuccess=0
2025-06-05T22:24:28.327340683Z + [[ 0 -eq 0 ]]
2025-06-05T22:24:28.327370521Z + break
2025-06-05T22:24:28.327394036Z + adbWake
2025-06-05T22:24:28.327429643Z + adb -s 10.0.1.29:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:24:28.327463298Z + sleep 2
2025-06-05T22:24:28.327498730Z + echo 'Waking 10.0.1.29:5555'
2025-06-05T22:24:28.327525964Z + touch 10.0.1.29/adbAppRunning
2025-06-05T22:24:28.327571251Z + finish
2025-06-05T22:24:28.327596046Z + echo 'prebmitune.sh is exiting for 10.0.1.29:5555 with exit code 0'
2025-06-05T22:24:28.327628560Z '
2025-06-05T22:24:28.327669287Z [EXECUTE] Finished running ./scripts/osprey/directv/prebmitune.sh in 5.068558135s
2025-06-05T22:24:28.327702255Z [EXECUTE] Running [./scripts/osprey/directv/bmitune.sh 674 10.0.1.29:5555]
2025-06-05T22:24:28.328479286Z [GIN-debug] Request: 172.23.0.1 GET /play/tuner/273, latency: 38.458764782s, status: 200
2025-06-05T22:24:30.085341627Z [EXECUTE] Stdout: 'bmitune.sh is exiting for 10.0.1.29:5555 with exit code 0
2025-06-05T22:24:30.085817828Z '
2025-06-05T22:24:30.085861988Z [EXECUTE] Stderr: '+ channelID='"674"'
2025-06-05T22:24:30.085896037Z + specialID=674
2025-06-05T22:24:30.085920937Z + streamerIP=10.0.1.29:5555
2025-06-05T22:24:30.085987564Z + streamerNoPort=10.0.1.29
2025-06-05T22:24:30.086013138Z + adbTarget='adb -s 10.0.1.29:5555'
2025-06-05T22:24:30.086041923Z + m3uName=directv.m3u
2025-06-05T22:24:30.086069006Z + trap finish EXIT
2025-06-05T22:24:30.086092411Z + main
2025-06-05T22:24:30.086114620Z + matchEncoderURL
2025-06-05T22:24:30.086138236Z + case "$streamerIP" in
2025-06-05T22:24:30.086167749Z + encoderURL=http://10.0.1.34/live/stream1
2025-06-05T22:24:30.086196249Z + tuneChannel
2025-06-05T22:24:30.086219007Z + adb -s 10.0.1.29:5555 shell input text '"674"'
2025-06-05T22:24:30.086245994Z + finish
2025-06-05T22:24:30.086274671Z + echo 'bmitune.sh is exiting for 10.0.1.29:5555 with exit code 0'
2025-06-05T22:24:30.086301474Z '
2025-06-05T22:24:30.086324279Z [EXECUTE] Finished running ./scripts/osprey/directv/bmitune.sh in 1.760837636s
2025-06-05T22:25:54.699642620Z Attempting network tune for device http://10.0.1.34/live/stream0 10.0.1.76:5555 273 
2025-06-05T22:25:54.703753873Z [EXECUTE] Running [./scripts/osprey/directv/prebmitune.sh 10.0.1.76:5555 273]
2025-06-05T22:25:54.848141682Z [IO] io.Copy: write tcp 172.23.0.2:7654->172.23.0.1:56338: write: broken pipe
2025-06-05T22:25:54.848315042Z [IOINFO] Successfully copied 44793408 bytes
2025-06-05T22:25:54.848357379Z [IOINFO] Transfer speed: 4.141590672012914 Mbits/second
2025-06-05T22:25:54.848396531Z Performing Close() for 10.0.1.29:5555
2025-06-05T22:25:54.848425698Z [EXECUTE] Running [./scripts/osprey/directv/stopbmitune.sh 10.0.1.29:5555 674]
2025-06-05T22:25:55.931659517Z [EXECUTE] Stdout: 'Sleep initiated for 10.0.1.29:5555
2025-06-05T22:25:55.932047782Z 10.0.1.29/stream_stopped written with epoch stop time
2025-06-05T22:25:55.932087258Z '
2025-06-05T22:25:55.932189904Z [EXECUTE] Stderr: '+ streamerIP=10.0.1.29:5555
2025-06-05T22:25:55.932315874Z + streamerNoPort=10.0.1.29
2025-06-05T22:25:55.932351021Z + adbTarget='adb -s 10.0.1.29:5555'
2025-06-05T22:25:55.932379133Z + main
2025-06-05T22:25:55.932404009Z + adbSleep
2025-06-05T22:25:55.932436409Z + sleep='input keyevent KEYCODE_SLEEP'
2025-06-05T22:25:55.932468462Z + adb -s 10.0.1.29:5555 shell input keyevent KEYCODE_SLEEP
2025-06-05T22:25:55.932495907Z + echo 'Sleep initiated for 10.0.1.29:5555'
2025-06-05T22:25:55.932525838Z + date +%s
2025-06-05T22:25:55.932549947Z + echo '10.0.1.29/stream_stopped written with epoch stop time'
2025-06-05T22:25:55.932575350Z '
2025-06-05T22:25:55.932596484Z [EXECUTE] Finished running ./scripts/osprey/directv/stopbmitune.sh in 1.084099602s
2025-06-05T22:25:59.090726430Z [EXECUTE] Stdout: 'already connected to 10.0.1.76:5555
2025-06-05T22:25:59.091258553Z Waking 10.0.1.76:5555
2025-06-05T22:25:59.091315353Z prebmitune.sh is exiting for 10.0.1.76:5555 with exit code 0
2025-06-05T22:25:59.091352482Z '
2025-06-05T22:25:59.091387106Z [EXECUTE] Stderr: '+ streamerIP=10.0.1.76:5555
2025-06-05T22:25:59.091419783Z + streamerNoPort=10.0.1.76
2025-06-05T22:25:59.091444081Z + adbTarget='adb -s 10.0.1.76:5555'
2025-06-05T22:25:59.091481300Z + mkdir -p 10.0.1.76
2025-06-05T22:25:59.091512979Z + trap finish EXIT
2025-06-05T22:25:59.091545049Z + main
2025-06-05T22:25:59.091573064Z + adbConnect
2025-06-05T22:25:59.091596072Z + adb connect 10.0.1.76:5555
2025-06-05T22:25:59.091627281Z + local -i adbMaxRetries=3
2025-06-05T22:25:59.091709177Z + local -i adbCounter=0
2025-06-05T22:25:59.091743457Z + true
2025-06-05T22:25:59.091775013Z + adb -s 10.0.1.76:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:25:59.091805385Z + local adbEventSuccess=0
2025-06-05T22:25:59.091841770Z + [[ 0 -eq 0 ]]
2025-06-05T22:25:59.091865776Z + break
2025-06-05T22:25:59.091888857Z + adbWake
2025-06-05T22:25:59.091921881Z + adb -s 10.0.1.76:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:25:59.091948092Z + sleep 2
2025-06-05T22:25:59.091971897Z + echo 'Waking 10.0.1.76:5555'
2025-06-05T22:25:59.092004001Z + touch 10.0.1.76/adbAppRunning
2025-06-05T22:25:59.092030737Z + finish
2025-06-05T22:25:59.092059904Z + echo 'prebmitune.sh is exiting for 10.0.1.76:5555 with exit code 0'
2025-06-05T22:25:59.092087673Z '
2025-06-05T22:25:59.092108939Z [EXECUTE] Finished running ./scripts/osprey/directv/prebmitune.sh in 4.385922632s
2025-06-05T22:25:59.092146695Z [GIN-debug] Request: 172.23.0.1 GET /play/tuner/674, latency: 1m35.84004924s, status: 200
2025-06-05T22:25:59.092189969Z [EXECUTE] Running [./scripts/osprey/directv/bmitune.sh 273 10.0.1.76:5555]
2025-06-05T22:26:00.211690836Z [EXECUTE] Stdout: 'bmitune.sh is exiting for 10.0.1.76:5555 with exit code 0
2025-06-05T22:26:00.211837407Z '
2025-06-05T22:26:00.211863195Z [EXECUTE] Stderr: '+ channelID='"273"'
2025-06-05T22:26:00.211895783Z + specialID=273
2025-06-05T22:26:00.211920677Z + streamerIP=10.0.1.76:5555
2025-06-05T22:26:00.211944790Z + streamerNoPort=10.0.1.76
2025-06-05T22:26:00.211971872Z + adbTarget='adb -s 10.0.1.76:5555'
2025-06-05T22:26:00.211997115Z + m3uName=directv.m3u
2025-06-05T22:26:00.212022249Z + trap finish EXIT
2025-06-05T22:26:00.212045860Z + main
2025-06-05T22:26:00.212068922Z + matchEncoderURL
2025-06-05T22:26:00.212093460Z + case "$streamerIP" in
2025-06-05T22:26:00.212117973Z + encoderURL=http://10.0.1.34/live/stream0
2025-06-05T22:26:00.212147071Z + tuneChannel
2025-06-05T22:26:00.212171398Z + adb -s 10.0.1.76:5555 shell input text '"273"'
2025-06-05T22:26:00.212197653Z + finish
2025-06-05T22:26:00.212219440Z + echo 'bmitune.sh is exiting for 10.0.1.76:5555 with exit code 0'
2025-06-05T22:26:00.212245587Z '
2025-06-05T22:26:00.212266534Z [EXECUTE] Finished running ./scripts/osprey/directv/bmitune.sh in 1.121409276s
2025-06-05T22:29:30.002928924Z Tuner 0 is active - skipping
2025-06-05T22:29:30.003402004Z Attempting network tune for device http://10.0.1.34/live/stream1 10.0.1.29:5555 674 
2025-06-05T22:29:30.008055093Z [EXECUTE] Running [./scripts/osprey/directv/prebmitune.sh 10.0.1.29:5555 674]
2025-06-05T22:29:34.347947157Z [EXECUTE] Stdout: 'already connected to 10.0.1.29:5555
2025-06-05T22:29:34.348313046Z Waking 10.0.1.29:5555
2025-06-05T22:29:34.348350978Z prebmitune.sh is exiting for 10.0.1.29:5555 with exit code 0
2025-06-05T22:29:34.348386656Z '
2025-06-05T22:29:34.348409690Z [EXECUTE] Stderr: '+ streamerIP=10.0.1.29:5555
2025-06-05T22:29:34.348438252Z + streamerNoPort=10.0.1.29
2025-06-05T22:29:34.348463816Z + adbTarget='adb -s 10.0.1.29:5555'
2025-06-05T22:29:34.348491584Z + mkdir -p 10.0.1.29
2025-06-05T22:29:34.348516462Z + trap finish EXIT
2025-06-05T22:29:34.348541218Z + main
2025-06-05T22:29:34.348567373Z + adbConnect
2025-06-05T22:29:34.348591122Z + adb connect 10.0.1.29:5555
2025-06-05T22:29:34.348662274Z + local -i adbMaxRetries=3
2025-06-05T22:29:34.348693561Z + local -i adbCounter=0
2025-06-05T22:29:34.348718964Z + true
2025-06-05T22:29:34.348745492Z + adb -s 10.0.1.29:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:29:34.348773938Z + local adbEventSuccess=0
2025-06-05T22:29:34.348798420Z + [[ 0 -eq 0 ]]
2025-06-05T22:29:34.348821672Z + break
2025-06-05T22:29:34.349791519Z + adbWake
2025-06-05T22:29:34.349819063Z + adb -s 10.0.1.29:5555 shell input keyevent KEYCODE_WAKEUP
2025-06-05T22:29:34.349860399Z + sleep 2
2025-06-05T22:29:34.349885115Z + echo 'Waking 10.0.1.29:5555'
2025-06-05T22:29:34.349911482Z + touch 10.0.1.29/adbAppRunning
2025-06-05T22:29:34.349942649Z + finish
2025-06-05T22:29:34.349965748Z + echo 'prebmitune.sh is exiting for 10.0.1.29:5555 with exit code 0'
2025-06-05T22:29:34.349994340Z '
2025-06-05T22:29:34.350019381Z [EXECUTE] Finished running ./scripts/osprey/directv/prebmitune.sh in 4.340065435s
2025-06-05T22:29:34.350053701Z [EXECUTE] Running [./scripts/osprey/directv/bmitune.sh 674 10.0.1.29:5555]
2025-06-05T22:29:35.439706798Z [EXECUTE] Stdout: 'bmitune.sh is exiting for 10.0.1.29:5555 with exit code 0
2025-06-05T22:29:35.440226280Z '
2025-06-05T22:29:35.440260567Z [EXECUTE] Stderr: '+ channelID='"674"'
2025-06-05T22:29:35.440294776Z + specialID=674
2025-06-05T22:29:35.440321391Z + streamerIP=10.0.1.29:5555
2025-06-05T22:29:35.440347683Z + streamerNoPort=10.0.1.29
2025-06-05T22:29:35.440377077Z + adbTarget='adb -s 10.0.1.29:5555'
2025-06-05T22:29:35.440403902Z + m3uName=directv.m3u
2025-06-05T22:29:35.440431901Z + trap finish EXIT
2025-06-05T22:29:35.440456506Z + main
2025-06-05T22:29:35.440479416Z + matchEncoderURL
2025-06-05T22:29:35.440502716Z + case "$streamerIP" in
2025-06-05T22:29:35.440528217Z + encoderURL=http://10.0.1.34/live/stream1
2025-06-05T22:29:35.440557800Z + tuneChannel
2025-06-05T22:29:35.440582135Z + adb -s 10.0.1.29:5555 shell input text '"674"'
2025-06-05T22:29:35.440609688Z + finish
2025-06-05T22:29:35.440632777Z + echo 'bmitune.sh is exiting for 10.0.1.29:5555 with exit code 0'
2025-06-05T22:29:35.440664948Z '
2025-06-05T22:29:35.440686878Z [EXECUTE] Finished running ./scripts/osprey/directv/bmitune.sh in 1.091285193s
1 Like

That's interesting. This is not the way I have my ENC5-V2 set up, but maybe they've changed something in the firmware along the way:

Otherwise, it looks like you're on track.

1 Like

Wanted to share a quick thing I discovered about the DirecTV Osprey Boxes. You can now use a MyFree DTV account to log into them. You don’t need a paid DirecTV account. This puts them in an App Only mode.

I would not necessarily recommend buying them as an Android / Google TV streamer as they are pretty old at this point. But if you have some already or can find them dirt cheap on eBay, the hardware is still nice. Still getting updates, have Ethernet and Optical audio and an amazing remote.

I have one dedicated to just running Channels App on a secondary TV. I changed the default launcher The backlight remote with channel number buttons works well. I have also tested and they do allow Apps which can be targeted for deep links, such as YTTV.

Happy Streaming!

I can get the following to work in a terminal perfectly and capture video and audio:

magewell2ts -i 1 -c h264_qsv -m | ffmpeg -i - -ss 5 -c:v copy -c:a copy -f mpegts test.ts

The same goes for this:

magewell2ts -i 1 -c h264_qsv -m | ffmpeg -i - -ss 5 -c:v copy -c:a copy -f mpegts -

The first part of the command calls a linux application for the magewell card I am experimenting with and the second takes the feed into ffmpeg for processing.

I cant seem to get it to work when I use this second one as a command in the ah4c env file.

CMD1="magewell2ts -i 1 -c h264_qsv -m | ffmpeg -i - -ss 5 -c:v copy -c:a copy -f mpegts -"
ENCODER1_URL=""
TUNER1_IP="192.168.1.12:5555"

I am doing this so I can control when the recording of the video feed by the card actually begins (-ss 5 gives a five second delay before capture starts). Any insight ?

I don't use this "tee" feature myself -- but I don't believe the approach you're using is quite right. With a device like this, my understanding is that you need specify the device, and then tee the output to ffmpeg for processing.

Something like this, based on the Magewell example in the repo:

CMD1_DEVICE="/dev/video0"
CMD1="ffmpeg -thread_queue_size 1024 -y -hwaccel cuda -hwaccel_output_format cuda -f v4l2 -i $CMD1_DEVICE -thread_queue_size 1024 -f pulse -i  alsa_input.pci-0000_08_00.0.stereo-fallback  -c:v h264_nvenc -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M  -vf 'hqdn3d=1.5:1.5:6:6,scale=3840:2160:flags=lanczos,unsharp=5:5:1.5:5:5:0.0' -c:a eac3 -strict -2 -b:a 6144000 -ar 48000 -af 'volume=2.0' -vsync 1 -async 1 -f mpegts -"

I don't think the Magewell capture utility factors in...

I see...

I was using the magewellts application because it appears to use far less system resources than the ffmpeg command, and because it allows for the loading of an EDID that allows bistreaming.

magewell2ts -i 1 -w EDID/ProCaptureHDMI-Atmos.bin -s 100 -c h264_qsv -q 10 -m

When ffmpeg is used it seems to umpix stereo to multichannel instead of pushing the original multichannel through.

The problem with the command above though is that the video begins to record at the Home Screen before the app is loaded and so the first couple of seconds registers as stereo audio . This leads to the video being identified in channels dvr as having two channels.

When the same video is viewed with vlc with the codec information displayed I can see that the moment the app (youtubetv or max for eg.) is loaded and the show starts the audio format changes to multichannel (5.1).

If I use a video editor to trim the part of the show that displays the android tv Home Screen then channels dvr displays the correct audio information. I figured if I could combine the command with ffmpeg I could delay when the recording of the show begins and do away with the android tv Home Screen section.

I wonder if you could start magewell2ts (and load your app) either in prebmitune.sh, or bmitune.sh (before the virtual tuning process begins) and send the output to a named pipe (use nohup and execute it in the background so the script continues).

That pipe name would be the same one you specify for CMD1_DEVICE. You could then do whatever other post processing you want with ffmpeg using CMD1.

The unknown here would be whether ah4c would accept a named pipe as a device, but I think it'd be worth a shot.

Still cant seem to get the delay going even when I move the turning function around. Can you say a bit more about the named pipe?

prebmitune.sh

#!/bin/bash
MAX_LAUNCH="com.wbd.stream"
MAX_NAME="com.wbd.beam.BeamActivity"
APP_NAME="com.google.android.apps.youtube.tvunplugged.activity.MainActivity"
APP_LAUNCH="com.google.android.youtube.tvunplugged"
content_file="/opt/opendct/contentid.txt"
content_id=
TUNERIP="$1"
STATIONIP="$2"

#Make Sure adb is up and connected
#sh /home/moisebuntu/Scripts/startadb.sh

# Wake up
sh startsystem.sh
adb -s $TUNERIP shell input keyevent KEYCODE_WAKEUP

# Read content_id from file
if [ -f "$content_file" ]; then
  content_id=$(grep -w "^$2" "$content_file" | cut -d " " -f3)
fi

# Check if content_id is empty
if [ -z "$content_id" ]; then
  echo "Invalid option or content_id not found in $content_file"
  exit 1
fi

#make sure adb is connected to device
adb connect $1

#check channel number and tune accordingly
if (( 810 <= $2 && $2 <= 818  ));then
        adb -s $1 shell "am start -a android.intent.action.VIEW -d https://play.max.com/channel/watch/"$content_id"" -n $MAX_LAUNCH/$MAX_NAME
	
    else

        adb -s $1 shell "am start -a android.intent.action.VIEW -d  https://tv.youtube.com/watch/"$content_id"" -n $APP_LAUNCH/$APP_NAME
fi


exit

And bmitune.sh:

#!/bin/bash

echo "$1"  > /tmp/temp.txt
echo "$2" >> /tmp/temp.txt
echo "$3" >> /tmp/temp.txt

STATION="$1"
TUNERIP="$2"
CONTENT_FILE="contentid.txt"
CONTENT_ID=""


#activate device
sleep 5 &
wait 

if [ $2 == "192.168.1.12" ]; then 


magewell2ts -i 1 -w /home/christophe/ah4c/EDID/ProCaptureHDMI-Atmos.bin -s 100 -c h264_qsv -q 10  -m

fi

if [ $2 == "192.168.1.13" ]; then 

magewell2ts -i 2 -w /home/christophe/ah4c/EDID/ProCaptureHDMI-Atmos.bin -s 100 -c h264_qsv -q 10  -m  

fi

if [ $2 == "192.168.1.14" ]; then 

magewell2ts -i 3 -w /home/christophe/ah4c/EDID/ProCaptureHDMI-Atmos.bin -s 100 -c h264_qsv -q 10  -m  

fi

if [ $2 == "192.168.1.15" ]; then 

magewell2ts -i 4 -w /home/christophe/ah4c/EDID/ProCaptureHDMI-Atmos.bin -s 100 -c h264_qsv -q 10  -m

fi

exit