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

Thanks

Hi !
Questions ,

  1. can i use this app to tune channels with deeplinks ? To use and open channel in Kodi from m3u. Any guide for that type of setup ?

  2. Will this app force the app to close/ open on android tv before tuning? I only use one app

  3. If used with a android based sat-tuner , can ah4c be set to only send key 1-10 etc send number 1 to tune to channel 1(Works on my remote today) So no need to open any android app only send key numbers . Thanks !

Yes on deeplinks, and ah4c works in VLC, so it should work in Kodi too. With ah4c you'd have a M3U available at a URL -- so look for a guide on using an M3U with Kodi.

ah4c requires some scripting to make the magic happen, which can be pretty basic or more advanced, depending on your combination of needs. You can leave an app running all the time if you like, but you'd probably want to account for situations where the app isn't responding -- e.g. force close and relaunch.

Sure, that's easily done. One person using ah4c uses some DirecTV Osprey boxes which sound similar in their operation -- i.e., no app to launch, with support for number based tuning.

Sorry if i was not clear , looking for ah4c deeplink guide / example. Not Kodi guide :relaxed:

This guy ended up switching to ADBTuner, as it was a better fit for what he was trying to do. However, check out his linked blog post as it does give the basics for ah4c, and he was using some very simple scripts utilizing deeplinks.

Ok, now that I have figured out how to get to all the live channels on the app, do I edit the bmitune scripts and rename them? For example this is how I would get to channel 1
input keyevent 97 home
input keyevent 20 keypad down
input keyevent 23 center
input keyevent 22 right
input keyevent 21 left
input keyevent 23 center / enter
And then I assume most everything else in the script is common to all apps? Like starting it and stopping it etc?

I tested it with a direct adb connection to my computer using the adb commands.

1 Like

You'll find there are different levels of complexity in scripting based on the specific streamer/app combo. Generally start with something simple, and then add-on as required.

You should be able to plug in your package name and package launch into the prebmitune.sh script I posted above.

Then looking at bmitune.sh, if you need different adb key sequences for each channel, you'll probably want to treat them each as a "special channel" and use the specialChannels() function to do the tuning.

The activeAudioCheck() function works great for DirecTV, as I don't start any "tuning" until the app is launched and audio is heard -- which may or may not be relevant to your app.

The main() function is what calls everything, so you can comment-out or re-arrange functions as needed for your situation.

You'll need to create an M3U as well, and keep in mind that whatever number(s) or letter(s) you use at the end of the stream URL in the M3U will be passed to the bmitune script as an argument ($1), and the hostname:port or IP:port of the streaming stick will be passed to all 3 scripts.

You should store your version of each script in the scripts directory under a subdirectory that uses the name of your streaming device (firetv for example), and then another subdirectory under that with the name of the streaming app (directv for example). This becomes the value you should use for the STREAMER_APP environment variable (scripts/firetv/directv for example)

Thank you. I will keep working on this, I'm pretty sure it will end up working properly, once I'm done I can post my scripts for someone else that might possibly need it.
I appreciate the help.

Docker newbe question . I want to browse ah4c files on my nas : /volume1/Docker/ah4c
How should i edit this file then ?

version: '3.9'
services:
  ah4c:
    image: bnhf/ah4c:${TAG}
    container_name: ah4c
    hostname: ah4c
    dns_search: ${DOMAIN} # Specify the name of your LAN's domain, usually local or localdomain
    ports:
      #- 5037:5037 # Port used by adb-server
      - 7654:7654 # Port used by this androidhdmi-for-channels proxy
      - 7655:8000 # Port used by ws-scrcpy
    environment:
      - IPADDRESS=${IPADDRESS} # Hostname or IP address of this androidhdmi-for-channels extension to be used in M3U file (also add port number if not in M3U)
      - NUMBER_TUNERS=${NUMBER_TUNERS} # Number of tuners you'd like defined 1, 2, 3 or 4 supported
      - TUNER1_IP=${TUNER1_IP} # Streaming device #1 with adb port in the form hostname:port or ip:port
      - TUNER2_IP=${TUNER2_IP} # Streaming device #2 with adb port in the form hostname:port or ip:port
      - TUNER3_IP=${TUNER3_IP} # Streaming device #3 with adb port in the form hostname:port or ip:port
      - TUNER4_IP=${TUNER4_IP} # Streaming device #4 with adb port in the form hostname:port or ip:port
      - ENCODER1_URL=${ENCODER1_URL} # Full URL for tuner #1 in the form http://hostname/stream or http://ip/stream
      - ENCODER2_URL=${ENCODER2_URL} # Full URL for tuner #2 in the form http://hostname/stream or http://ip/stream
      - ENCODER3_URL=${ENCODER3_URL} # Full URL for tuner #3 in the form http://hostname/stream or http://ip/stream
      - ENCODER4_URL=${ENCODER4_URL} # Full URL for tuner #4 in the form http://hostname/stream or http://ip/stream
      - STREAMER_APP=${STREAMER_APP} # Streaming device name and streaming app you're using in the form scripts/streamer/app (use lowercase with slashes between as shown)
      - CHANNELSIP=${CHANNELSIP} # Hostname or IP address of the Channels DVR server itself
      - ALERT_SMTP_SERVER=${ALERT_SMTP_SERVER} # The domainname:port of the SMTP server you'll be using like smtp.gmail.com:587. This is for sending ah4c alerts if tuning fails.
      - ALERT_AUTH_SERVER=${ALERT_AUTH_SERVER} # The auth server for the e-mail you'll be using like smtp.gmail.com
      - ALERT_EMAIL_FROM=${ALERT_EMAIL_FROM} # The e-mail address you'd like your ah4c failure alert e-mails to show as being from.
      - ALERT_EMAIL_PASS=${ALERT_EMAIL_PASS} # Gmail and Yahoo both support the creation of app-specific e-mail passwords, and this is the way to go! It's NOT recommended to use your everyday e-mail password.
      - ALERT_EMAIL_TO=${ALERT_EMAIL_TO} # The e-mail address you'd like your alert e-mails sent to.
      #- ALERT_WEBHOOK_URL="" # For advanced users, tuning failure alerts can be sent via a webhook.
      - LIVETV_ATTEMPTS=${LIVETV_ATTEMPTS} # For FireTV Live Guide tuning only, set maximum number of attempts at finding the desired channel
      - CREATE_M3US=${CREATE_M3US} # Set to true to create device-specific M3Us for use with Amazon Prime Premium channels -- requires a FireTV device
      - TZ=${TZ} # Your local timezone in Linux "tz" format
    volumes:
      - /${HOST_DIR}/ah4c/scripts:/opt/scripts # pre/stop/bmitune.sh scripts will be stored in this bound host directory under streamer/app
      - /${HOST_DIR}/ah4c/m3u:/opt/m3u # m3u files will be stored here and hosted at http://<hostname or ip>:7654/m3u for use in Channels DVR - Custom Channels settings
      - /${HOST_DIR}/ah4c/adb:/root/.android # Persistent data directory for adb keys
    restart:

There's not much you'd need to edit in the docker-compose itself (with perhaps the exception of the ports), but rather it's the environment variables you need to concentrate on:

These are the provided examples:

TAG=latest
DOMAIN=localdomain
IPADDRESS=htpc6:7674
NUMBER_TUNERS=1
TUNER1_IP=firestick-rack1:5555
ENCODER1_URL=http://encoder_00000/0.ts
STREAMER_APP=scripts/firetv/directv
CHANNELSIP=media-server6
ALERT_SMTP_SERVER=smtp.gmail.com:587
ALERT_AUTH_SERVER=smtp.gmail.com
[email protected]
ALERT_EMAIL_PASS=yourgmailapppassword
[email protected]
LIVETV_ATTEMPTS=25
CREATE_M3US=false
TZ=US/Mountain
HOST_DIR=/data

In general, use the comments (which are after the #) in the docker-compose to help you define these variables, but to your specific question -- setting this variable:

HOST_DIR=/volume1/Docker

would result in the scripts, M3Us and ADB data files being browsable in the folder you referenced above.

1 Like

By editing the docker compose file, and restarting it, will that automatically load all the new configuration in the docker compose?
Also, are there any more special channel examples?
Thanks

The docker-compose should require little to no editing -- it's the environment variables that need your attention. Stop your stack in Portainer, then edit the environment variables, then start the stack again and choose re-pull and re-deploy if you want to redownload the docker container:

This "case" statement from the activeAudioCheck function is an example of a way you could do your tuning. Each $specialID would be a channel number passed into the script (via the URL used in the M3U -- whatever you use after the last "/" is passed to the bmitune.sh script). Then between the ")" and the ";;" would be your adb commands using the same format shown:

$adbTarget shell input keyevent KEYCODE_DPAD_LEFT

A "break" to exit the function after the channel is matched and tuning is done would be used instead of "exit 1". Expand the number of cases to match the number of channels you have. The "*)" is for anything that doesn't match, and could have an "echo" error message and an "exit 1" to exit the script.

Thanks ! That worked. IĀ“looking at scripts and m3us but i`m not sure how to go on.
Would meecool/youtubetv be a good starting point to open my app "Allente" and tune deeplinks ?
If so any chance you could give me some example for 2 channels with m3u and bmitune.sh based on the following info:

My apps name="allente.b2c.tvclient"
Channel 1 (name SVT1) and has the following deeplink: allente://play/live/20001
Channel 2 (name SVT2) and has the following deeplink: allente://play/live/20002

And then how would my m3u look for above channels?
Streamer ip 192.168.0.100
ah4c ip 192.168.0.101

Sure, you could use mecool/youtubetv as a starting point. These are very simple versions of the scripts needed, but they might be fine -- and would get you familiar with the concepts. Most anything else you could add, would be to deal with particular issues related to your specific streaming app.

prebmitune.sh would probably be fine as is:

#!/bin/bash
#prebmitune.sh for android/yttv
STREAMERIP="$1"
ADB_CMD="adb -s $STREAMERIP shell"
WAKE="input keyevent KEYCODE_WAKEUP"
HOME="input keyevent KEYCODE_HOME"
adb connect $STREAMERIP
$ADB_CMD $HOME

bmitune.sh would need to be modified. You'd want the line after "#Send the command" to mirror what you've done in your testing to launch the app and tune to the channel. Given your particular deep link, you'd want the URL in the M3U to send 2000x as your channel number. The command might look something like below, once you add the correct value of APP_LAUNCH:

#!/bin/bash
#bmitune.sh for android/yttv
STREAMERIP="$2"
ADB_CMD="adb -s $STREAMERIP shell"
CHANNEL=\""$1\""
APP_LAUNCH="com.google.android.youtube.tvunplugged"
APP_NAME="allente.b2c.tvclient"

#Send the command
$ADB_CMD am start -a android.intent.action.VIEW -d allente://play/live/$CHANNEL -n $APP_LAUNCH/$APP_NAME

stopbmitune.sh could be something like this:

#!/bin/bash
#stopbmitune.sh for android/yttv
STREAMERIP="$1"
ADB_CMD="adb -s $STREAMERIP shell"
SLEEP="input keyevent KEYCODE_SLEEP"
HOME="input keyevent KEYCODE_HOME"
$ADB_CMD $HOME
$ADB_CMD $SLEEP

And your M3U should be setup along these lines, though you should add your channel's specific Gracenote Station IDs, between the quotes after tvc-guide-stationid:

#EXTM3U
#EXTINF:-1 channel-id="SVT1" tvc-guide-stationid="",SVT1
http://{{ .IPADDRESS }}/play/tuner/20001
#EXTINF:-1 channel-id="SVT2" tvc-guide-stationid="",SVT2
http://{{ .IPADDRESS }}/play/tuner/20002

Setting this up for the first time, trying it out with just 1 tuner for now - using Fubo as the source, Linux, Docker w/ Portainer. Couple of issues that I ran into:

  1. The main issue was the 3 scripts were missing in /scripts/firetv/fubo. Downloaded them and copied them up and changed permissions fixed it. Concerned that if they get updated and I do a new pull & deploy - they won't actually get updated.

  2. Adding a channel for testing, I just added it to the existing m3u that came installed and just disabled the others. When adding it to cdvr - gave me messages the m3u was incorrect. Looking at the file it appears the existing channels that I disabled are not commented out correctly - or maybe it's not the way it should work. More of fyi than anything as a new m3u with only my test channel worked fine. Be a nice feature if it would work to be able to toggle channels - when switching channels from TVE or ADBtuner as hings change.

Otherwise - it went very smooth and works great. Tunes much faster. Hope this fixes my issues with Fubo I'm having with ADbtuner.

The last silly thing - can't seem to get the TZ for timestamps to work. Using TZ=America/New_York - same as my other stacks.

3 more tuners to go...

Right you are -- I see they are missing from my build system. I'll fix that shortly. Any updates to the scripts are probably going to be coming from you, since it would seem you're the only one using this particular combination atm. :slight_smile:

I adapted my firetv/directv scipts for Fubo somewhere along the way, but haven't looked at them again since my Fubo trial expired -- glad to hear they still work.

Comments in M3U files are not particularly intuitive, since the "#" has another purpose. I don't use comments often in M3Us, but my recollection is that #<space> is a comment, but # followed by any other character is not.

Also somewhere along the way, I switched to a build container that doesn't include tzdata without realizing it -- I'll add it to the next build, along with those scripts.

Thanks for the quality feedback!

Which HDMI encoder are you using here? Or better yet, you have a better breakdown to what all your using in the rack patch panel? I'm interested in your particular ENCODER as I would then be able to plug multiple HDMI devices into including a Chromecast and Firestick. Thanks

Here's the breakdown. Some items I had on-hand, but everything can be sourced from Amazon -- assuming you're in the US of course:

URayCoder H265 H264 4K HDMI Video Streaming Encoder IPTV for HDMI to RTSP RTMP HLS M3U8 UDP SRT ONVIF, HDMI to IP Live Broadcast Streamer Converter Hardware:
https://www.amazon.com/gp/product/B07TKMPCZH

AC Infinity Vented Cantilever 1U Universal Rack Shelf, 10" Deep, for 19ā€ equipment racks:
https://www.amazon.com/gp/product/B01C9KYUG8

C2G Legrand 16 Port Patch Panel, Ethernet Keystone Panel with Blank 1U Keystone:
https://www.amazon.com/gp/product/B0002GWPTG

RiteAV USB 3.0 Keystone Jack A-A Female to Female - Black:
https://www.amazon.com/gp/product/B075DGXM9R

VCE HDMI Keystone Jack 6-Pack | 4K HDMI Female to Female Adapter | HDMI Coupler Snap-in | for Keystone Wall Plate | Black:
https://www.amazon.com/gp/product/B07214QPBD

Intellinet Cat.6 UTP Keystone Coupler:
https://www.amazon.com/gp/product/B00173ROGM

VCE 20-Pack Blank Keystone Jack Inserts | UL Listed | for Keystone Wall Plate and Patch Panel | Black:
https://www.amazon.com/VCE-20-Pack-Keystone-Inserts-Wallplate/dp/B07G8D1WYC

Monoprice Cat6A Ethernet Patch Cable - RJ45, Stranded, STP, 5-Pack, 36AWG, 0.5 Feet, Black - SlimRun Series:

Monoprice Cat6A Ethernet Patch Cable - Snagless RJ45 | 550Mhz | 10G | UTP | Pure Bare Copper Wire | 30AWG | 10-Pack | 1 Feet | Black | SlimRun Series:
https://www.amazon.com/gp/product/B01BGV2TAA

UCTRONICS Upgraded Ethernet and Power for Raspberry Pi Zero, Micro USB to Ethernet/PoE Adapter for Fire TV Stick, Chromecast, Google Mini, Wyze Cams and More, IEEE 802.3af Compliant:
https://www.amazon.com/gp/product/B0B9ZLVGJ4

REVODATA Gigabit PoE Splitter 12V 2A Output with IEEE 802.3af/at Standard Compliant 10,100,1000Mbps Power Over Ethernet Splitter Adapter for Security Camera CCTV Surveillance 5.5x2.1mm DC PlugPS5712TG:
https://www.amazon.com/gp/product/B08HS4NT13

CableCreation [2-Pack Micro USB to Micro USB Cable Short, USB2.0 Micro-B Male to Male OTG Cable Works for DJI Spark and Mavic, PS4, Android Phone and Tablet, DAC and More,8 inch / 20CM:
https://www.amazon.com/gp/product/B07CKW6RYD

ELECTOP 2 Pack USB 2.0 A Male to USB Micro Female Adapter Converter:
https://www.amazon.com/gp/product/B015PC65EM

Mediabridgeā„¢ Flex Series HDMI Cable (1 Foot) Supports 4K@50/60Hz, High Speed, Hand-Tested, HDMI 2.0 Ready - UHD, 18Gbps, Audio Return Channel:
https://www.amazon.com/gp/product/B007PESCCC

Amazon Fire TV Stick 4K Max streaming device | Wi-Fi 6 | Alexa Voice Remote (includes TV controls):
https://www.amazon.com/gp/product/B08MQZXN1X

I think that's everything. You'll need to work out the quantities based on the number of sticks you'll be using. The only change I'd make building now is to use the 2nd generation FireStick 4K Max devices. Obviously not a budget build (few of my projects are :slight_smile:), but it's been rock-solid since day one. Nothing has been rebooted, or touched, in many months.

Using this since my last post and getting down to 1 issue that I can't resolve.
Watching or recording, every 2nd subsequent request to the same device - is washed out. Like a dimmed version - not a normal bright display. Either watching live and it records that way. Hard to see. It's taken a few days troubleshooting with no answer, its very repeatable.

I thought it was a Firestick issue, so I swapped out to an ONN stick same issue. Swapped out to a different Firestick model. Changed ports on the encoder, rebooted things 1 at a time - testing step by step, reboot everything at once, reset device(s) to factory - nothing changes. I have a new test server spun up - same problem. When watching in VLC - you can see it as well. I'm not sure how else to test this out.

I copied out the logs to separate txt files and looked at them side by side but nothing jumps out to me. Here is the bad one - ran about 4 minutes after the good one. I can post the original if it will help..

2024-02-26T15:04:23.488102487Z Attempting network tune for device http://10.0.0.60/0.ts 10.0.0.64:5555 32639
2024-02-26T15:04:23.546138116Z [EXECUTE] Running [./scripts/firetv/fubo/prebmitune.sh 10.0.0.64:5555 32639]
2024-02-26T15:04:23.678067341Z [EXECUTE] Stdout: 'already connected to 10.0.0.64:5555
2024-02-26T15:04:23.678118801Z prebmitune.sh is exiting for 10.0.0.64:5555 with exit code 0
2024-02-26T15:04:23.678128258Z '
2024-02-26T15:04:23.678134573Z [EXECUTE] Stderr: '+ streamerIP=10.0.0.64:5555
2024-02-26T15:04:23.678140837Z + streamerNoPort=10.0.0.64
2024-02-26T15:04:23.678145690Z + adbTarget='adb -s 10.0.0.64:5555'
2024-02-26T15:04:23.678150523Z + mkdir -p 10.0.0.64
2024-02-26T15:04:23.678155306Z + trap finish EXIT
2024-02-26T15:04:23.678160437Z + main
2024-02-26T15:04:23.678165240Z + adbConnect
2024-02-26T15:04:23.678170073Z + adb connect 10.0.0.64:5555
2024-02-26T15:04:23.678174945Z + local -i adbMaxRetries=2
2024-02-26T15:04:23.678179828Z + local -i adbCounter=0
2024-02-26T15:04:23.678184571Z + true
2024-02-26T15:04:23.678189364Z + adb -s 10.0.0.64:5555 shell input keyevent KEYCODE_WAKEUP
2024-02-26T15:04:23.678194386Z + local adbEventSuccess=0
2024-02-26T15:04:23.678199358Z + [[ 0 -eq 0 ]]
2024-02-26T15:04:23.678204151Z + break
2024-02-26T15:04:23.678208795Z + finish
2024-02-26T15:04:23.678213826Z + echo 'prebmitune.sh is exiting for 10.0.0.64:5555 with exit code 0'
2024-02-26T15:04:23.678218898Z '
2024-02-26T15:04:23.678223750Z [EXECUTE] Finished running ./scripts/firetv/fubo/prebmitune.sh in 132.016672ms
2024-02-26T15:04:23.678747023Z [EXECUTE] Running [./scripts/firetv/fubo/bmitune.sh 32639 10.0.0.64:5555]
2024-02-26T15:04:30.085644709Z [EXECUTE] Stdout: 'Current PID for this script is 466
2024-02-26T15:04:30.085670275Z Not a special channel (exit nor reboot)
2024-02-26T15:04:30.085673357Z Starting: Intent { act=android.intent.action.VIEW dat=https://link.fubo.tv/... }
2024-02-26T15:04:30.085675734Z No active audio stream detected and app is not in focus after 4 seconds -- attempting to tune again...
2024-02-26T15:04:30.085677802Z Active audio stream detected with -26.3 LUF.
2024-02-26T15:04:30.085679751Z bmitune.sh is exiting for 10.0.0.64:5555 with exit code 0
2024-02-26T15:04:30.085693613Z '
2024-02-26T15:04:30.085696179Z [EXECUTE] Stderr: '+ channelID=32639
2024-02-26T15:04:30.085697889Z + specialID=32639
2024-02-26T15:04:30.085699580Z + streamerIP=10.0.0.64:5555
2024-02-26T15:04:30.085701250Z + streamerNoPort=10.0.0.64
2024-02-26T15:04:30.085702941Z + adbTarget='adb -s 10.0.0.64:5555'
2024-02-26T15:04:30.085704641Z + packageName=com.fubo.firetv.screen
2024-02-26T15:04:30.085706322Z + trap finish EXIT
2024-02-26T15:04:30.085707962Z + main
2024-02-26T15:04:30.085709683Z + updateReferenceFiles
2024-02-26T15:04:30.085711314Z + mkdir -p 10.0.0.64
2024-02-26T15:04:30.085712984Z + [[ -f 10.0.0.64/stream_stopped ]]
2024-02-26T15:04:30.085714635Z + [[ -f 10.0.0.64/last_channel ]]
2024-02-26T15:04:30.085716315Z + echo 466
2024-02-26T15:04:30.085717966Z + echo 'Current PID for this script is 466'
2024-02-26T15:04:30.085719637Z + matchEncoderURL
2024-02-26T15:04:30.085721268Z + case "$streamerIP" in
2024-02-26T15:04:30.085723266Z + encoderURL=http://10.0.0.60/0.ts
2024-02-26T15:04:30.085725026Z + specialChannels
2024-02-26T15:04:30.085726647Z + '[' 32639 = exit ']'
2024-02-26T15:04:30.085728268Z + '[' 32639 = reboot ']'
2024-02-26T15:04:30.085729929Z + [[ -f 10.0.0.64/adbCommunicationFail ]]
2024-02-26T15:04:30.085731609Z + echo 'Not a special channel (exit nor reboot)'
2024-02-26T15:04:30.085733300Z + tuneChannel
2024-02-26T15:04:30.085735030Z + adb -s 10.0.0.64:5555 shell am start -a android.intent.action.VIEW -d https://link.fubo.tv/al1%3Fv%3D1%26a%3Dplay%26t%3Dchannel%26channel_id%3D32639
2024-02-26T15:04:30.085736999Z Warning: Activity not started, its current task has been brought to the front
2024-02-26T15:04:30.085738739Z + activeAudioCheck
2024-02-26T15:04:30.085740350Z ++ date +%s
2024-02-26T15:04:30.085741961Z + local startTime=1708959863
2024-02-26T15:04:30.085743612Z + local maxDuration=60
2024-02-26T15:04:30.085745302Z + local minimumLoudness=-50
2024-02-26T15:04:30.085746953Z + local sleepDuration=0.5
2024-02-26T15:04:30.085748584Z + true
2024-02-26T15:04:30.085750264Z ++ ffmpeg -t 1 -i http://10.0.0.60/0.ts -filter:a ebur128 -map 0:a -f null -hide_banner -
2024-02-26T15:04:30.085751985Z ++ awk '/I: /{print $2}'
2024-02-26T15:04:30.085753645Z + checkLoudness=-70.0
2024-02-26T15:04:30.085755256Z ++ date +%s
2024-02-26T15:04:30.085756897Z + (( 1708959867 - 1708959863 > 60 ))
2024-02-26T15:04:30.085759234Z ++ echo '-70.0 > -50'
2024-02-26T15:04:30.085761014Z ++ bc -l
2024-02-26T15:04:30.085762694Z + (( 0 ))
2024-02-26T15:04:30.085766543Z + appFocusCheck 0
2024-02-26T15:04:30.085768362Z ++ adb -s 10.0.0.64:5555 shell dumpsys window windows
2024-02-26T15:04:30.085770083Z ++ grep -E mCurrentFocus
2024-02-26T15:04:30.085771733Z ++ cut -d / -f1
2024-02-26T15:04:30.085773364Z ++ sed 's/.* //g'
2024-02-26T15:04:30.085775502Z + appFocus=
2024-02-26T15:04:30.085777113Z + [[ '' == com.fubo.firetv.screen ]]
2024-02-26T15:04:30.085778764Z + return 1
2024-02-26T15:04:30.085780424Z ++ date +%s
2024-02-26T15:04:30.085782155Z + echo 'No active audio stream detected and app is not in focus after 4 seconds -- attempting to tune again...'
2024-02-26T15:04:30.085783945Z + adb -s 10.0.0.64:5555 shell input keyevent KEYCODE_CENTER
2024-02-26T15:04:30.085785645Z + true
2024-02-26T15:04:30.085788380Z ++ ffmpeg -t 1 -i http://10.0.0.60/0.ts -filter:a ebur128 -map 0:a -f null -hide_banner -
2024-02-26T15:04:30.085790219Z ++ awk '/I: /{print $2}'
2024-02-26T15:04:30.085791880Z + checkLoudness=-26.3
2024-02-26T15:04:30.085793541Z ++ date +%s
2024-02-26T15:04:30.085795221Z + (( 1708959870 - 1708959863 > 60 ))
2024-02-26T15:04:30.085797001Z ++ echo '-26.3 > -50'
2024-02-26T15:04:30.085798711Z ++ bc -l
2024-02-26T15:04:30.085800362Z + (( 1 ))
2024-02-26T15:04:30.085801963Z + echo 'Active audio stream detected with -26.3 LUF.'
2024-02-26T15:04:30.085803654Z + break
2024-02-26T15:04:30.085805274Z + finish
2024-02-26T15:04:30.085806925Z + echo 'bmitune.sh is exiting for 10.0.0.64:5555 with exit code 0'
2024-02-26T15:04:30.085808993Z '
2024-02-26T15:04:30.085810624Z [EXECUTE] Finished running ./scripts/firetv/fubo/bmitune.sh in 6.407330249s
2024-02-26T15:04:36.169211878Z [IO] io.Copy: write tcp 172.19.0.2:7654->10.0.0.37:34540: write: broken pipe
2024-02-26T15:04:36.169339032Z [IOINFO] Successfully copied 24864900 bytes
2024-02-26T15:04:36.169346957Z [IOINFO] Transfer speed: 15.925155478836098 Mbits/second
2024-02-26T15:04:36.169354256Z Performing Close() for 10.0.0.64:5555
2024-02-26T15:04:36.169363952Z [EXECUTE] Running [./scripts/firetv/fubo/stopbmitune.sh 10.0.0.64:5555 32639]
2024-02-26T15:04:38.749824196Z [EXECUTE] Stdout: 'Streaming stopped for 10.0.0.64:5555
2024-02-26T15:04:38.749881345Z Sleep initiated for 10.0.0.64:5555
2024-02-26T15:04:38.749891169Z 10.0.0.64/stream_stopped written with epoch stop time
2024-02-26T15:04:38.749898160Z '
2024-02-26T15:04:38.749903420Z [EXECUTE] Stderr: '+ streamerIP=10.0.0.64:5555
2024-02-26T15:04:38.749909566Z + streamerNoPort=10.0.0.64
2024-02-26T15:04:38.749915075Z + adbTarget='adb -s 10.0.0.64:5555'
2024-02-26T15:04:38.749921767Z + packageName=com.fubo.firetv.screen
2024-02-26T15:04:38.749962766Z + main
2024-02-26T15:04:38.749970244Z + bmituneDone
2024-02-26T15:04:38.749975037Z + bmitunePID=466
2024-02-26T15:04:38.749979681Z + ps -p 466
2024-02-26T15:04:38.749984275Z + adbStop
2024-02-26T15:04:38.749989038Z + stop='input keyevent KEYCODE_BACK; input keyevent KEYCODE_BACK; input keyevent KEYCODE_HOME'
2024-02-26T15:04:38.749994338Z + adb -s 10.0.0.64:5555 shell input keyevent 'KEYCODE_BACK;' input keyevent 'KEYCODE_BACK;' input keyevent KEYCODE_HOME
2024-02-26T15:04:38.749999787Z + sleep 2
2024-02-26T15:04:38.750004541Z + echo 'Streaming stopped for 10.0.0.64:5555'
2024-02-26T15:04:38.750009284Z + adbSleep
2024-02-26T15:04:38.750014594Z + sleep='input keyevent KEYCODE_SLEEP'
2024-02-26T15:04:38.750019178Z + adb -s 10.0.0.64:5555 shell input keyevent KEYCODE_SLEEP
2024-02-26T15:04:38.750023922Z + echo 'Sleep initiated for 10.0.0.64:5555'
2024-02-26T15:04:38.750028675Z + date +%s
2024-02-26T15:04:38.750033239Z + echo '10.0.0.64/stream_stopped written with epoch stop time'
2024-02-26T15:04:38.750038082Z '
2024-02-26T15:04:38.750042825Z [EXECUTE] Finished running ./scripts/firetv/fubo/stopbmitune.sh in 2.580601648s
2024-02-26T15:04:38.750095031Z [GIN-debug] Request: 10.0.0.37 GET /play/tuner/32639, latency: 15.261837806s, status: 200

My first reaction is that this doesn't sound like a coding issue. It strikes me as more like something to do with the encoder (settings?), or maybe power related? What encoder are you using? And, how are you powering your devices?

EDIT: ah4c is strictly a proxy, there's no processing of the video stream -- it's just passed to Channels as it's received.