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

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.

Just got the following:
HDMI Encoder
FireStick TV (4K)
Google TV (4k)

and so I want to test.
So I enable ADB on the Google TV - Done
Got the ENCODER on the home network and have its ip address

now is there a doc or docs to complete the test. If this works then I try the other device (Firestick)

What brand of encoder did you get?

What streaming app are you hoping to use?

I got this encoder:
EXVIST H.265 1080P
https://www.amazon.com/dp/B08FDZ2VNZ?ref=ppx_yo2ov_dt_b_product_details&th=1
as a test, but also found one for $65 on order to try as well. I only plan on having a HDHomeRun, Firestick and Google TV for now.

As for the app to start with. For Firestick/FireTv let's go with Freevee (anything here)
For the GoogleTV my son has 3 months free of Youtube TV and so any local off that like NBC, CBS would be a good test.

If you have YTTV, and want to get things up-and-running as quickly as possible, I'd suggest you use the ADBTuner project:

Once you get familiar with the concepts, if you want to work up some scripts for apps that don't have deeplinks, you can circle back here.

First of all, thank you so much @bnhf for setting this up! I have everything generally up and running, but am seeing a couple of issues and wanted to check that I hadn't messed anything up and what the best way to workaround these issues is.

I am using this for DirecTV Stream on a Fire Stick. So I've set STREAMER_APP=scripts/firetv/directv. However, if I use the directv.m3u in Channels then some of the channel names don't quite match (largely if they have an "HD" suffix or not) so the search results don't return anything and things get stuck. I then tried switching to the dtvstream.m3u and that worked for some channels and not others, again largely because of the "HD" suffix issue.

Looking at the code I see this line in the bmitune.sh file:

m3uName="${STREAMER_APP#*/*/}.m3u"

Now if I'm reading that right it means that the name of the streamer app/script and the m3u need to match or it might pull the name of the station from the "wrong" m3u file. And in my setup the names of the script and m3u are different.

What's the best way to fix that? Should I just duplicate your firetv/directv scripts and give them a unique name and have it match to a new m3u file? (I'm probably going to create a new and large m3u file for my entire DirecTV Stream package so that I can use this method as the default ahead of TVE in Channels.) Or am I missing something and have it misconfigured some way?

Thanks for your help!

That is a known issue between having DTV and DTVStream credentials, and it's why there's basically a duplicated set of scripts under scripts/firetv/dtvstream, so switch your STREAMER_APP variable to that and it'll improve the situation.

@gfhartzell has been the primary maintainer of dtvstream.m3u, but like me he uses just a subset of the channels available. So it's very possible that the channels he uses are the ones that are working for you. Hopefully he'll see this discussion, and between the two of you can expand dtvstream.m3u to include all of the channels you want.

If you run into any troublesome channels, due to multiple matches in the search, we do have a section for such "problem children" -- so one way or another, we should be able to get you to 100% success. Though channel tuning is not fast using this method, it's quite reliable once you have everything setup properly. And for recordings at least, tuning accuracy is what matters -- speed is a distant second.

Ah ha! I didn't realize there was already a duplicate set of scripts because I didn't see them here: https://github.com/sullrich/ah4c/tree/main/scripts/firetv

I'll try that and work on a full dtvstream.m3u for my full list of channels. I'll share that here and you can decide if it makes sense to include (and I can open a PR or whatever you prefer). Admittedly it may not be ideal because I'm grandfathered into an old package that they call "Package: MGM+ + FreePreview + Free MAX + Unlimited Hours of Cloud DVR + NBA League Pass + Gotta Have It + DTVN EE - Enhanced Technology Fee + 20 In-Home Streams". Catchy!

Right you are! They're in the build though, and I'll add them to the repo along with at least one other that's in the queue from the Netherlands.

The marketing team must have been on vacation when they named that package! If we need to do another version of the DTV scripts/M3U for you, that's fine -- but if we can make it happen with the current DTVStream toolset, that'd would be ideal.

Just an FYI the dtvstream.m3u is for Philadelphia, PA and the HBO entiries are untested,
Also I found using the iPhone app to see the channel names sorted by number helped especially to find the search names for my locals. Olivetin now does the best job for finding the channel id. Have at it!

2 Likes

My encoder is the URay 4K 4 Channels H.265 H.264 HDMI IP Video Streaming Encoder, 2 Firesticks, 2 onn's. Everything is currently laid on my bench still. They are all powered by their usb - plugged directly in wall.

I noticed that some of my recordings were hard to see on the tv - I call it dimmed - lite - not bright as the others. I started troubleshooting : its no particular channel, tuner or device or port on the encoder. I finally realized it was every other recording. I swapped tuners to different ports, reset a couple devices to factory - the issues doesn't follow anything traceable.

I can duplicate 100% every time. I start watching a channel from channels browser while also watching in vlc. Evrything looks great the first time. I'll stop the browser watching and see the vlc closes everything and goes the test pattern screen. I then restart watching again in the browser - and the browser window and the vlc window are dull /dim. Repeat the process and screen(s) are back to full color & brightness. I can reboot everything and the issue remains. I first thought something in the scripts wasn't actually clearing everything and shutting it down all the way - leaving something hanging the process, then the 2nd time it effects the picture - the 3rd time reset to normal. But I don't see anything weird when watching the vlc session, no flashing, jittering or sound issues.

This does not happen with abdtuner that I still have setup 1 channel for.

I checked with Uray and I have the latest firmware. Not sure how to test this any further to isolate the issue...

Can you check the display settings on the Android device when the picture looks bad? My two chromecasts will sometimes switch to 8-bit RGB which looks horribly washed out and I haven't found a consistent cause, or easy fix, other than changing the setting back or rebooting.

Also take a look into the "match content" settings on the Android device. Maybe the video mode is changing between sources and that's causing it to bug out?

That's an important clue. I wonder if the Fubo app needs to be force closed after each tune? If you're using "compatibility mode" in ADBTuner, then that could be the difference.

This is the function in stopbmitune.sh to modify:

#Stop stream
adbStop() {
  stop="input keyevent KEYCODE_BACK; \
        input keyevent KEYCODE_BACK; \
        input keyevent KEYCODE_HOME"
  #stop="am force-stop $packageName"
  $adbTarget shell $stop; sleep 2
  echo "Streaming stopped for $streamerIP"
}

I think I changed from the force-stop to the KEYCODE approach in the interest of faster tuning, but the app may be misbehaving when left running.

So here's my first stab at a comprehensive dtvstream.m3u for my setup:

This is for nearly all of the channels that I receive on my package in the San Francisco Bay Area. I still need to add channels above #500 which would be HBO, Starz, regional sports networks, and a few others, but I wanted to get something up and running first.

I switched over to the dtvstream scripts with this m3u and so far everything seems to be working great!

2 Likes

Finally got some time to test this - and it seems to have solved that issue. The video looks good now with back-to-back captures - thank you! Whats the best way to lock that script to prevent future updates from overwritng?

Couple of other things:
I'm having issues on reboots with losing the ADB keys to the device. I have to restart the device and then restart ah4c container.

Once I get that resolved, the first time I try to watch a channel it stops on the Fubo profile stream, once I select that - I have to select "watch live" -using the remote of course. It seems to be fine after that for any subsequent channel watching.

I know you said I'm the only one using Fubo, I realize this isn't high on your list of issues to deal with. I've got a new server spun up to move everything to and trying to get it all tested beforehand. Any insight is appreciated... allot of this may be the Fubo app itself..

Preventing updates to custom scripts and M3Us is done using these two environment variables. You'd change them to false:

UPDATE_SCRIPTS=true
UPDATE_M3US=true

That suggests you don't have your persistent data directories setup correctly. That's handled by these three bindings:

    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

And, this env var:

HOST_DIR=/data

Generally this is a simple as setting a parent directory (like /data in the example), but the approach can vary by the OS you're running on your Docker host.

This should be something that can be handled as part of the tuning process. We do have a test for active audio to work with, so maybe those two KEYCODES code be sent if audio isn't heard in x seconds after tuning?

I'll tackle this one first. This may be my lack of portainer skills as this is my first go at it.
I can see the 3 adb files on my Host (Ubuntu 20.04 server LTS) file manager @ /data/ah4c/adb.

This is the container volumes :
image

Do I need to map a container volume to the host?

That looks perfect actually. Those adb data files should be persistent with those settings. Go ahead and post your complete docker-compose and env vars, and I'll see if anything looks amiss elsewhere.

Have you tried using the bundled ws-scrcpy? That uses that same adb data, so maybe try connecting that way to be sure you're not prompted (as though it's a new connection) on the streaming device: http://<yourdockerhost>:7655 should get you there if you kept the standard ports.

@bnhf
Can you give me example for script /m3u files
To send adb number tuning? No need to open/close any app . Using android sat tuner.

If you can give me these 2 as example files . Thanks !

Channel 1: SVT1, press 1 on remote
Channel 10: Tv10, press 10 on remote