The original HDMI for Channels thread is super long, and this particular variant (dockerized version of ah4c plus ws-scrcpy) bears only a passing resemblance to the original project. So, I thought it might be time to create a new thread that highlights what the capabilities are of this very useful extension.
There are two projects that use this same combination of HDMI encoder(s) + streaming stick(s) as a source for Channels DVR. This project, ah4c, and ADBTuner. ADBTuner is great for any streaming app that supports deep links, while ah4c supports both deep links and remote control emulation.
Deep links allow for reasonably fast virtual tuning, while sending Android Debug Bridge (adb) commands to simulate keypresses is typically slower. The main advantage to using adb commands in script form, is that pretty much any streaming app running on a streaming stick, connected to an HDMI encoder, can become a source for a virtual tuner.
This dockerized version of ah4c uses Portainer, so you'll want to be sure you have this excellent WebUI for Docker installed before beginning. Here's the current recommended docker-compose for Portainer-Stacks:
version: '3.9'
services:
# 2024.10.30
# GitHub home for this project with setup instructions: https://github.com/sullrich/ah4c
# Docker Hub home for this project: https://hub.docker.com/repository/docker/bnhf/ah4c
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:
- ${ADBS_PORT}:5037 # Port used by adb-server
- ${HOST_PORT}:7654 # Port used by this ah4c proxy
- ${WSCR_PORT}:8000 # Port used by ws-scrcpy
environment:
- IPADDRESS=${IPADDRESS} # Hostname or IP address of this ah4c 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, 4, 5, 6, 7, 8 or 9 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
- TUNER5_IP=${TUNER5_IP} # Streaming device #5 with adb port in the form hostname:port or ip:port
- TUNER6_IP=${TUNER6_IP} # Streaming device #6 with adb port in the form hostname:port or ip:port
- TUNER7_IP=${TUNER7_IP} # Streaming device #7 with adb port in the form hostname:port or ip:port
- TUNER8_IP=${TUNER8_IP} # Streaming device #8 with adb port in the form hostname:port or ip:port
- TUNER9_IP=${TUNER9_IP} # Streaming device #9 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
- ENCODER5_URL=${ENCODER5_URL} # Full URL for tuner #5 in the form http://hostname/stream or http://ip/stream
- ENCODER6_URL=${ENCODER6_URL} # Full URL for tuner #6 in the form http://hostname/stream or http://ip/stream
- ENCODER7_URL=${ENCODER7_URL} # Full URL for tuner #7 in the form http://hostname/stream or http://ip/stream
- ENCODER8_URL=${ENCODER8_URL} # Full URL for tuner #8 in the form http://hostname/stream or http://ip/stream
- ENCODER9_URL=${ENCODER9_URL} # Full URL for tuner #9 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=""
- 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
- UPDATE_SCRIPTS=${UPDATE_SCRIPTS} # Set to true if you'd like the sample scripts and STREAMER_APP scripts updated whether they exist or not
- UPDATE_M3US=${UPDATE_M3US} # Set to true if you'd like the sample m3us updated whether they exist or not
- TZ=${TZ} # Your local timezone in Linux "tz" format
- SPEED_MODE=${SPEED_MODE} # Set to false if you'd like the target streaming app to be closed after each tuning cycle (limited script support).
- KEEP_WATCHING=${KEEP_WATCHING} # In supported scripts, set the delay before resending a tuning deeplink to prevent "Are you still watching?" type messages. Examples: Use 4h for 4 hours or 240m for 240 minutes.
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: unless-stopped
Most anything that'll be unique to your installation is setup to use environment variables. Here's a set of example environment variables you'll want customize to your particular setup:
TAG=latest
DOMAIN=localdomain tailxxxxx.ts.net
ADBS_PORT=5037
HOST_PORT=7654
WSCR_PORT=7655
IPADDRESS=htpc6:7654
NUMBER_TUNERS=5
TUNER1_IP=firestick-rack1:5555
ENCODER1_URL=http://encoder_48007/0.ts
TUNER2_IP=firestick-rack2:5555
ENCODER2_URL=http://encoder_48007/4.ts
TUNER3_IP=firestick-rack3:5555
ENCODER3_URL=http://encoder_48007/8.ts
TUNER4_IP=firestick-rack4:5555
ENCODER4_URL=http://encoder_48007/12.ts
TUNER5_IP=firestick-travel2:5555
ENCODER5_URL=http://encoder_23393/0.ts
STREAMER_APP=scripts/firetv/dtvdeeplinks
CHANNELSIP=media-server6
ALERT_SMTP_SERVER=smtp.gmail.com:587
ALERT_AUTH_SERVER=smtp.gmail.com
ALERT_EMAIL_FROM=xxxxxxxxxx@gmail.com
ALERT_EMAIL_PASS=xxxxxxxxxxxxxxxx
ALERT_EMAIL_TO=xxxxxxxxxx@gmail.com
UPDATE_SCRIPTS=true
UPDATE_M3US=true
TZ=US/Mountain
SPEED_MODE=false
KEEP_WATCHING=4h
HOST_DIR=/data
These variables can be entered in the form above using Advanced mode, and will look similar to this in Simple mode:
Be sure to review the comments in the docker-compose above for additional hints on how to define these all-important environment variables.
There are existing scripts for a number of combinations of streamer/app. For example combinations like scripts/firetv/directv, scripts/osprey/directv, scripts/firetv/livetv will all place tuning scripts and M3Us in the directory on your Docker host you have mapped to /opt/scripts and /opt/m3u.
There are other existing combinations as well, but if there are no current scripts for your desired combination of streamer/app, then you'll need to create them. scripts/firetv/directv is a good place to start, as this set of scripts has many Bash functions that can be re-used. Look in the scripts folder at:
to get an idea of what's available. (Many thanks to @KompilerDJ for his excellent work!)
Once you have ah4c up-and-running, complete with functional tuning scripts and M3U, you can add this virtual tuner in the Custom Channels section of Channels DVR:
There are numerous tools built-in to this container to give you an idea what's happening with your virtual tuning:
The main page can be found at the address you specified for $IPADDRESS:
And a few sample pages:
Activity & logs:
Edit Channel M3Us:
In addition a browser based version of scrcpy is also included, using a common adb authorization database with ah4c. Be aware, DRM is not supported with this tool though, so you'll see all the menus and can open apps, but none of the DRM protected content will display. Even with that limitation, it's amazingly useful, particularly for remote access and control of your sticks:
This can be found at the port you specified in your docker-compose (usually 7655). All of the streaming sticks defined in your docker-compose will be listed:
Click on shell, and you'll have an adb shell in a new tab where you can issue commands to your selected streaming stick. Back in the original tab, click on Configure stream, followed by:
And you'll see whatever your HDMI-connected streaming stick is displaying:
There's a button to passthrough keyboard commands, along with Home, Back and Screenshot buttons. Any commands you can't generate on the keyboard you can send from the shell. Examples of these would be:
input keyevent KEYCODE_SLEEP
input keyevent KEYCODE_MENU
bnhf/ah4c:latest should now be fully up-to-date, and can be used in place of ah4c:prime or ah4c:test2
Hopefully this will be enough to get anyone going that's not already familiar with this extension, but if not, post your questions or comments here. Positive discourse only please!