ADBTuner: A "channel tuning" application for networked Google TV / Android TV devices

Well I think ADBTuner is a capable little app that can do a lot of things that haven't been explored yet. As a hobbyist I'd like to see what @Jubeejb can pull off.

But yeah, if someone is looking to automate their home on each channel change then being able to run whatever code they want inside the ah4c container will certainly make it easier to achieve that goal. edit: The DirecTV thing might be easier to figure out as well.

3 Likes

Set this variable in your docker environment:

KNOWN_STREAM_DEFAULT_TIMEOUT=8

It defaults to 8 seconds. You can lower it but you have to make sure enough time is allotted for for whatever post tune commands you have configured. 8 seconds is playing it safe, but it also gives the playback device a nice window to reconnect without having to load the content again.

I'm not quite sure what you are explaining about the rest. Is the Home Assistant plugin sending remote commands to the DirecTV box? Does it provide a REST interface?

1 Like

Hello, Thank you for your help. I'm not familiar with ah4c. As I noted previously I'm not a programmer. I integrate solutions using products the much smarter folks developed. As an example - I use Home Assistant not for home automation but because it has an extensive library of plugins that provide simple interfaces to a wide variety of devices and software - such as Node-Red. I use Node-Red and its large library of nodes and functions that let me interface products like ADBtuner with products like the Directv device. I know just enough JSON and YAML to pass values between the products. I run Docker on and RPI and manage the environment using Portainer. This is my way of saying - I have no idea where or how to set that timeout variable in my docker environment, but it certainly appears to a solution for my challenge. Can you tell me where/how I set that variable?

As for the issue regarding the DirecTV device, yes I can provide the plugin with inputs that can send commands to the Directv device like a remote control without using ADB. Like tune to channel 202 and the device tunes to channel 202. Thats all I know about the plugin. So to make this happen using ADBtuner I modified a tuning configuration to send an HTTP POST command such as "http://192.XXX.XXX.59:1880/user?||TARGET_URL_OR_IDENTIFIER||" to my Node-Red server. When it's received by Node-Red I scan and search the header information for user? which provides the channel number, I move the data to an interface node for Home Assistant that directs the command and channel number to the device. For all this to happen I only needed to provide one line of JSON.
--- {"media_content_id": payload, "media_content_type": "channel"} --- Although this may sound complicated - the solution tunes the device in 1 second. This simple solution would work well in ADBtuner if I could add the DirecTV device without having to enable ADB or a need for a Package Name as it's not relevant to tune the DirecTV device. Is that doable? Thanks so much for all your assistance.

1 Like

Not to hijack the thread, but we actually have a minimal install for AH4C now that is currently in beta and just about ready to go. That I believe is deployable through Olive Tin for Channels, aka Project OneClick. It walks you through a setup wizard, and then there's just a settings page to configure everything, scripts and such, that allow you to tune. If you're using Osprey boxes, which it sounds like you might be, there are scripts that just work for those out of the box. You don't have to do much. And you can pull in all of your channels into an M3U using the action and project one click to grab all those. This beta that I've been working on has a goal of making it as easy as possible to get up and running for new users. So, I would just pick the tool that works best for you. If it comes to tuning by channel number, people have been doing it with AH4C for a couple of years now with very few issues. If you have any questions, feel free to ask in the dedicated thread to not hijack this one, of course.

1 Like

Thank you so much. I'll check it out. It does appear it might be what I'm looking for.

2 Likes

Thank you turtletank, I did manage to figure out how to change the variable. Any assistance with my adb problem is greatly appreciated.

You have to enable developer options and USB debugging. There is no way around ADB with this tool or ah4c.

1 Like

@turtletank Thank you so much for this project. I love it! If you have a tip jar, point be to it.

Here's my ADBTuner tuner configuration for the Spectrum app on a Fire Stick 4k Max. I'm still working on it, but it's a better start than anything else AI and I have found. The current FS4K Max still has the ADB interface we need. The new cheap HD has the new OS without ADB. Not sure which other versions have which OS, but the current Max is a safe choice.

{
  "name": "Spectrum Tune Only Configuration ADBTuner example tuning commands",
  "author": "Dan",
  "version": "0",
  "description": "Spectrum double DPAD_UP focus, and discrete keyevent timing.",
  "uuid": "b3ecf82b-41c2-4695-9720-8c5e0d9b65f9",
  "global_options": {
    "wait_for_video_playback_detection": true,
    "use_fixed_delay": false,
    "fixed_delay_seconds": 0,
    "wait_seconds_before_playback_detection": 15,
    "wait_after_post_playback_start_commands_seconds": 5
  },
  "pre_tune_commands": [
    {
      "ADB": {
        "commands": [
          "input keyevent KEYCODE_MEDIA_STOP",
          "adbtuner_open_app ||TARGET_PACKAGE_NAME||"
        ]
      }
    },
    {
      "ADB": {
        "command": "sleep 2"
      }
    },
    {
      "ADB": {
        "command": "input keyevent KEYCODE_DPAD_DOWN"
      }
    },
    {
      "ADB": {
        "command": "input keyevent KEYCODE_ENTER"
      }
    }
  ],
  "tune_commands": [
    {
      "ADB_NUMBER_INPUT_SEQUENCE": {
        "number": "||TARGET_URL_OR_IDENTIFIER||",
        "input_delay_seconds": 0.25
      }
    },
    {
      "HTTP": {
        "method": "GET",
        "action": "http://||TARGET_DEVICE_IP_ADDRESS||/tuned",
        "timeout": 5
      }
    }
  ],
  "tune_match_text_commands": [],
  "post_playback_start_commands": [],
  "post_tune_commands": [
    {
      "ADB": {
        "command": "input keyevent KEYCODE_HOME"
      }
    }
  ],
  "timed_keep_active_commands": []
}

I have ADBTuner setup to record F1 on Apple TV (on an Amazon FireStick) via FruitDeepLinks. However, it gets stuck on this screen rather than starting the event:

Looking at the logs it appears as though it is not recognizing the buttons on screen and not clicking through:

Starting tune match text monitoring. Match commands: [{'match_text': ['watch', 'live', 'mls', 'mlb', "don't allow"], 'commands': [{'type': 'ADB', 'command': 'input keyevent KEYCODE_DPAD_CENTER'}], 'start_checking_after_seconds': 5}] 
Tuning completed after 12.4 seconds. Display was None, application (com.apple.atve.amazon.appletv) was running. 
On screen text: '“tv formula 1 - baku city circuit baku  =d -  a et ee  ee af ey ee ete wt soy' 
Text match result: Text to match: ['watch', 'live', 'mls', 'mlb', "don't allow"]. Matches found: None. 
On screen text: '“tv formula 1 - baku city circuit baku  c= -  sn er a sw (aes ee' 
Text match result: Text to match: ['watch', 'live', 'mls', 'mlb', "don't allow"]. Matches found: None. 
On screen text: 'sa ae == a ae we os awe =' 
Text match result: Text to match: ['watch', 'live', 'mls', 'mlb', "don't allow"]. Matches found: None. 
On screen text: '“tv formula 1 - baku city circuit baku  =d -  a et ee  ee af ey ee ete wt soy' 

@bhnf suggested in the OliveTin thread where we were originally discussing getting this all working that maybe there are some tweaks that could be made to Tesseract OCR to more accurately read the text in those buttons @turtletank

1 Like

Thanks for the heads up. I will take a look.

1 Like

I've got something coming soon for Spectrum that will make managing it in ADBTuner and Roku Bridge much, much, much easier, but in the meantime you can see the configurations I'm using:

Here is my Config for DirecTV that works with FireTV and ONN 4k boxes.

{
  "name": "DirecTV for ONN",
  "author": "Anvil",
  "version": "1",
  "description": "Tunes DirecTV for ONN and FireTV.",
  "uuid": "c4a41390-263c-45fc-ad2b-7854e6b09bc2",
  "global_options": {
    "wait_for_video_playback_detection": false,
    "use_fixed_delay": true,
    "fixed_delay_seconds": 2,
    "check_for_and_clear_whos_watching_prompts": false,
    "wait_after_post_playback_start_commands_seconds": 0
  },
  "pre_tune_commands": [],
  "tune_commands": [
    "am start -S -W -n '||TARGET_PACKAGE_NAME||'/$(cmd package resolve-activity -a android.intent.action.MAIN '||TARGET_PACKAGE_NAME||' | awk -F= '/name=/{print $2; exit}') -a android.intent.action.VIEW -d '||TARGET_URL_OR_IDENTIFIER||'",
    "sleep 5; am start -W -n '||TARGET_PACKAGE_NAME||'/$(cmd package resolve-activity -a android.intent.action.MAIN '||TARGET_PACKAGE_NAME||' | awk -F= '/name=/{print $2; exit}') -a android.intent.action.VIEW -d '||TARGET_URL_OR_IDENTIFIER||'"
  ],
  "post_playback_start_commands": [],
  "post_tune_commands": [
    "input keyevent KEYCODE_MEDIA_STOP",
    "input keyevent KEYCODE_HOME"
  ],
  "timed_keep_active_commands": [
    {
      "run_every_minutes": 60,
      "commands": [
        "input keyevent KEYCODE_MEDIA_PLAY"
      ]
    }
  ]
}

@turtletank I just set up a separate instance of ADBTuner to test with Chromecast and the beta feature to automatically enable ADB. I don't know how you pulled that off, but it works. Its like Witchcraft.

Its been a while since I updated ADBTuner. Some major progress has taken place.

Thankyou!

1 Like

I don't think this is an adbtuner issue, but seems like the right place to ask.

I setup my instance last month, just for the ESPN broadcast channels:

  • LinkPi ENC1-V3P with latest firmware + Onn 4K Plus
  • adbtuner 20260815-1 installed on Synology NAS
  • latest Configuration and ESPN Stations imported

It works but I regularly miss recordings due to some glitch with the ESPN app. For example just now I tried to tune into ESPN using the Channels app on my main TV. It follows the script perfectly up to hitting the "Watch Live" button, but then I get "There was an error playing this video" and it's stuck. I then tried to tune ESPN2 - again everything works up to the "Watch Live" button, but then I got "This channel is not part of your package" (which it is). I then went to my desktop, connected my monitor to the Onn and I'm able to watch both channels just fine. I reconnect the ONN to the LinkPi, go back to my TV and everything is fine. In other cases I've seen everything work, but the app just takes me to a gray screen. I would say my success rate for recordings was 100% initially but is now closer to 50%.

Anyone having a similar experience? Any suggestions? Thanks.

1 Like

Absolutely. The same game changer I talked about in this post is now available for the ESPN linear channels. It's very, very nice -- and will put the issues you're describing above in the rearview mirror:

1 Like

A post was merged into an existing topic: AndroidHDMI for Channels (ah4c): A virtual channel tuner using HDMI Encoder(s) + streaming stick(s)

A post was merged into an existing topic: AndroidHDMI for Channels (ah4c): A virtual channel tuner using HDMI Encoder(s) + streaming stick(s)

@turtletank, saw a weird issue. Not sure if it is a one-off or what, but something happened and ADBTuner thought that all tuners were full when they were all open. I traced it back in the logs to something that seemed to start the day before and went on for 16 hours:

2026-10-10 15:37:36.328 | 2026-10-10 15:37:36.314 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reconnected after a dropped connection.
2026-10-10 15:38:45.070 | 2026-10-10 15:38:45.069 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reconnected after a dropped connection.
2026-10-10 15:38:51.289 | 2026-10-10 15:38:51.288 - lib.adb - [Pool 1] ADB: 10.255.1.168 - command failed, device is not responding. Check for approval popup on device.
2026-10-10 15:38:56.211 | 2026-10-10 15:38:56.210 - lib.adb - Reading from 10.255.1.168:5555 timed out (2 seconds)
2026-10-10 15:38:56.212 | 2026-10-10 15:38:56.211 - lib.adb - [Pool 1] ADB: Connection error. Device may be waking up. Trying again.
2026-10-10 15:38:57.213 | 2026-10-10 15:38:57.213 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reachable but not connected, waiting 10s before the next attempt.
2026-10-10 15:39:31.121 | 2026-10-10 15:39:31.120 - lib.adb - [Pool 1] ADB: 10.255.1.168:5555 unreachable, skipping connect.
2026-10-10 15:39:31.133 | 2026-10-10 15:39:31.132 - lib.adb - [Pool 1] ADB: 10.255.1.168:5555 is reachable again.
2026-10-10 15:39:34.119 | 2026-10-10 15:39:34.119 - lib.adb - Reading from 10.255.1.168:5555 timed out (2 seconds)
2026-10-10 15:39:34.119 | 2026-10-10 15:39:34.119 - lib.adb - [Pool 1] ADB: Connection error. Device may be waking up. Trying again.
2026-10-10 15:39:35.119 | 2026-10-10 15:39:35.119 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reachable but not connected, waiting 20s before the next attempt.
2026-10-10 15:40:08.948 | 2026-10-10 15:40:08.947 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reconnected after a dropped connection.
2026-10-10 15:46:37.925 | 2026-10-10 15:46:37.914 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reconnected after a dropped connection.
2026-10-10 15:46:41.190 | 2026-10-10 15:46:41.189 - lib.adb - [Pool 1] ADB: 10.255.1.168 - command failed, device is not responding. Check for approval popup on device.
2026-10-10 15:46:41.365 | 2026-10-10 15:46:41.364 - lib.adb - Unknown command: 1701322796 = 'b', he'' (arg0 = 1952999273, arg1 = 909193789, msg = 'b', height=2160, fps=23.97'')
2026-10-10 15:46:41.366 | 2026-10-10 15:46:41.364 - lib.adb - [Pool 1] ADB: Command error
2026-10-10 15:47:13.314 | 2026-10-10 15:47:13.313 - lib.adb - Unknown command: 892481590 = 'b'6025'' (arg0 = 1818304556, arg1 = 1852990836, msg = 'b'6025, alternativeRefresh'')
2026-10-10 15:47:13.314 | 2026-10-10 15:47:13.314 - lib.adb - [Pool 1] ADB: Command error
2026-10-10 15:47:13.314 | 2026-10-10 15:47:13.314 - lib.adb - Unknown command: 1702125906 = 'b'Rate'' (arg0 = 1566260595, arg1 = 2065706109, msg = 'b'Rates=[]}, {id=181, widt'')
2026-10-10 15:47:13.314 | 2026-10-10 15:47:13.314 - lib.adb - [Pool 1] ADB: Command error
2026-10-10 15:47:45.297 | 2026-10-10 15:47:45.296 - lib.adb - Unknown command: 942882152 = 'b'h=38'' (arg0 = 539766836, arg1 = 1734960488, msg = 'b'h=3840, height=2160, fps'')
...
2026-10-11 07:25:27.936 | 2026-10-11 07:25:27.935 - lib.adb - [Pool 1] ADB: Command error
2026-10-11 07:25:27.936 | 2026-10-11 07:25:27.935 - lib.adb - Unknown command: 1030975590 = 'b'fps='' (arg0 = 808333366, arg1 = 808464432, msg = 'b'fps=60.000004, alternati'')
2026-10-11 07:25:27.936 | 2026-10-11 07:25:27.935 - lib.adb - [Pool 1] ADB: Command error
2026-10-11 07:25:58.251 | 2026-10-11 07:25:58.250 - lib.adb - [Pool 1] ADB: 10.255.1.168 - reconnected after a dropped connection.
2026-10-11 07:49:10.536 | 2026-10-11 07:49:10.534 - tuner_management - Caching installed apps list for all tuners
2026-10-11 07:49:11.106 | 2026-10-11 07:49:11.106 - tuner_management - Cached installed apps for tuner Link Pi ENC1-V3 (1).
2026-10-11 08:50:02.117 | 2026-10-11 08:50:02.087 - tuner_management - Caching installed apps list for all tuners
2026-10-11 09:25:25.678 | 2026-10-11 09:25:25.660 - stream - [Tune Cm32kCLdnCJBgFEBvd2kLh] localhost:7968 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
2026-10-11 09:25:26.599 | 2026-10-11 09:25:26.599 - stream - [Tune (Cm32kCLdnCJBgFEBvd2kLh)] No active tuners found for NFL Network HD. Reserving a new tuner.
2026-10-11 09:25:26.615 | 2026-10-11 09:25:26.614 - tuner_management - [Tune Cm32kCLdnCJBgFEBvd2kLh] Attempting to reserve tuner for: ['com.fastchannels.player'].
...
2026-10-11 09:25:36.759 | 2026-10-11 09:25:36.758 - stream - [Tune (Cm32kCLdnCJBgFEBvd2kLh)] No tuners available for: ['com.fastchannels.player'].
2026-10-11 09:25:40.064 | 2026-10-11 09:25:40.063 - stream - [Tune 5QEgXMxZRfPVJS729v6WHS] localhost:7968 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
...

It didn't matter the method or what I tried to tune to, it was all the same result. I only fixed it by force restarting the containers, which had been running for 15 days at that point.

1 Like

Sorry about that. Thanks for the heads up. I will have a fix for this in the next release.