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

I did try that earlier, here it is just now - still not getting the adb commands to process. The only thing I noticed was that it divided out the channels with a \

[EXECUTE] Stderr: '+ channelID='"242B"'
+ specialID=242B
+ streamerIP=10.0.0.62:5555
+ streamerNoPort=10.0.0.62
+ adbTarget='adb -s 10.0.0.62:5555'
+ m3uName=directv.m3u
+ trap finish EXIT
+ main
+ matchEncoderURL
+ case "$streamerIP" in
+ encoderURL=http://10.0.0.60/4.ts
+ tuneChannel
+ [[ "242B" == \2\4\2 ]]
+ [[ "242B" == \2\4\2\A ]]
+ [[ "242B" == \2\4\2\B ]]
+ adb -s 10.0.0.62:5555 shell input text '"242B"'
+ finish
+ echo 'bmitune.sh is exiting for 10.0.0.62:5555 with exit code 0'

How about:

tuneChannel() {
  if [[ "$channelID" == \"242\" ]]; then
    $adbTarget shell input text "244"
    sleep 1
    $adbTarget shell input keyevent KEYCODE_CHANNEL_DOWN
    $adbTarget shell input keyevent KEYCODE_CHANNEL_DOWN
  elif [[ "$channelID" == \"242A\" ]]; then
    $adbTarget shell input text "244"
    sleep 1;
    $adbTarget shell input keyevent KEYCODE_CHANNEL_DOWN
  elif [[ "$channelID" == \"242B\" ]]; then
    $adbTarget shell input text "241"
    sleep 1
    $adbTarget shell input keyevent KEYCODE_CHANNEL_UP
    $adbTarget shell input keyevent KEYCODE_CHANNEL_UP
    $adbTarget shell input keyevent KEYCODE_CHANNEL_UP
  else
    $adbTarget shell input text $channelID
  fi
}

You nailed it! Seeing the adb commands come through now. Look like I need some fine adjustments with sleep timings - but easier to trace now.

As always - you've been a great help!!

Dumb question, but where do I go to make those changes?

There are no dumb questions - ever. It's in the bmitune file for whatever setup you're using. Usually in your /data/ah4c/scripts.

New bnhf/ah4c:latest (aka bnhf/ah4c:2024.07.29) pushed today.

Fixes/improvements include:

  • Reworked dtvdeeplinks scripts due to changes to the DirecTV app. Active audio is now confirmed before sending the deeplink, as the links were being ignored if the app wasn't already running.

  • Added Paris Extra 1 and Paris Extra 2 to dtvdeeplinks.m3u.

  • Updated dtvstream.m3u based on recent additions by @gfhartzell as described here:

Can you post your bmitune? Or where do I add it in the file?

You'll see the tuneChannel section in your bmitune file. You may need to fine tune the keyevents for your setup..

tuneChannel() {
  if [[ "$channelID" == \"242\" ]]; then
    $adbTarget shell input text "244"
    sleep 1
    $adbTarget shell input keyevent KEYCODE_CHANNEL_DOWN
  elif [[ "$channelID" == \"242A\" ]]; then
    $adbTarget shell input text "244"
    sleep 1;
    $adbTarget shell input keyevent KEYCODE_CHANNEL_DOWN
    $adbTarget shell input keyevent KEYCODE_CHANNEL_DOWN
  elif [[ "$channelID" == \"242B\" ]]; then
    $adbTarget shell input text "241"
    sleep 1
    $adbTarget shell input keyevent KEYCODE_CHANNEL_UP
    $adbTarget shell input keyevent KEYCODE_CHANNEL_UP
  else
    $adbTarget shell input text $channelID
  fi
}

Do you know the nbctve://live/ deep links for the paris extra 1/2 channels on the NBC app so I can tune to them with ADB?

Sorry, no.

New bnhf/ah4c:latest (aka bnhf/ah4c:2024.07.30) pushed with improvements to the dtvdeeplinks scripts.

Specifically, if the DTV app is already running, and it's been less than 4 hours since it was last used -- deeplinks will be sent as before. If either of those tests is false, the app will be launched and active audio detected first before sending the deeplink. This restores tuning speeds to previous (fast) levels.

Here's something that might help someone else. I'm not sure if it's due to my "cheapest I could find" EXVIST H.264/H.265 encoder or something else entirely, but sometimes (not always) channels DVR says it sees EOF soon after the actual video starts playing.

2024/08/05 15:54:28.454989 [SNR] Buffer statistics for "TV/Alma's Way/Alma's Way S01E11 2021-10-19 Socks for Sale Almas Anim 2024-08-05-1554.mpg": buf=0% drop=0%
2024/08/05 15:54:28.459657 [DVR] Job 1722898417-chKHET Alma's Way ended prematurely: 5m31.540346421s

As a result, it closes the connection, and ah4c runs the stop script. If it's a record job in channels DVR, it tries again and again and does not succeed (because it starts the turning process from the beginning each time).

There's a lot I don't know about MPEGTS, but I suspect that when the video starts playing either the software on my device or the firmware on the decoder says, "well, things have changed, so I'm going to end that stream and start a new one". I poked around a bit and tried a lot of things in my knuckle-dragging way. Without understanding what is actually going on, I have finally hit upon something that works around the problem.

The TSDuck toolkit is able to analyze and do a lot of things with transport streams. It's possible to use it as a very simple streaming server at the output of its pipeline. It can also be configured to overlook a few things, like an unexpected EOF. For the EOF thing, you can tell it to go back to the source and start reading again. With those things, I was able to construct a simple proxy that reads the stream out of my encoder and makes it available for chanels DVR (via ah4c). Since there is no transcoding, it doesn't use much resource.

If you have a similar problem or if you just want to see more details, there is a docker image on Docker hub at wjcarpenter/tsduck-proxy. The artifacts for building that docker image can be found in this GitLab repo: tsduck-proxy · main · WJCarpenter / tv scraps · GitLab

I was having some stability issues with my low-powered Android TV dongles. Since my primary use was to control the kodi app, and since kodi runs many places, I decided to see if I could use a Raspberry Pi running kodi as the tuning device for ah4c. (Spoiler: yes).

I've just submitted a PR for the linux/kodi/ family of scripts, which share a lot of logic with the chromecast/kodi_faves/ family of scripts.

In fact, one implementation detail might be of interest to others. I already had all of the logic in chromecast/kodi_faves/common.sh. Each of the prebmitune.sh, bmitune.sh, and stopbmitune.sh scripts are now identical and look like this:

#!/bin/bash
FLAVOR=linux
STUB=$(dirname $(dirname $(dirname $(realpath $0))))
if [[ -z "${STUB}" || "${STUB}" = "/" ]]; then exit 12; fi
COMMON_DIR=${STUB}/chromecast/kodi_faves
source ${COMMON_DIR}/common.sh
DO_THIS=$(basename ${0%.*})
${DO_THIS} "$@" 1>&2

That's for linux/kodi/. the chromecast/kodi_faves/ versions have "FLAVOR=android" instead. Logic in common.sh consults the FLAVOR and COMMON_DIR values.

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