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

Been a while since I've swung around to this. Wanted to give just a general update about usage and some mods: Our family uses this heavily, and it's been working great. Thank you again! Only issue is the ADB key reset; bandaid for me is to redeploy docker stack and re-allow ADB for each android box when the prompt comes up. I have to do this sometimes every few weeks. Besides that, the tuning on osprey boxes has been really good. Rarely is there a tuning issue. It does occur here and there, but enough where people are trained to retune and I don't care.

In other news I modified the scripts heavily to do some interesting things. I am successfully controlling an old sirius xm polk xrt12 from 2005 via rs232... over a network, with the help of a Opengear Console Server where rs232 controllable devices can be individually controlled via an ssh session. I spun up a separate docker stack, reverse engineered the scripts for ah4c, ripped out the ADB portions, and replaced them with an SSH command that connects to the receiver over serial and tunes to music stations. The Polk models have video outputs (composite), which I feed to a Contemporary Research Encoder.

I have a second polk here that I need to add, which I'll do soon. I am a complete idiot, so let me know if its useful to share the rs232 script and how I should do that. It's hacked together, but it works for us with this sick console server I got on ebay.

One suggestion for the developers: show the key contents on the web UI somewhere, and offer an env var override. That way you can copy the allowed key into your docker env and it will stay consistent going forward.

:open_mouth::clap:t3:

2 Likes

What would be the advantage of this approach over the current directory binding for the adb keys?

2 Likes

@bnhf

I have been running the bnhf/ah4c:appletv build since March when we worked out all the issues to use it with Spectrum TV app...
I set my scripts/m3u's to not update. I also disabled updates on the AppleTV 4k's. Everything has worked great till now...

Spectrum TV forced me to update the apps on the AppleTV's or it would not allow me to watch channels anymore. Now it will do 1 of 3 things when I tune different channels ...

  1. Display the channel as Normal
  2. Display a large screen overlay blocking most of the live channel that has an "Exit to Live TV" selection
  3. Display a small block at bottom of live screen that asks if I want to "Watch from the beginning?"

I was thinking I will need to try and use tesseract to have a chance to overcome this.
It doesn't look like you have ran an update for the Appletv tag version since March.
Would it be possible to add this to the Appletv version and let me know if you have additional suggestions for me to try. :grinning:

Shouldn't be a problem -- I'll give it a go tomorrow. I see the ghcr.io/postlund/pyatv:master I'm using for the final part of the build just got updated about a week ago. I assume you want me to use this latest :master? Before this recent update, pyatv hadn't changed since late last year.

Sounds Great
Yea go ahead and use latest:master...I assume you used master before? That way I can verify everything works with newest pyatv at the same time...
Really Appreciate it

Decided to do a quick test build today if you want to spin it up and make sure it loads OK and such. I added tesseract-ocr and used the latest :master (as I did before). Pushed as bnhf/ah4c:appletv.test

EDIT: Also, in case it's helpful, here's an example of a Bash function to grab a single frame and perform OCR on it:

tuneCheck() {
  sleep 40
  ffmpeg -i $encoderURL -frames:v 1 -y $streamerNoPort/screencapture.jpg -loglevel quiet
  tesseract $streamerNoPort/screencapture.jpg $streamerNoPort/screencapture
  grep -q "Filter\|Today" $streamerNoPort/screencapture.txt

  if [ $? == 0 ]; then
    echo "Deeplink tuning appears to have failed. Killing app and re-tuning..."
    $adbTarget shell am force-stop $packageName
    tuneChannel
  else
    echo "Deeplink tuning appears to have been successful!"
  fi
}

The sleep could be shortened to match however much time you want to allow before performing the check.

"Filter" or "Today" are the two words being tested for, and if either is found an error code 0 is returned.

Just spun it up with no changes except image....
Looks like pyatv part not working...

AttributeError: type object 'ProtocolMessage' has no attribute 'RegisterExtension'
Existing ./scripts/firetv/directv/prebmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/bmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/stopbmitune.sh found, and will be preserved
Existing directv.m3u found, and will be preserved
Existing dtvosprey.m3u found, and will be preserved
Existing dtvstream.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 livetv.m3u found, and will be preserved
Existing npo.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 youtubetv_shield.m3u found, and will be preserved
Existing youtubetv.m3u found, and will be preserved
[START] ah4c is starting
[ENV] Not loading env
[ENV] IPADDRESS 192.168.1.101: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] Creating tuner 1
[ENV] ENCODER1_URL http://192.168.1.41/live/stream3
[ENV] TUNER1_IP 192.168.1.54
[ENV] CMD1
[ENV] TEECMD1
[ENV] PRE SCRIPT ./scripts/atv/spectrum/prebmitune.sh
[ENV] START SCRIPT ./scripts/atv/spectrum/bmitune.sh
[ENV] STOP SCRIPT ./scripts/atv/spectrum/stopbmitune.sh
[ENV] REBOOT SCRIPT ./scripts/atv/spectrum/reboot.sh
[ENV] Creating tuner 2
[ENV] ENCODER2_URL http://192.168.1.41/live/stream4
[ENV] TUNER2_IP 192.168.1.55
[ENV] CMD2
[ENV] TEECMD2
[ENV] PRE SCRIPT ./scripts/atv/spectrum/prebmitune.sh
[ENV] START SCRIPT ./scripts/atv/spectrum/bmitune.sh
[ENV] STOP SCRIPT ./scripts/atv/spectrum/stopbmitune.sh
[ENV] REBOOT SCRIPT ./scripts/atv/spectrum/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 --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
    [GIN-debug] HEAD /favicon.ico --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
    [GIN-debug] Loaded HTML Templates (11):
  • status.html
  • config.html
  • edit.html
  • logs.html
  • m3us.html
  • routes.html
  • editm3u.html
  • index.html
  • status_and_logs.html
  • stream.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
    Attempting network tune for device http://192.168.1.41/live/stream3 192.168.1.54 32771
    [EXECUTE] Running [./scripts/atv/spectrum/prebmitune.sh 192.168.1.54 32771]
    [EXECUTE] Stdout: ''
    [EXECUTE] Stderr: ''
    [EXECUTE] Finished running ./scripts/atv/spectrum/prebmitune.sh in 4.748612ms
    [EXECUTE] Running [./scripts/atv/spectrum/bmitune.sh 32771 192.168.1.54]
    [EXECUTE] Stdout: ''
    [EXECUTE] Stderr: 'Traceback (most recent call last):
    File "/usr/local/bin/atvremote", line 5, in
    from pyatv.scripts.atvremote import main
    File "/usr/local/lib/python3.12/site-packages/pyatv/init.py", line 26, in
    from pyatv.protocols import PROTOCOLS
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/init.py", line 10, in
    from pyatv.protocols import airplay as airplay_proto
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/airplay/init.py", line 28, in
    from pyatv.protocols import mrp
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/init.py", line 60, in
    from pyatv.protocols.mrp import messages, protobuf
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/messages.py", line 9, in
    from pyatv.protocols.mrp import protobuf
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/init.py", line 9, in
    from . import AudioFadeMessage_pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/AudioFadeMessage_pb2.py", line 15, in
    from pyatv.protocols.mrp.protobuf import PlayerPath_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_PlayerPath__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/PlayerPath_pb2.py", line 14, in
    from pyatv.protocols.mrp.protobuf import Origin_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_Origin__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/Origin_pb2.py", line 14, in
    from pyatv.protocols.mrp.protobuf import DeviceInfoMessage_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_DeviceInfoMessage__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/DeviceInfoMessage_pb2.py", line 24, in
    pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_ProtocolMessage__pb2.ProtocolMessage.RegisterExtension(deviceInfoMessage)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    AttributeError: type object 'ProtocolMessage' has no attribute 'RegisterExtension'
    '
    [EXECUTE] Finished running ./scripts/atv/spectrum/bmitune.sh in 905.080885ms
    [ERR] Failed to run start script: exit status 1
    [IO] io.Copy: write tcp 172.31.0.2:7654->192.168.1.20:40130: write: broken pipe
    [IOINFO] Successfully copied 4762004 bytes
    [IOINFO] Transfer speed: 0.5984158457025579 Mbits/second
    Performing Close() for 192.168.1.54
    [EXECUTE] Running [./scripts/atv/spectrum/stopbmitune.sh 192.168.1.54 32771]
    [EXECUTE] Stdout: ''
    [EXECUTE] Stderr: 'Traceback (most recent call last):
    File "/usr/local/bin/atvremote", line 5, in
    from pyatv.scripts.atvremote import main
    File "/usr/local/lib/python3.12/site-packages/pyatv/init.py", line 26, in
    from pyatv.protocols import PROTOCOLS
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/init.py", line 10, in
    from pyatv.protocols import airplay as airplay_proto
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/airplay/init.py", line 28, in
    from pyatv.protocols import mrp
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/init.py", line 60, in
    from pyatv.protocols.mrp import messages, protobuf
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/messages.py", line 9, in
    from pyatv.protocols.mrp import protobuf
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/init.py", line 9, in
    from . import AudioFadeMessage_pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/AudioFadeMessage_pb2.py", line 15, in
    from pyatv.protocols.mrp.protobuf import PlayerPath_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_PlayerPath__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/PlayerPath_pb2.py", line 14, in
    from pyatv.protocols.mrp.protobuf import Origin_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_Origin__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/Origin_pb2.py", line 14, in
    from pyatv.protocols.mrp.protobuf import DeviceInfoMessage_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_DeviceInfoMessage__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/DeviceInfoMessage_pb2.py", line 24, in
    pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_ProtocolMessage__pb2.ProtocolMessage.RegisterExtension(deviceInfoMessage)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    AttributeError: type object 'ProtocolMessage' has no attribute 'RegisterExtension'
    '
    [EXECUTE] Finished running ./scripts/atv/spectrum/stopbmitune.sh in 882.959319ms
    [ERR] Failed to run stop script: exit status 1
    [EXECUTE] Running [./scripts/atv/spectrum/reboot.sh 192.168.1.54 32771]
    [EXECUTE] Stdout: ''
    [EXECUTE] Stderr: ''
    [EXECUTE] Finished running ./scripts/atv/spectrum/reboot.sh in 610.201ยตs
    [GIN-debug] Request: 192.168.1.20 GET /play/tuner/32771, latency: 1m4.555481955s, status: 200

Here is the log...

Turns out there was a :latest tag for the pyatv container, so I built again using that as a starting point. If this doesn't work, it'll probably make sense to try the version from 12/23 we used before. Let me know how it goes. Pushed again as :appletv.test.

Still not Running...I don't know if it makes a difference but I remember we had to use a different base build before because your original one would not run the pyatv stuff. So we had to use a different one for just amd64 and maybe arm64...

[START] ah4c is ready
[GIN-debug] Listening and serving HTTP on :7654
[GIN-debug] Loaded HTML Templates (11):

  • index.html
  • logs.html
  • routes.html
  • status.html
  • status_and_logs.html
  • stream.html
  • editm3u.html
  • m3us.html
  • config.html
  • edit.html
    [GIN-debug] Request: 192.168.1.184 GET /, latency: 4.619243ms, status: 200
    [GIN-debug] Loaded HTML Templates (11):
  • index.html
  • logs.html
  • status.html
  • stream.html
  • status_and_logs.html
  • config.html
  • edit.html
  • editm3u.html
  • m3us.html
  • routes.html
    [GIN-debug] Request: 192.168.1.184 GET /, latency: 3.413568ms, status: 200
    [GIN-debug] Request: 192.168.1.184 GET /status, latency: 5.272982ms, status: 200
    [GIN-debug] Request: 192.168.1.184 GET /status/andlogs, latency: 2.141965ms, status: 200
    [GIN-debug] Request: 192.168.1.184 GET /logs?notime, latency: 2.155091ms, status: 200
    [GIN-debug] Request: 192.168.1.184 GET /status, latency: 4.468869ms, status: 200
    Attempting network tune for device http://192.168.1.41/live/stream3 192.168.1.54 58515
    [EXECUTE] Running [./scripts/atv/spectrum/prebmitune.sh 192.168.1.54 58515]
    [EXECUTE] Stdout: ''
    [EXECUTE] Stderr: ''
    [EXECUTE] Finished running ./scripts/atv/spectrum/prebmitune.sh in 4.865311ms
    [EXECUTE] Running [./scripts/atv/spectrum/bmitune.sh 58515 192.168.1.54]
    [EXECUTE] Stdout: ''
    [EXECUTE] Stderr: 'Traceback (most recent call last):
    File "/usr/local/bin/atvremote", line 5, in
    from pyatv.scripts.atvremote import main
    File "/usr/local/lib/python3.12/site-packages/pyatv/init.py", line 26, in
    from pyatv.protocols import PROTOCOLS
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/init.py", line 10, in
    from pyatv.protocols import airplay as airplay_proto
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/airplay/init.py", line 28, in
    from pyatv.protocols import mrp
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/init.py", line 60, in
    from pyatv.protocols.mrp import messages, protobuf
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/messages.py", line 9, in
    from pyatv.protocols.mrp import protobuf
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/init.py", line 9, in
    from . import AudioFadeMessage_pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/AudioFadeMessage_pb2.py", line 15, in
    from pyatv.protocols.mrp.protobuf import PlayerPath_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_PlayerPath__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/PlayerPath_pb2.py", line 14, in
    from pyatv.protocols.mrp.protobuf import Origin_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_Origin__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/Origin_pb2.py", line 14, in
    from pyatv.protocols.mrp.protobuf import DeviceInfoMessage_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_DeviceInfoMessage__pb2
    File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/DeviceInfoMessage_pb2.py", line 24, in
    pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_ProtocolMessage__pb2.ProtocolMessage.RegisterExtension(deviceInfoMessage)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    AttributeError: type object 'ProtocolMessage' has no attribute 'RegisterExtension'
    '
    [EXECUTE] Finished running ./scripts/atv/spectrum/bmitune.sh in 899.986141ms
    [ERR] Failed to run start script: exit status 1

We're using the pyatv container itself, with some modifications. Can you post just the part of the logs from container start until "ah4c ready" with no attempts at tuning.

Also, don't forget to use 3 backticks before and after logs or code blocks for best readability...

This should be it...sending from phone...if not i will try and get you better tomorrow

bnhf/ah4c:appletv.test

  File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/AudioFadeMessage_pb2.py", line 15, in <module>
    from pyatv.protocols.mrp.protobuf import PlayerPath_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_PlayerPath__pb2
  File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/PlayerPath_pb2.py", line 14, in <module>
    from pyatv.protocols.mrp.protobuf import Origin_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_Origin__pb2
  File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/Origin_pb2.py", line 14, in <module>
    from pyatv.protocols.mrp.protobuf import DeviceInfoMessage_pb2 as pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_DeviceInfoMessage__pb2
  File "/usr/local/lib/python3.12/site-packages/pyatv/protocols/mrp/protobuf/DeviceInfoMessage_pb2.py", line 24, in <module>
    pyatv_dot_protocols_dot_mrp_dot_protobuf_dot_ProtocolMessage__pb2.ProtocolMessage.RegisterExtension(deviceInfoMessage)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'ProtocolMessage' has no attribute 'RegisterExtension'
Existing ./scripts/firetv/directv/prebmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/bmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/stopbmitune.sh found, and will be preserved
Existing directv.m3u found, and will be preserved
Existing dtvosprey.m3u found, and will be preserved
Existing dtvstream.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 livetv.m3u found, and will be preserved
Existing npo.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 youtubetv_shield.m3u found, and will be preserved
Existing youtubetv.m3u found, and will be preserved
[START] ah4c is starting
[ENV] Not loading env
[ENV] IPADDRESS                  192.168.1.101: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] Creating tuner             1
[ENV] ENCODER1_URL               http://192.168.1.41/live/stream3
[ENV] TUNER1_IP                  192.168.1.54
[ENV] CMD1                       
[ENV] TEECMD1                    
[ENV] PRE SCRIPT                 ./scripts/atv/spectrum/prebmitune.sh
[ENV] START SCRIPT               ./scripts/atv/spectrum/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/atv/spectrum/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/atv/spectrum/reboot.sh
[ENV] Creating tuner             2
[ENV] ENCODER2_URL               http://192.168.1.41/live/stream4
[ENV] TUNER2_IP                  192.168.1.55
[ENV] CMD2                       
[ENV] TEECMD2                    
[ENV] PRE SCRIPT                 ./scripts/atv/spectrum/prebmitune.sh
[ENV] START SCRIPT               ./scripts/atv/spectrum/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/atv/spectrum/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/atv/spectrum/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              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
[GIN-debug] HEAD   /favicon.ico              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
[GIN-debug] Loaded HTML Templates (11): 
	- config.html

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

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

	- m3us.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 here

The only thing we're doing with pyatv during the container startup is this function:

# List currently connected atv devices and then connect to each indivdually
atvConnections() {

  local atvs=($@)
  
  for atv in "${atvs[@]}"
    do
      if [[ -n $atv ]]; then
        atvremote --scan-hosts $atv scan
      fi
  done
}

This cycles through your TUNERx_IP values (your Apple TVs) and lists the supported (and paired) protocols. Can you think of a reason this might be failing based on your test setup?

@bnhf

I had never bothered to update my stack to use the environment variable section instead of just putting them in the docker stack...so I went ahead and did that this morning.
As you would expect the results were identical...Works with TAG=apple and fails with TAG=apple.test
I just checked and the old original uses Python 3.11 and the failing new one uses Python 3.12.5
Maybe that is the issue?

Here is the log from the working version before any tuning done. I have added additional protocols besides companion to allow extra commands if needed...but these have been in there since the beginning.

   
 - D0:03:4B:1F:2C:09

:
 - Protocol: RAOP, Port: 7000, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
 - Protocol: Companion, Port: 49153, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
 - Protocol: AirPlay, Port: 7000, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
Existing ./scripts/firetv/directv/prebmitune.sh found, and will be preserved
Existing ./scripts/atv/spectrum/prebmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/bmitune.sh found, and will be preserved
Existing ./scripts/atv/spectrum/bmitune.sh found, and will be preserved
Existing ./scripts/firetv/directv/stopbmitune.sh found, and will be preserved
Existing ./scripts/atv/spectrum/stopbmitune.sh found, and will be preserved
Existing ./scripts/atv/spectrum/atvpair.sh found, and will be preserved
Existing directv.m3u found, and will be preserved
Existing dtvosprey.m3u found, and will be preserved
Existing dtvstream.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 livetv.m3u found, and will be preserved
Existing npo.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 youtubetv_shield.m3u found, and will be preserved
Existing youtubetv.m3u found, and will be preserved
[START] ah4c is starting
[ENV] Not loading env
[ENV] IPADDRESS                  192.168.1.101: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] Creating tuner             1
[ENV] ENCODER1_URL               http://192.168.1.41/live/stream3
[ENV] TUNER1_IP                  192.168.1.54
[ENV] CMD1                       
[ENV] TEECMD1                    
[ENV] PRE SCRIPT                 ./scripts/atv/spectrum/prebmitune.sh
[ENV] START SCRIPT               ./scripts/atv/spectrum/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/atv/spectrum/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/atv/spectrum/reboot.sh
[ENV] Creating tuner             2
[ENV] ENCODER2_URL               http://192.168.1.41/live/stream4
[ENV] TUNER2_IP                  192.168.1.55
[ENV] CMD2                       
[ENV] TEECMD2                    
[ENV] PRE SCRIPT                 ./scripts/atv/spectrum/prebmitune.sh
[ENV] START SCRIPT               ./scripts/atv/spectrum/bmitune.sh
[ENV] STOP SCRIPT                ./scripts/atv/spectrum/stopbmitune.sh
[ENV] REBOOT SCRIPT              ./scripts/atv/spectrum/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              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
[GIN-debug] HEAD   /favicon.ico              --> github.com/gin-gonic/gin.(*RouterGroup).StaticFile.func1 (2 handlers)
[GIN-debug] Loaded HTML Templates (11): 
	- stream.html
	- 
	- config.html

	- edit.html
	- editm3u.html

	- logs.html
	- routes.html
	- index.html

	- m3us.html
	- status.html
	- status_and_logs.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

On another note...I have been unable to manually push any buttons on my cheap apple replacement remotes...or manually send any commands through atvremote that will clear the "Start from beginning" dialog...SO APPLE MAY HAVE SCREWED UP THE APP!
I have tried power cycling and rebooting the ATV's and uninstalling and reinstalling the Spectrum App...May be time to experiment with a XUMO stream box and send ir commands if I can't get deep links to work...Wonder if they have adb debugging blocked on those boxes if you order one from the xumo website instead of spectrum directly...

Can't help with any of the rest of it, but I did run into the issue of the "start from the beginning" banner that not only doesn't go away, but also limits other remote commands. What I finally discovered was that somewhere along the line the spectrum app was updated in a way that causes it to lock up with shows that can "start from the beginning" if you just close the app. If you leave the app running (and streaming) it works just fine. Once it happens, the only way to clear it is to completely "quit" the app.

So I just leave one of the tuners running unless it is not used for more than a couple of hours. Otherwise I execute the remote command string to completely close the spectrum app on the ATV. Been working without a single issue for months now.

@chasut

I had set all the AppleTV's to not auto update apps once I had everything working back in March and had not had any issues....:slight_smile:
Then Spectrum decided UNLESS I update the apps it would refuse to let me play anything and just sit on the update app screen when you started Spectrum...

Have been doing some additional testing and have discovered like you said it only comes up when the show has the start from beginning option.
Also If I run Spectrum natively with the remote instead of the deeplinks from ah4c the "Start Over" comes up on those shows but then disappears after 5-8 seconds just like it should...

Here is the deeplink commmand I am using to launch the channel from ah4c:

atvremote --storage-filename /root/.android/.pyatv.conf -s $2 launch_app=spectrumTV://watch.spectrum.net/livetv/$1

Couple Questions:

  1. How are you leaving the tuner running when you are not watching it?
  2. What are the Python commands you are using to completely shut down the Spectrum app?

I have a little bit different setup, but it should work the same.
I use the "menu" command on the exit or stop tune. This returns to the spectrum main screen but does not exit the spectrum app. Unfortunately the stream keeps running behind the seen. But the HDMI tuner link to CDVR is closed and available for use. The upside is that any subsequent tune with deep link is super fast.

To completely close/quit the app I send the remote string through atvremote [home] + [delay 1 s] + [home repeat 2x] + [delay 0.5 s] + [left] + [delay 1s] + [up] + [home]

This replicates the double press home which brings up the app switcher, then swiping left to the first app in the queue (it is always spectrum as nothing else uses this tuner), then swiping up to close/quit the app and a final home to make sure everything is back to clean home menu in the ATV. Everything is ready for the next request for a tuner.

If you don't mind the bandwidth used by the stream always being running, just doing #1 is adequate to stop the issue with start from beginning banner. Or you can always completely quit the app and everything will work just fine. I just decided to add the additional logic because my tuners get quite a bit of activity and I like that leaving them "open" gives me a lightning fast tune during busy times or when channel surfing, but completely shut down at night or when they are idle.

Please share your experience. Always looking to improve and there are just a few of us using spectrum. That is why I lurk around these threads :wink:

btw, once you get the stuck "start from the beginning" banner, you MUST go through the quit sequence to reset things. At least I could not find anyway to fix it without completely quitting the app.

1 Like

@chasut
I can't tell you how many times you and @bnhf have saved me in this project...
Have no idea what Spectrum did that makes it screwy if using python/atvremote but work fine with the physical remote without completely quiting the app...I swear I even powered the units all the way off (unplugged) and they still messed up on the first atvremote tune after power up...
I can always count on Spectrum to screw up AND overcharge for a perfectly working system...lol

I have changed my stopbmitune.sh command for now to:

**

atvremote --storage-filename /root/.android/.pyatv.conf -s $1 home delay=250 home delay=5000 up delay=250 up delay=5000 home

**

This has worked perfectly more than a half dozen times so far so I think I will let it run for a little bit and make sure before I try to reduce the 5 sec delays down any. I really am not worried about the speed so much and would rather have something that just works.

In order to future proof... I will try and figure out using the tesseract-ocr when we figure out what is going on with new build. Hopefully this would allow me to only run the "reset" Spectrum app when needed and speed things up.

For sure, the power of the community! And please do share on tesseract progress. Hopefully we won't ever need it. But like you, I fear they will eventually add some stupid feature that throws a monkey wrench into this extremely cool project.