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

Yes definitely, and it makes sense with LinkPi's 5 tuners per encoder. I'll add that soon-ish.

Oh, that would be best if I could add another tuner.
My whole thing is I have two ENC5s, or at least one on the way, so I wanted to run 10 Ospreys, and I realized it was maxing out at nine.

If you need help drafting a PR, let me know if I can be of any assistance. I have a long weekend right now!

@bnhf

I got this working, minimal diff too.

Test build at ghcr.io/mackid1993/ah4c:latest.

1 Like

Merged. Nicely done. I'll build a new container in the next day or so.

2 Likes

Thanks so much!

pretty sure when we were doing this, mlb was doing a freeview and I got all the mlb.tv team channels in my m3u. :wink: I have basic mlb with tmobile, but since I'm a twins fan living in iowa, I can never watch them. at some point I plan on subscribing to the team, but kinda waiting for new ownership, or at-least a lucky mix hot streak. regardless, I'd like to keep them in the m3u. (posting for other's reference)

#EXTINF:-1 channel-id="1250" channel-number="1250" tvc-guide-stationid="MLB-109-ARI",Arizona Diamondbacks – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1250

#EXTINF:-1 channel-id="1251" channel-number="1251" tvc-guide-stationid="MLB-133-ATH",Athletics – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1251

#EXTINF:-1 channel-id="1252" channel-number="1252" tvc-guide-stationid="MLB-144-ATL",Atlanta Braves – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1252

#EXTINF:-1 channel-id="1253" channel-number="1253" tvc-guide-stationid="MLB-110-BAL",Baltimore Orioles – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1253

#EXTINF:-1 channel-id="1254" channel-number="1254" tvc-guide-stationid="MLB-111-BOS",Boston Red Sox – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1254

#EXTINF:-1 channel-id="1255" channel-number="1255" tvc-guide-stationid="MLB-112-CHC",Chicago Cubs – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1255

#EXTINF:-1 channel-id="1256" channel-number="1256" tvc-guide-stationid="MLB-145-CHW",Chicago White Sox – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1256

#EXTINF:-1 channel-id="1257" channel-number="1257" tvc-guide-stationid="MLB-113-CIN",Cincinnati Reds – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1257

#EXTINF:-1 channel-id="1258" channel-number="1258" tvc-guide-stationid="MLB-114-CLE",Cleveland Guardians – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1258

#EXTINF:-1 channel-id="1259" channel-number="1259" tvc-guide-stationid="MLB-115-COL",Colorado Rockies – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1259

#EXTINF:-1 channel-id="1260" channel-number="1260" tvc-guide-stationid="MLB-116-DET",Detroit Tigers – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1260

#EXTINF:-1 channel-id="1261" channel-number="1261" tvc-guide-stationid="MLB-117-HOU",Houston Astros – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1261

#EXTINF:-1 channel-id="1262" channel-number="1262" tvc-guide-stationid="MLB-118-KCR",Kansas City Royals – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1262

#EXTINF:-1 channel-id="1263" channel-number="1263" tvc-guide-stationid="MLB-108-LAA",Los Angeles Angels – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1263

#EXTINF:-1 channel-id="1264" channel-number="1264" tvc-guide-stationid="MLB-119-LAD",Los Angeles Dodgers – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1264

#EXTINF:-1 channel-id="1265" channel-number="1265" tvc-guide-stationid="MLB-146-MIA",Miami Marlins – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1265

#EXTINF:-1 channel-id="1266" channel-number="1266" tvc-guide-stationid="MLB-158-MIL",Milwaukee Brewers – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1266

#EXTINF:-1 channel-id="1267" channel-number="1267" tvc-guide-stationid="MLB-142-MIN",Minnesota Twins – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1267

#EXTINF:-1 channel-id="1268" channel-number="1268" tvc-guide-stationid="MLB-121-NYM",New York Mets – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1268

#EXTINF:-1 channel-id="1269" channel-number="1269" tvc-guide-stationid="MLB-147-NYY",New York Yankees – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1269

#EXTINF:-1 channel-id="1270" channel-number="1270" tvc-guide-stationid="MLB-143-PHI",Philadelphia Phillies – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1270

#EXTINF:-1 channel-id="1271" channel-number="1271" tvc-guide-stationid="MLB-134-PIT",Pittsburgh Pirates – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1271

#EXTINF:-1 channel-id="1272" channel-number="1272" tvc-guide-stationid="MLB-135-SDP",San Diego Padres – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1272

#EXTINF:-1 channel-id="1273" channel-number="1273" tvc-guide-stationid="MLB-137-SFG",San Francisco Giants – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1273

#EXTINF:-1 channel-id="1274" channel-number="1274" tvc-guide-stationid="MLB-136-SEA",Seattle Mariners – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1274

#EXTINF:-1 channel-id="1275" channel-number="1275" tvc-guide-stationid="MLB-138-STL",St. Louis Cardinals – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1275

#EXTINF:-1 channel-id="1276" channel-number="1276" tvc-guide-stationid="MLB-139-TBR",Tampa Bay Rays – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1276

#EXTINF:-1 channel-id="1277" channel-number="1277" tvc-guide-stationid="MLB-140-TEX",Texas Rangers – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1277

#EXTINF:-1 channel-id="1278" channel-number="1278" tvc-guide-stationid="MLB-141-TOR",Toronto Blue Jays – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1278

#EXTINF:-1 channel-id="1279" channel-number="1279" tvc-guide-stationid="MLB-120-WAS",Washington Nationals – MLB.TV
http://{{ .IPADDRESS }}/play/tuner/1279

my issue is today i started seeing this in the log for every team.

2026/05/27 22:34:33.676553 [ERR] Failed to fetch station MLB-142-MIN for channel 1267 on X-M3U: Invalid station ID: MLB-142-MIN

can anyone with mlb check the series id's

I just got ah4c setup (through olivetin) a couple days ago and it is largely working well.

I'm seeing an issue where ah4c thinks tuners are still in use after channelsdvr releases them. Right now, only one tuner is being used, but ah4c believes all 3 are in use, resulting in tuning requests failing. The 2 that should be idle were released over an hour ago.


Let's start by taking a look a one complete tuning cycle for a single channel. This data is best grabbed from Portainer-Logs (change the number of lines to 10000 and turn off Auto-refresh to grab them). Here's an example of such a cycle from one of my setups:

[EXECUTE] Stderr: '+ dvr=utheater-pc:8089
+ channelNameID=KSTPD-8713109229817176105
++ awk -F- '{print $2}'
++ echo KSTPD-8713109229817176105
+ channelID=8713109229817176105
++ echo KSTPD-8713109229817176105
++ awk -F- '{print $1}'
+ channelName=KSTPD
+ specialID=KSTPD
+ streamerIP=192.168.1.93:5555
+ streamerNoPort=192.168.1.93
+ adbTarget='adb -s 192.168.1.93:5555'
+ packageName=com.xfinity.cloudtvr.tenfoot
+ packageAction=com.xfinity.common.view.LaunchActivity
+ m3uName=xfinity.m3u
++ grep -B1 /play/tuner/KSTPD-8713109229817176105 /opt/m3u/xfinity.m3u
++ awk -F 'channel-id="' 'NF>1 {split($2, a, "\""); print a[1]}'
+ m3uChannelID=1005
++ curl -s http://utheater-pc:8089/api/v1/channels
++ jq -r '.[] | select(.id == "1005") | .number'
+ channelNumber=1005
+ [[ false == '' ]]
+ speedMode=false
+ read -a autoCropChannels
+ trap finish EXIT
+ main
+ updateReferenceFiles
+ mkdir -p 192.168.1.93
+ [[ -f 192.168.1.93/stream_stopped ]]
+ [[ -f 192.168.1.93/last_channel ]]
+ echo 3716
+ echo 'Current PID for this script is 3716'
+ matchEncoderURL
+ case "$streamerIP" in
+ encoderURL=http://192.168.1.52:8090/stream0
+ encoderStreamNumber=stream0
+ encoderIP=192.168.1.52:8090/stream0
+ encoderIP=192.168.1.52
+ specialChannels
+ '[' KSTPD = exit ']'
+ '[' KSTPD = reboot ']'
+ [[ -f 192.168.1.93/adbCommunicationFail ]]
+ echo 'Not a special channel (exit nor reboot)'
+ tuneChannel
+ adb -s 192.168.1.93:5555 shell am start -n com.xfinity.cloudtvr.tenfoot/com.xfinity.common.view.LaunchActivity https://www.xfinity.com/stream/live/KSTPD/8713109229817176105/KSTPD
+ echo -e '#!/bin/bash\n\nwhile true; do sleep 4h; adb -s 192.168.1.93:5555 shell input keyevent KEYCODE_DPAD_DOWN; done'
+ chmod +x ./192.168.1.93/keep_watching.sh
+ [[ -n 4h ]]
+ nohup ./192.168.1.93/keep_watching.sh
+ printf '%s\n' 1810 1812 1841 1842 1846 1848 1852 1862
+ grep -qx 1005
+ :
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.93:5555 with exit code 0'
Terminated
'
[EXECUTE] Finished running ./scripts/firetv/xfinity/bmitune.sh in 3h18m12.817639882s
[EXECUTE] Stdout: 'Streaming stopped for 192.168.1.93:5555
Sleep initiated for 192.168.1.93:5555
192.168.1.93/stream_stopped written with epoch stop time
'
[EXECUTE] Stderr: '+ dvr=utheater-pc:8089
+ streamerIP=192.168.1.93:5555
+ streamerNoPort=192.168.1.93
+ channelNameID=KSTPD-8713109229817176105
+ adbTarget='adb -s 192.168.1.93:5555'
+ packageName=com.xfinity.cloudtvr.tenfoot
+ m3uName=xfinity.m3u
++ grep -B1 /play/tuner/KSTPD-8713109229817176105 /opt/m3u/xfinity.m3u
++ awk -F 'channel-id="' 'NF>1 {split($2, a, "\""); print a[1]}'
+ m3uChannelID=1005
++ curl -s http://utheater-pc:8089/api/v1/channels
++ jq -r '.[] | select(.id == "1005") | .number'
+ channelNumber=1005
+ [[ false == '' ]]
+ speedMode=false
+ read -a autoCropChannels
+ printf '%s\n' 1810 1812 1841 1842 1846 1848 1852 1862
+ grep -qx 1005
+ main
+ [[ -n croppedChannel ]]
+ matchEncoderURL
+ case "$streamerIP" in
+ encoderURL=http://192.168.1.52:8090/stream0
+ encoderStreamNumber=stream0
+ encoderIP=192.168.1.52:8090/stream0
+ encoderIP=192.168.1.52
+ bmituneDone
+ bmitunePID=3716
++ pgrep -f 192.168.1.93/keep_watching.sh
+ keepWatchingPID=3737
++ pgrep -P 3737
+ keepWatchingCPID=3738
+ [[ -n '' ]]

+ ps -p 3716
+ [[ -n 4h ]]
+ kill 3737 3738
+ rm ./192.168.1.93/keep_watching.sh
+ [[ -n '' ]]
+ rm ./192.168.1.52/stream0.sh
rm: cannot remove './192.168.1.52/stream0.sh': No such file or directory

p
+ [[ false == \t\r\u\e ]]
+ stop='am force-stop com.xfinity.cloudtvr.tenfoot'
+ adb -s 192.168.1.93:5555 shell am force-stop com.xfinity.cloudtvr.tenfoot

2
+ echo 'Streaming stopped for 192.168.1.93:5555'
+ adbSleep
+ sleep='input keyevent KEYCODE_SLEEP'
+ adb -s 192.168.1.93:5555 shell input keyevent KEYCODE_SLEEP
+ echo 'Sleep initiated for 192.168.1.93:5555'
+ date +%s
+ echo '192.168.1.93/stream_stopped written with epoch stop time'
'
[EXECUTE] Finished running ./scripts/firetv/xfinity/stopbmitune.sh in 3.657007508s
[GIN-debug] Request: 100.xxx.xxx.xxx GET /play/tuner/KSTPD-8713109229817176105, latency: 3h18m18.110633081s, status: 200

I think there are a couple tuning actions here, but I think it also may catch the problem, as I now show 2 tuners in use for COZI when in fact, none are actually being used by ChannelsDVR.

Attempting network tune for device http://192.168.8.204:8000/chn1 192.168.8.200:5555 WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.200:5555 WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961]

[EXECUTE] Stdout: 'already connected to 192.168.8.200:5555

Waking 192.168.8.200:5555

prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0

'

[EXECUTE] Stderr: '+ streamerIP=192.168.8.200:5555

+ streamerNoPort=192.168.8.200

+ adbTarget='adb -s 192.168.8.200:5555'

+ mkdir -p 192.168.8.200

+ trap finish EXIT

+ main

 + adbConnect

+ adb connect 192.168.8.200:5555

+ local -i adbMaxRetries=3

+ local -i adbCounter=0

+ true

+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP

+ local adbEventSuccess=0

+ [[ 0 -eq 0 ]]

+ break



e

+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP

+ echo 'Waking 192.168.8.200:5555'

+ touch 192.168.8.200/adbAppRunning

+ finish

+ echo 'prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0'

'

[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 164.026029ms

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961 192.168.8.200:5555]

[Tue Jun 9 09:44:26 EDT 2026] Keep-alive started for 192.168.8.200:5555 (interval: 4h)

[IO] io.Copy: write tcp 172.20.0.2:7654->172.20.0.1:60800: write: broken pipe

[IOINFO] Successfully copied 6084492 bytes

[IOINFO] Transfer speed: 6.494723514549132 Mbits/second

Performing Close() for 192.168.8.200:5555

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh 192.168.8.200:5555 WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961]

[EXECUTE] Stdout: 'Starting: Intent { act=android.intent.action.VIEW dat=https://deeplink.directvnow.com/... pkg=com.att.tv.openvideo }

bmitune.sh is exiting for 192.168.8.200:5555 with exit code 0

'

[EXECUTE] Stderr: '++ echo WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961

++ awk -F~ '{print $2}'

+ channelID=5ad9d224-cbce-ac95-d65a-33d75a313961

++ echo WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961

++ awk -F~ '{print $1}'

+ channelName=WKMG

+ specialID=WKMG

+ streamerIP=192.168.8.200:5555

+ streamerNoPort=192.168.8.200

+ adbTarget='adb -s 192.168.8.200:5555'

+ [[ false == '' ]]

+ speedMode=false

+ mkdir -p 192.168.8.200

+ echo 133

+ trap finish EXIT

+ main

+ tuneChannel

+ adb -s 192.168.8.200:5555 shell 'am start -a android.intent.action.VIEW -d '\''https://deeplink.directvnow.com/tune/live/channel/WKMG/5ad9d224-cbce-ac95-d65a-33d75a313961'\'' com.att.tv.openvideo'

Warning: Activity not started, intent has been delivered to currently running top-most instance.

+ echo -e '#!/bin/bash\n\necho "[$(date)] Keep-alive started for 192.168.8.200:5555 (interval: 4h)" > /proc/1/fd/1\nwhile true; do sleep 4h; echo "[$(date)] Keep-alive sent to 192.168.8.200:5555" > /proc/1/fd/1; adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_MEDIA_PLAY; done'

+ chmod +x ./192.168.8.200/keep_watching.sh

+ finish

+ echo 'bmitune.sh is exiting for 192.168.8.200:5555 with exit code 0'

+ [[ -n 4h ]]

+ nohup ./192.168.8.200/keep_watching.sh

Terminated

'

[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/bmitune.sh in 7.519640999s

[EXECUTE] Stdout: 'Sleep initiated for 192.168.8.200:5555

192.168.8.200/stream_stopped written with epoch stop time

'

[EXECUTE] Stderr: '+ streamerIP=192.168.8.200:5555

+ streamerNoPort=192.168.8.200

+ adbTarget='adb -s 192.168.8.200:5555'

+ main

+ bmituneDone

+ bmitunePID=133

++ pgrep -f 192.168.8.200/keep_watching.sh

+ keepWatchingPID=145

++ ps -o ppid= -p 145

+ keepWatchingPPID=' 144'

++ pgrep -P 145

+ keepWatchingCPID=147

+ ps -p 133

+ [[ -n 4h ]]

+ pkill -P 144

+ kill 147

+ rm ./192.168.8.200/keep_watching.sh

+ adbSleep

+ sleep='input keyevent KEYCODE_SLEEP'

+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_SLEEP

+ echo 'Sleep initiated for 192.168.8.200:5555'

+ date +%s

+ echo '192.168.8.200/stream_stopped written with epoch stop time'

'

[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh in 239.069896ms

[GIN-debug] Request: 172.20.0.1 GET /play/tuner/WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961, latency: 7.970209818s, status: 200

Attempting network tune for device http://192.168.8.204:8000/chn1 192.168.8.200:5555 COZI~9fd00aad-1cc7-cf23-ba3e-bae853bd6165

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.200:5555 COZI~9fd00aad-1cc7-cf23-ba3e-bae853bd6165]

[EXECUTE] Stdout: 'already connected to 192.168.8.200:5555

Waking 192.168.8.200:5555

prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0

'

[EXECUTE] Stderr: '+ streamerIP=192.168.8.200:5555

+ streamerNoPort=192.168.8.200

+ adbTarget='adb -s 192.168.8.200:5555'

+ mkdir -p 192.168.8.200

+ trap finish EXIT

+ main

 + adbConnect

+ adb connect 192.168.8.200:5555

+ local -i adbMaxRetries=3

+ local -i adbCounter=0

+ true

+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP

+ local adbEventSuccess=0

+ [[ 0 -eq 0 ]]

+ break



e

+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP

+ echo 'Waking 192.168.8.200:5555'

+ touch 192.168.8.200/adbAppRunning

+ finish

+ echo 'prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0'

'

[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 452.310845ms

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh COZI~9fd00aad-1cc7-cf23-ba3e-bae853bd6165 192.168.8.200:5555]

[Tue Jun 9 09:46:06 EDT 2026] Keep-alive started for 192.168.8.200:5555 (interval: 4h)

[GIN-debug] Loaded HTML Templates (30):

- silicondust.m3u

- coachella.m3u

- foo-fighters.m3u

- fubo.m3u

- livetv.m3u

-

- dtv407deeplinks.m3u

- spectrum.m3u

- allente.m3u

- channels.m3u

- dtvstreamdeeplinks.m3u

- kodifaves-pbs-seatac.m3u

- pbs-seatac.m3u

- xfinity.m3u

- directv-old.m3u

- npo.m3u

 - sling.m3u

- youtubetv.m3u

- directv-orlando.m3u

- dtvdeeplinks.m3u

- dtvstream.m3u

- nbc.m3u

- youtubetv_shield.m3u

- directvdeeplinks.m3u

- zinwell.m3u

- edc.m3u

- dtvosprey.m3u

- pbs-worcester.m3u

- directv.m3u

- hulu.m3u

[GIN-debug] Loaded HTML Templates (11):

- stream.html

- config.html

- editm3u.html

- index.html

- routes.html

-

 - edit.html

 - logs.html

 - m3us.html

- status.html

- status_and_logs.html

[GIN-debug] Request: 172.20.0.1 GET /m3u/dtv407deeplinks.m3u, latency: 34.776194ms, status: 200

Tuner 0 is active - skipping

Attempting network tune for device http://192.168.8.204:8000/chn2 192.168.8.201:5555 COZI~9fd00aad-1cc7-cf23-ba3e-bae853bd6165

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.201:5555 COZI~9fd00aad-1cc7-cf23-ba3e-bae853bd6165]

[EXECUTE] Stdout: 'already connected to 192.168.8.201:5555

Waking 192.168.8.201:5555

prebmitune.sh is exiting for 192.168.8.201:5555 with exit code 0

'

[EXECUTE] Stderr: '+ streamerIP=192.168.8.201:5555

+ streamerNoPort=192.168.8.201

+ adbTarget='adb -s 192.168.8.201:5555'

+ mkdir -p 192.168.8.201

+ trap finish EXIT

+ main

 + adbConnect

+ adb connect 192.168.8.201:5555

+ local -i adbMaxRetries=3

+ local -i adbCounter=0

+ true

+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_WAKEUP

+ local adbEventSuccess=0

+ [[ 0 -eq 0 ]]

+ break



e

+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_WAKEUP

+ echo 'Waking 192.168.8.201:5555'

+ touch 192.168.8.201/adbAppRunning

+ finish

+ echo 'prebmitune.sh is exiting for 192.168.8.201:5555 with exit code 0'

'

[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 530.510722ms

[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh COZI~9fd00aad-1cc7-cf23-ba3e-bae853bd6165 192.168.8.201:5555]

[Tue Jun 9 09:48:07 EDT 2026] Keep-alive started for 192.168.8.201:5555 (interval: 4h)

The first tuning action looks normal to me, but the second one you included is not complete. So let's try this:

  • Restart the ah4c container
  • Tune to one, and only one channel
  • Stop streaming that channel
  • Post the entire log from container start to streaming stop
[START] ah4c is ready
[GIN-debug] Listening and serving HTTP on :7654
> [email protected] start
> node ./index.js
Listening on:
	http://ah4c1:8000/ http://localhost:8000/
	http://127.0.0.1:8000/ http://172.20.0.2:8000/
	http://[::1]:8000/
Attempting network tune for device http://192.168.8.204:8000/chn1 192.168.8.200:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.200:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8]
[EXECUTE] Stdout: 'already connected to 192.168.8.200:5555
Waking 192.168.8.200:5555
prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0
'
[EXECUTE] Stderr: '+ streamerIP=192.168.8.200:5555
+ streamerNoPort=192.168.8.200
+ adbTarget='adb -s 192.168.8.200:5555'
+ mkdir -p 192.168.8.200
+ trap finish EXIT
+ main

+ adbConnect
+ adb connect 192.168.8.200:5555
+ local -i adbMaxRetries=3
+ local -i adbCounter=0
+ true
+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP
+ local adbEventSuccess=0
+ [[ 0 -eq 0 ]]
+ break

e
+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP
+ echo 'Waking 192.168.8.200:5555'
+ touch 192.168.8.200/adbAppRunning
+ finish
+ echo 'prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0'
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 446.704291ms
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 192.168.8.200:5555]
[Tue Jun  9 10:26:27 EDT 2026] Keep-alive started for 192.168.8.200:5555 (interval: 4h)
Tuner 0 is active - skipping
Attempting network tune for device http://192.168.8.204:8000/chn2 192.168.8.201:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.201:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8]
[EXECUTE] Stdout: 'already connected to 192.168.8.201:5555
Waking 192.168.8.201:5555
prebmitune.sh is exiting for 192.168.8.201:5555 with exit code 0
'
[EXECUTE] Stderr: '+ streamerIP=192.168.8.201:5555
+ streamerNoPort=192.168.8.201
+ adbTarget='adb -s 192.168.8.201:5555'
+ mkdir -p 192.168.8.201
+ trap finish EXIT
+ main

+ adbConnect
+ adb connect 192.168.8.201:5555
+ local -i adbMaxRetries=3
+ local -i adbCounter=0
+ true
+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_WAKEUP
+ local adbEventSuccess=0
+ [[ 0 -eq 0 ]]
+ break

e
+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_WAKEUP
+ echo 'Waking 192.168.8.201:5555'
+ touch 192.168.8.201/adbAppRunning
+ finish
+ echo 'prebmitune.sh is exiting for 192.168.8.201:5555 with exit code 0'
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 382.810105ms
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 192.168.8.201:5555]
[Tue Jun  9 10:28:27 EDT 2026] Keep-alive started for 192.168.8.201:5555 (interval: 4h)
[IO] io.Copy: write tcp 172.20.0.2:7654->172.20.0.1:34626: write: broken pipe
[IOINFO] Successfully copied 17337296 bytes
[IOINFO] Transfer speed: 6.444878585537081 Mbits/second
Performing Close() for 192.168.8.201:5555
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh 192.168.8.201:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8]
[EXECUTE] Stdout: 'Starting: Intent { act=android.intent.action.VIEW dat=https://deeplink.directvnow.com/... pkg=com.att.tv.openvideo }
bmitune.sh is exiting for 192.168.8.201:5555 with exit code 0
'
[EXECUTE] Stderr: '++ echo ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8
++ awk -F~ '{print $2}'
+ channelID=dede9246-d012-a0b5-3a0d-47e1dab9aad8
++ echo ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8
++ awk -F~ '{print $1}'
+ channelName=ESPNHD
+ specialID=ESPNHD
+ streamerIP=192.168.8.201:5555
+ streamerNoPort=192.168.8.201
+ adbTarget='adb -s 192.168.8.201:5555'
+ [[ false == '' ]]
+ speedMode=false
+ mkdir -p 192.168.8.201
+ echo 178
+ trap finish EXIT
+ main
+ tuneChannel
+ adb -s 192.168.8.201:5555 shell 'am start -a android.intent.action.VIEW -d '\''https://deeplink.directvnow.com/tune/live/channel/ESPNHD/dede9246-d012-a0b5-3a0d-47e1dab9aad8'\'' com.att.tv.openvideo'
Warning: Activity not started, intent has been delivered to currently running top-most instance.
+ echo -e '#!/bin/bash\n\necho "[$(date)] Keep-alive started for 192.168.8.201:5555 (interval: 4h)" > /proc/1/fd/1\nwhile true; do sleep 4h; echo "[$(date)] Keep-alive sent to 192.168.8.201:5555" > /proc/1/fd/1; adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_MEDIA_PLAY; done'
+ chmod +x ./192.168.8.201/keep_watching.sh
+ finish
+ [[ -n 4h ]]
+ echo 'bmitune.sh is exiting for 192.168.8.201:5555 with exit code 0'
+ nohup ./192.168.8.201/keep_watching.sh
Terminated
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/bmitune.sh in 21.639728757s
[EXECUTE] Stdout: 'Sleep initiated for 192.168.8.201:5555
192.168.8.201/stream_stopped written with epoch stop time
'
[EXECUTE] Stderr: '+ streamerIP=192.168.8.201:5555
+ streamerNoPort=192.168.8.201
+ adbTarget='adb -s 192.168.8.201:5555'
+ main
+ bmituneDone
+ bmitunePID=178
++ pgrep -f 192.168.8.201/keep_watching.sh
+ keepWatchingPID=190
++ ps -o ppid= -p 190
+ keepWatchingPPID='  189'
++ pgrep -P 190
+ keepWatchingCPID=192
+ ps -p 178
+ [[ -n 4h ]]
+ pkill -P 189
+ kill 192
+ rm ./192.168.8.201/keep_watching.sh
+ adbSleep
+ sleep='input keyevent KEYCODE_SLEEP'
+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_SLEEP
+ echo 'Sleep initiated for 192.168.8.201:5555'
+ date +%s
+ echo '192.168.8.201/stream_stopped written with epoch stop time'
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh in 247.62053ms
[GIN-debug] Request: 172.20.0.1 GET /play/tuner/ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8, latency: 22.20984483s, status: 200

      

Here is what I got after restarting the container and tuning to ESPN. This tuning attempt took exceptionally long and based on the ah4c status, it used 2 tuners leaving one showing in use. This is what I suspect is happening, as some tuning attempts are quick and others take a minute.

The status over 15 min later still showing the first tuner in use. When the channel was playing on my phone, the first 2 tuners both showed ESPN. This tuning was after a restart of the container, when no tuners were in use.

I see that second tune happening, which I can't explain yet -- that's something I've never seen before.

However, I do want to see the entire log from container start, and yours is missing everything from before the container is ready. I'm looking for this part too:

127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::	ip6-localnet
ff00::	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.20.0.2	ah4c
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
connected to 192.168.1.93:5555
connected to 192.168.1.201:5555
Existing ./scripts/firetv/directv/prebmitune.sh found, and will be preserved
Existing ./scripts/firetv/xfinity/prebmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/bmitune.sh found, and will be preserved
Existing ./scripts/firetv/xfinity/bmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/stopbmitune.sh found, and will be preserved
Existing ./scripts/firetv/xfinity/stopbmitune.sh found, and will be preserved
Existing allente.m3u found, and will be preserved
Existing channels.m3u found, and will be preserved
Existing coachella.m3u found, and will be preserved
Existing directv.m3u found, and will be preserved
Existing dtvdeeplinks.m3u found, and will be preserved
Existing dtvosprey.m3u found, and will be preserved
Existing dtvstream.m3u found, and will be preserved
Existing dtvstreamdeeplinks.m3u found, and will be preserved
Existing edc.m3u found, and will be preserved
Existing foo-fighters.m3u found, and will be preserved
Existing fubo.m3u found, and will be preserved
Existing hulu.m3u found, and will be preserved
Existing kodifaves-pbs-seatac.m3u found, and will be preserved
Existing livetv.m3u found, and will be preserved
Existing nbc.m3u found, and will be preserved
Existing npo.m3u found, and will be preserved
Existing pbs-seatac.m3u found, and will be preserved
Existing pbs-worcester.m3u found, and will be preserved
Existing silicondust.m3u found, and will be preserved
Existing sling.m3u found, and will be preserved
Existing spectrum.m3u found, and will be preserved
Existing xfinity.m3u found, and will be preserved
Existing youtubetv_shield.m3u found, and will be preserved
Existing youtubetv.m3u found, and will be preserved
Existing zinwell.m3u found, and will be preserved
[START] ah4c is starting
[ENV] Not loading env
[ENV] IPADDRESS                  channels0:7654
[ENV] ALERT_SMTP_SERVER          smtp.gmail.com:587
[ENV] ALERT_AUTH_SERVER          smtp.gmail.com
[ENV] ALERT_EMAIL_FROM           [Redacted]@gmail.com
[ENV] ALERT_EMAIL_PASS           [Redacted]
[ENV] ALERT_EMAIL_TO             [Redacted]@gmail.com
[ENV] ALERT_WEBHOOK_URL          
[ENV] ALLOW_DEBUG_VIDEO_PREVIEW  
[ENV] Creating tuner             1
[ENV] ENCODER1_URL               http://192.168.1.52:8090/stream0
[ENV] TUNER1_IP                  192.168.1.93:5555
[ENV] CMD1                       
[ENV] TEECMD1                    
[ENV] PRE SCRIPT                 ./scripts/firetv/xfinity/prebmitune.sh
[ENV] START SCRIPT               ./scripts/firetv/xfinity/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/firetv/xfinity/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/firetv/xfinity/reboot.sh
[ENV] Creating tuner             2
[ENV] ENCODER2_URL               http://192.168.1.52:8090/stream2
[ENV] TUNER2_IP                  192.168.1.201:5555
[ENV] CMD2                       
[ENV] TEECMD2                    
[ENV] PRE SCRIPT                 ./scripts/firetv/xfinity/prebmitune.sh
[ENV] START SCRIPT               ./scripts/firetv/xfinity/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/firetv/xfinity/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/firetv/xfinity/reboot.sh
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET    /favicon.ico              --> main.run.(*RouterGroup).StaticFile.func24 (2 handlers)
[GIN-debug] HEAD   /favicon.ico              --> main.run.(*RouterGroup).StaticFile.func24 (2 handlers)
[GIN-debug] Loaded HTML Templates (11): 
	- index.html

	- logs.html

	- m3us.html
	- routes.html
	- stream.html
	- config.html
	- status.html
	- status_and_logs.html
	- 

	- edit.html
	- editm3u.html
[GIN-debug] GET    /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
[GIN-debug] HEAD   /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
[GIN-debug] GET    /                         --> main.run.func1 (2 handlers)
[GIN-debug] GET    /routes                   --> main.run.func2 (2 handlers)
[GIN-debug] GET    /play/tuner:tuner/:channel --> main.run.func3 (2 handlers)
[GIN-debug] GET    /m3u/:channel             --> main.run.func4 (2 handlers)
[GIN-debug] GET    /env                      --> main.run.func5 (2 handlers)
[GIN-debug] GET    /logs/text                --> main.run.func6 (2 handlers)
[GIN-debug] GET    /logs                     --> main.run.func7 (2 handlers)
[GIN-debug] GET    /status/andlogs           --> main.run.func8 (2 handlers)
[GIN-debug] GET    /logs/json                --> main.run.func9 (2 handlers)
[GIN-debug] GET    /video                    --> main.run.func10 (2 handlers)
[GIN-debug] GET    /status                   --> main.statusPageHandler (2 handlers)
[GIN-debug] GET    /api/status               --> main.apiStatusHandler (2 handlers)
[GIN-debug] GET    /stream                   --> main.run.func11 (2 handlers)
[GIN-debug] GET    /test/webhook             --> main.run.func12 (2 handlers)
[GIN-debug] GET    /test/email               --> main.run.func13 (2 handlers)
[GIN-debug] GET    /status/channelsactivity  --> main.run.func14 (2 handlers)
[GIN-debug] GET    /edit                     --> main.run.func15 (2 handlers)
[GIN-debug] POST   /save                     --> main.run.func16 (2 handlers)
[GIN-debug] POST   /m3usave/:file            --> main.run.func17 (2 handlers)
[GIN-debug] GET    /m3us                     --> main.run.func18 (2 handlers)
[GIN-debug] GET    /editm3u/:file            --> main.run.func19 (2 handlers)
[GIN-debug] GET    /config                   --> main.run.func20 (2 handlers)
[GIN-debug] POST   /configsave               --> main.run.func21 (2 handlers)
[START] ah4c is ready
[GIN-debug] Listening and serving HTTP on :7654
> [email protected] start
> node ./index.js
Listening on:
	http://ah4c:8000/ http://localhost:8000/
	http://127.0.0.1:8000/ http://172.20.0.2:8000/
	http://[::1]:8000/

Got it, here is the full thing again with the added part a the top:

'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh in 138.851893ms
[GIN-debug] Request: 172.20.0.1 GET /play/tuner/WKMG~5ad9d224-cbce-ac95-d65a-33d75a313961, latency: 24.54545738s, status: 200
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::	ip6-localnet
ff00::	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.20.0.2	ah4c1
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
connected to 192.168.8.200:5555
connected to 192.168.8.201:5555
connected to 192.168.8.203:5555
No existing ./scripts/firetv/directv/prebmitune.sh found or UPDATE_SCRIPTS set to true
No existing ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh found or UPDATE_SCRIPTS set to true
No existing ./scripts/firetv/directv/bmitune.sh found or UPDATE_SCRIPTS set to true
No existing ./scripts/osprey/dtvospreydeeplinks/bmitune.sh found or UPDATE_SCRIPTS set to true
No existing ./scripts/firetv/directv/stopbmitune.sh found or UPDATE_SCRIPTS set to true
No existing ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh found or UPDATE_SCRIPTS set to true
No existing allente.m3u found or UPDATE_M3US set to true
No existing channels.m3u found or UPDATE_M3US set to true
No existing coachella.m3u found or UPDATE_M3US set to true
No existing directv.m3u found or UPDATE_M3US set to true
No existing dtvdeeplinks.m3u found or UPDATE_M3US set to true
No existing dtvosprey.m3u found or UPDATE_M3US set to true
No existing dtvstream.m3u found or UPDATE_M3US set to true
No existing dtvstreamdeeplinks.m3u found or UPDATE_M3US set to true
No existing edc.m3u found or UPDATE_M3US set to true
No existing foo-fighters.m3u found or UPDATE_M3US set to true
No existing fubo.m3u found or UPDATE_M3US set to true
No existing hulu.m3u found or UPDATE_M3US set to true
No existing kodifaves-pbs-seatac.m3u found or UPDATE_M3US set to true
No existing livetv.m3u found or UPDATE_M3US set to true
No existing nbc.m3u found or UPDATE_M3US set to true
No existing npo.m3u found or UPDATE_M3US set to true
No existing pbs-seatac.m3u found or UPDATE_M3US set to true
No existing pbs-worcester.m3u found or UPDATE_M3US set to true
No existing silicondust.m3u found or UPDATE_M3US set to true
No existing sling.m3u found or UPDATE_M3US set to true
No existing spectrum.m3u found or UPDATE_M3US set to true
No existing xfinity.m3u found or UPDATE_M3US set to true
No existing youtubetv_shield.m3u found or UPDATE_M3US set to true
No existing youtubetv.m3u found or UPDATE_M3US set to true
No existing zinwell.m3u found or UPDATE_M3US set to true
No user-defined custom script to run
[START] ah4c is starting
[ENV] Not loading env
[ENV] IPADDRESS                  192.168.8.132:7654
[ENV] ALERT_SMTP_SERVER          
[ENV] ALERT_AUTH_SERVER          
[ENV] ALERT_EMAIL_FROM           
[ENV] ALERT_EMAIL_PASS           
[ENV] ALERT_EMAIL_TO             
[ENV] ALERT_WEBHOOK_URL          
[ENV] ALLOW_DEBUG_VIDEO_PREVIEW  
[ENV] NULL_FRAME_INSERTION       
[ENV] Creating tuner             1
[ENV] ENCODER1_URL               http://192.168.8.204:8000/chn1
[ENV] TUNER1_IP                  192.168.8.200:5555
[ENV] CMD1                       
[ENV] TEECMD1                    
[ENV] PRE SCRIPT                 ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh
[ENV] START SCRIPT               ./scripts/osprey/dtvospreydeeplinks/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/osprey/dtvospreydeeplinks/reboot.sh
[ENV] Creating tuner             2
[ENV] ENCODER2_URL               http://192.168.8.204:8000/chn2
[ENV] TUNER2_IP                  192.168.8.201:5555
[ENV] CMD2                       
[ENV] TEECMD2                    
[ENV] PRE SCRIPT                 ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh
[ENV] START SCRIPT               ./scripts/osprey/dtvospreydeeplinks/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/osprey/dtvospreydeeplinks/reboot.sh
[ENV] Creating tuner             3
[ENV] ENCODER3_URL               http://192.168.8.204:8000/chn3
[ENV] TUNER3_IP                  192.168.8.203:5555
[ENV] CMD3                       
[ENV] TEECMD3                    
[ENV] PRE SCRIPT                 ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh
[ENV] START SCRIPT               ./scripts/osprey/dtvospreydeeplinks/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/osprey/dtvospreydeeplinks/reboot.sh
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET    /favicon.ico              --> main.run.(*RouterGroup).StaticFile.func24 (2 handlers)
[GIN-debug] HEAD   /favicon.ico              --> main.run.(*RouterGroup).StaticFile.func24 (2 handlers)
[GIN-debug] Loaded HTML Templates (11): 
	- config.html

	- logs.html
	- routes.html
	- status_and_logs.html
	- stream.html

	- edit.html
	- editm3u.html
	- index.html

	- m3us.html
	- status.html
	- 
[GIN-debug] GET    /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
[GIN-debug] HEAD   /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (2 handlers)
[GIN-debug] GET    /                         --> main.run.func1 (2 handlers)
[GIN-debug] GET    /routes                   --> main.run.func2 (2 handlers)
[GIN-debug] GET    /play/tuner:tuner/:channel --> main.run.func3 (2 handlers)
[GIN-debug] GET    /m3u/:channel             --> main.run.func4 (2 handlers)
[GIN-debug] GET    /env                      --> main.run.func5 (2 handlers)
[GIN-debug] GET    /logs/text                --> main.run.func6 (2 handlers)
[GIN-debug] GET    /logs                     --> main.run.func7 (2 handlers)
[GIN-debug] GET    /status/andlogs           --> main.run.func8 (2 handlers)
[GIN-debug] GET    /logs/json                --> main.run.func9 (2 handlers)
[GIN-debug] GET    /video                    --> main.run.func10 (2 handlers)
[GIN-debug] GET    /status                   --> main.statusPageHandler (2 handlers)
[GIN-debug] GET    /api/status               --> main.apiStatusHandler (2 handlers)
[GIN-debug] GET    /stream                   --> main.run.func11 (2 handlers)
[GIN-debug] GET    /test/webhook             --> main.run.func12 (2 handlers)
[GIN-debug] GET    /test/email               --> main.run.func13 (2 handlers)
[GIN-debug] GET    /status/channelsactivity  --> main.run.func14 (2 handlers)
[GIN-debug] GET    /edit                     --> main.run.func15 (2 handlers)
[GIN-debug] POST   /save                     --> main.run.func16 (2 handlers)
[GIN-debug] POST   /m3usave/:file            --> main.run.func17 (2 handlers)
[GIN-debug] GET    /m3us                     --> main.run.func18 (2 handlers)
[GIN-debug] GET    /editm3u/:file            --> main.run.func19 (2 handlers)
[GIN-debug] GET    /config                   --> main.run.func20 (2 handlers)
[GIN-debug] POST   /configsave               --> main.run.func21 (2 handlers)
[START] ah4c is ready
[GIN-debug] Listening and serving HTTP on :7654
> [email protected] start
> node ./index.js
Listening on:
	http://ah4c1:8000/ http://localhost:8000/
	http://127.0.0.1:8000/ http://172.20.0.2:8000/
	http://[::1]:8000/
Attempting network tune for device http://192.168.8.204:8000/chn1 192.168.8.200:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.200:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8]
[EXECUTE] Stdout: 'already connected to 192.168.8.200:5555
Waking 192.168.8.200:5555
prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0
'
[EXECUTE] Stderr: '+ streamerIP=192.168.8.200:5555
+ streamerNoPort=192.168.8.200
+ adbTarget='adb -s 192.168.8.200:5555'
+ mkdir -p 192.168.8.200
+ trap finish EXIT
+ main

+ adbConnect
+ adb connect 192.168.8.200:5555
+ local -i adbMaxRetries=3
+ local -i adbCounter=0
+ true
+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP
+ local adbEventSuccess=0
+ [[ 0 -eq 0 ]]
+ break

e
+ adb -s 192.168.8.200:5555 shell input keyevent KEYCODE_WAKEUP
+ echo 'Waking 192.168.8.200:5555'
+ touch 192.168.8.200/adbAppRunning
+ finish
+ echo 'prebmitune.sh is exiting for 192.168.8.200:5555 with exit code 0'
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 446.704291ms
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 192.168.8.200:5555]
[Tue Jun  9 10:26:27 EDT 2026] Keep-alive started for 192.168.8.200:5555 (interval: 4h)
Tuner 0 is active - skipping
Attempting network tune for device http://192.168.8.204:8000/chn2 192.168.8.201:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/prebmitune.sh 192.168.8.201:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8]
[EXECUTE] Stdout: 'already connected to 192.168.8.201:5555
Waking 192.168.8.201:5555
prebmitune.sh is exiting for 192.168.8.201:5555 with exit code 0
'
[EXECUTE] Stderr: '+ streamerIP=192.168.8.201:5555
+ streamerNoPort=192.168.8.201
+ adbTarget='adb -s 192.168.8.201:5555'
+ mkdir -p 192.168.8.201
+ trap finish EXIT
+ main

+ adbConnect
+ adb connect 192.168.8.201:5555
+ local -i adbMaxRetries=3
+ local -i adbCounter=0
+ true
+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_WAKEUP
+ local adbEventSuccess=0
+ [[ 0 -eq 0 ]]
+ break

e
+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_WAKEUP
+ echo 'Waking 192.168.8.201:5555'
+ touch 192.168.8.201/adbAppRunning
+ finish
+ echo 'prebmitune.sh is exiting for 192.168.8.201:5555 with exit code 0'
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/prebmitune.sh in 382.810105ms
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/bmitune.sh ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8 192.168.8.201:5555]
[Tue Jun  9 10:28:27 EDT 2026] Keep-alive started for 192.168.8.201:5555 (interval: 4h)
[IO] io.Copy: write tcp 172.20.0.2:7654->172.20.0.1:34626: write: broken pipe
[IOINFO] Successfully copied 17337296 bytes
[IOINFO] Transfer speed: 6.444878585537081 Mbits/second
Performing Close() for 192.168.8.201:5555
[EXECUTE] Running [./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh 192.168.8.201:5555 ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8]
[EXECUTE] Stdout: 'Starting: Intent { act=android.intent.action.VIEW dat=https://deeplink.directvnow.com/... pkg=com.att.tv.openvideo }
bmitune.sh is exiting for 192.168.8.201:5555 with exit code 0
'
[EXECUTE] Stderr: '++ echo ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8
++ awk -F~ '{print $2}'
+ channelID=dede9246-d012-a0b5-3a0d-47e1dab9aad8
++ echo ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8
++ awk -F~ '{print $1}'
+ channelName=ESPNHD
+ specialID=ESPNHD
+ streamerIP=192.168.8.201:5555
+ streamerNoPort=192.168.8.201
+ adbTarget='adb -s 192.168.8.201:5555'
+ [[ false == '' ]]
+ speedMode=false
+ mkdir -p 192.168.8.201
+ echo 178
+ trap finish EXIT
+ main
+ tuneChannel
+ adb -s 192.168.8.201:5555 shell 'am start -a android.intent.action.VIEW -d '\''https://deeplink.directvnow.com/tune/live/channel/ESPNHD/dede9246-d012-a0b5-3a0d-47e1dab9aad8'\'' com.att.tv.openvideo'
Warning: Activity not started, intent has been delivered to currently running top-most instance.
+ echo -e '#!/bin/bash\n\necho "[$(date)] Keep-alive started for 192.168.8.201:5555 (interval: 4h)" > /proc/1/fd/1\nwhile true; do sleep 4h; echo "[$(date)] Keep-alive sent to 192.168.8.201:5555" > /proc/1/fd/1; adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_MEDIA_PLAY; done'
+ chmod +x ./192.168.8.201/keep_watching.sh
+ finish
+ [[ -n 4h ]]
+ echo 'bmitune.sh is exiting for 192.168.8.201:5555 with exit code 0'
+ nohup ./192.168.8.201/keep_watching.sh
Terminated
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/bmitune.sh in 21.639728757s
[EXECUTE] Stdout: 'Sleep initiated for 192.168.8.201:5555
192.168.8.201/stream_stopped written with epoch stop time
'
[EXECUTE] Stderr: '+ streamerIP=192.168.8.201:5555
+ streamerNoPort=192.168.8.201
+ adbTarget='adb -s 192.168.8.201:5555'
+ main
+ bmituneDone
+ bmitunePID=178
++ pgrep -f 192.168.8.201/keep_watching.sh
+ keepWatchingPID=190
++ ps -o ppid= -p 190
+ keepWatchingPPID='  189'
++ pgrep -P 190
+ keepWatchingCPID=192
+ ps -p 178
+ [[ -n 4h ]]
+ pkill -P 189
+ kill 192
+ rm ./192.168.8.201/keep_watching.sh
+ adbSleep
+ sleep='input keyevent KEYCODE_SLEEP'
+ adb -s 192.168.8.201:5555 shell input keyevent KEYCODE_SLEEP
+ echo 'Sleep initiated for 192.168.8.201:5555'
+ date +%s
+ echo '192.168.8.201/stream_stopped written with epoch stop time'
'
[EXECUTE] Finished running ./scripts/osprey/dtvospreydeeplinks/stopbmitune.sh in 247.62053ms
[GIN-debug] Request: 172.20.0.1 GET /play/tuner/ESPNHD~dede9246-d012-a0b5-3a0d-47e1dab9aad8, latency: 22.20984483s, status: 200

@mackid1993 I was wondering if you could take a look at this? Since this code has been stable, for a number of years, before recent changes -- I'm a bit suspicious of this new issue reported by @PSPS. As you can see in the attached log, prebmitune.sh just gets finished and another tuning cycle is started.

@PSPS Could you post the corresponding tuning cycle for this channel from the CDVR logs? I just want to be sure CDVR isn't initiating this second tune. Also, when you get a moment, could you stop the ah4c stack and change the value of TAG in the env vars section of the Portainer-Stacks Editor to 2026.04.06, and let's see if this same problem exists.

I've been running this for ages with no issues. @PSPS can you share your docker-compose.yml and .env?

Question: are these osprey deeplinks scripts being used with ospreys? If not I (think I) know the problem.

The keepalive will press play on the set interval which is meant to keep an osprey going. Not sure if that will break a different device.

This is in the CDVR log:

2026/06/09 10:26:27.076729 [TNR] Opened connection to M3U-ah4c1-dtv407deeplinks for ch206 ESPN
2026/06/09 10:28:27.078747 [TNR] Closing connection M3U-ah4c1-dtv407deeplinks ch206 after no data was received for 2m0s
2026/06/09 10:28:27.078747 [TNR] Closed connection to M3U-ah4c1-dtv407deeplinks for ch206 ESPN
2026/06/09 10:28:27.079322 [SNR] Buffer statistics for 192.168.8.132 (192.168.8.132) for ch206 ESPN: buf=0% drop=0%
2026/06/09 10:28:27.535096 [TNR] Opened connection to M3U-ah4c1-dtv407deeplinks for ch206 ESPN
2026/06/09 10:28:48.993318 [SNR] Buffer statistics for 192.168.8.132 (192.168.8.132) for ch206 ESPN: buf=0% drop=0%
2026/06/09 10:28:48.993318 [TNR] Closed connection to M3U-ah4c1-dtv407deeplinks for ch206 ESPN

Also, I did not see a TAG entry in the env variables - I added it with the value specified and will try to recreate the behavior.

I have 3 osprey devices attached. Two are the newer dongle style and 1 is the older box style with the ethernet connection.

Ok can you share your compose and env