I think I got it, your version of adb is not sending the "0" key
What do you mean "your version of adb" -- the adb included with ah4c is right from the Debian repo. It's not something I'm building. More likely the zinwell/livetv scripts need tweaking.
EDIT: Looking at your logs, you tried to tune channel 41 -- so I'm not sure where 0 factors in here:
2026/09/01 16:12:14 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
I also tried to tune to channel 2.1 and 4.1. It has to be 3 digits and it is not taking the "0"
By "it" I assume you mean the Zinwell box? Are you using the same Zinwell scripts that are currently in the ah4c repo? Can you post the zinwell.m3u you're using?
I am using the default m3u as I created it.
I'm a little unclear on why you're only answering a select few of my questions, but what you have posted is not adding up...
If this is your M3U:
#EXTM3U
#EXTINF:-1 channel-id="102.1" channel-number="" tvc-guide-stationid="" tvg-group="" tvg-logo="",CBS 2 NEXTGENTV
http://{{ .IPADDRESS }}/play/tuner/02-1
#EXTINF:-1 channel-id="104.1" channel-number="" tvc-guide-stationid="" tvg-group="" tvg-logo="",NBC 4 NEXTGENTV
http://{{ .IPADDRESS }}/play/tuner/04-1
#EXTINF:-1 channel-id="147.1" channel-number="" tvc-guide-stationid="" tvg-group="" tvg-logo="",WNJU 47 NEXTGENTV
http://{{ .IPADDRESS }}/play/tuner/47-1
And this is your bmitune.sh script:
#!/bin/bash
# bmitune.sh for zinwell/livetv
# 2025.09.23
#Debug on if uncommented
set -x
#Global
channelID="$1"
streamerIP="$2"
adbTarget="adb -s $streamerIP"
#Trap end of script run
finish() {
echo "bmitune.sh is exiting for $streamerIP with exit code $?"
}
trap finish EXIT
#Tuning is based on channel number values from zinwell.m3u
tuneChannel() {
for (( i=0; i<${#channelID}; i++ )); do
keypress="${channelID:$i:1}"
$adbTarget shell input keyevent KEYCODE_$keypress
sleep 2
done
$adbTarget shell input keyevent KEYCODE_DPAD_CENTER
}
main() {
tuneChannel
}
main
It makes no sense (and frankly seems impossible), that this could be your log output when attempting to tune to channel 104.1:
AH4C
Logs
Last updated: 9/1/2026, 4:13:11 PM showing last 500 lines
Home
Device Control
Activity
Activity & Logs
Logs
Closed Captions
Channel M3Us
API Routes
v2026.08.28.1306
2026/09/01 16:11:18 [START] ah4c v2026.08.28.1306 is starting
2026/09/01 16:11:18 [ENV] Not loading env
2026/09/01 16:11:18 [ENV] IPADDRESS 192.168.1.28:7654
2026/09/01 16:11:18 [ENV] ALERT_SMTP_SERVER
2026/09/01 16:11:18 [ENV] ALERT_AUTH_SERVER
2026/09/01 16:11:18 [ENV] ALERT_EMAIL_FROM
2026/09/01 16:11:18 [ENV] ALERT_EMAIL_PASS
2026/09/01 16:11:18 [ENV] ALERT_EMAIL_TO
2026/09/01 16:11:18 [ENV] ALERT_WEBHOOK_URL
2026/09/01 16:11:18 [ENV] ALLOW_DEBUG_VIDEO_PREVIEW
2026/09/01 16:11:18 [ENV] NULL_FRAME_INSERTION
2026/09/01 16:11:18 [ENV] PLAYBACK_DETECTION
2026/09/01 16:11:18 [ENV] PLAYBACK_DELAY
2026/09/01 16:11:18 [ENV] PLAYBACK_STATIC_TIMEOUT
2026/09/01 16:11:18 [ENV] Creating tuner 1
2026/09/01 16:11:18 [ENV] ENCODER1_URL http://192.168.1.70:8090/stream0
2026/09/01 16:11:18 [ENV] TUNER1_IP 192.168.1.71
2026/09/01 16:11:18 [ENV] CMD1 ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:11:18 [ENV] TEECMD1
2026/09/01 16:11:18 [ENV] PRE SCRIPT ./scripts/zinwell/livetv/prebmitune.sh
2026/09/01 16:11:18 [ENV] START SCRIPT ./scripts/zinwell/livetv/bmitune.sh
2026/09/01 16:11:18 [ENV] STOP SCRIPT ./scripts/zinwell/livetv/stopbmitune.sh
2026/09/01 16:11:18 [ENV] REBOOT SCRIPT ./scripts/zinwell/livetv/reboot.sh
2026/09/01 16:11:18 [ENV] Creating tuner 2
2026/09/01 16:11:18 [ENV] ENCODER2_URL http://192.168.1.70:8090/stream1
2026/09/01 16:11:18 [ENV] TUNER2_IP 192.168.1.72
2026/09/01 16:11:18 [ENV] CMD2 ffmpeg -i http://192.168.1.70:8090/stream1 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:11:18 [ENV] TEECMD2
2026/09/01 16:11:18 [ENV] PRE SCRIPT ./scripts/zinwell/livetv/prebmitune.sh
2026/09/01 16:11:18 [ENV] START SCRIPT ./scripts/zinwell/livetv/bmitune.sh
2026/09/01 16:11:18 [ENV] STOP SCRIPT ./scripts/zinwell/livetv/stopbmitune.sh
2026/09/01 16:11:18 [ENV] REBOOT SCRIPT ./scripts/zinwell/livetv/reboot.sh
2026/09/01 16:11:18 [ENV] Creating tuner 3
2026/09/01 16:11:18 [ENV] ENCODER3_URL http://192.168.1.70:8090/stream2
2026/09/01 16:11:18 [ENV] TUNER3_IP 192.168.1.73
2026/09/01 16:11:18 [ENV] CMD3 ffmpeg -i http://192.168.1.70:8090/stream2 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:11:18 [ENV] TEECMD3
2026/09/01 16:11:18 [ENV] PRE SCRIPT ./scripts/zinwell/livetv/prebmitune.sh
2026/09/01 16:11:18 [ENV] START SCRIPT ./scripts/zinwell/livetv/bmitune.sh
2026/09/01 16:11:18 [ENV] STOP SCRIPT ./scripts/zinwell/livetv/stopbmitune.sh
2026/09/01 16:11:18 [ENV] REBOOT SCRIPT ./scripts/zinwell/livetv/reboot.sh
2026/09/01 16:11:18 [ENV] Creating tuner 4
2026/09/01 16:11:18 [ENV] ENCODER4_URL http://192.168.1.70:8090/stream3
2026/09/01 16:11:18 [ENV] TUNER4_IP 192.168.1.74
2026/09/01 16:11:18 [ENV] CMD4 ffmpeg -i http://192.168.1.70:8090/stream3 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:11:18 [ENV] TEECMD4
2026/09/01 16:11:18 [ENV] PRE SCRIPT ./scripts/zinwell/livetv/prebmitune.sh
2026/09/01 16:11:18 [ENV] START SCRIPT ./scripts/zinwell/livetv/bmitune.sh
2026/09/01 16:11:18 [ENV] STOP SCRIPT ./scripts/zinwell/livetv/stopbmitune.sh
2026/09/01 16:11:18 [ENV] REBOOT SCRIPT ./scripts/zinwell/livetv/reboot.sh
2026/09/01 16:11:18 [ENV] Creating tuner 5
2026/09/01 16:11:18 [ENV] ENCODER5_URL http://192.168.1.70:8090/stream4
2026/09/01 16:11:18 [ENV] TUNER5_IP 192.168.1.75
2026/09/01 16:11:18 [ENV] CMD5 ffmpeg -i http://192.168.1.70:8090/stream4 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:11:18 [ENV] TEECMD5
2026/09/01 16:11:18 [ENV] PRE SCRIPT ./scripts/zinwell/livetv/prebmitune.sh
2026/09/01 16:11:18 [ENV] START SCRIPT ./scripts/zinwell/livetv/bmitune.sh
2026/09/01 16:11:18 [ENV] STOP SCRIPT ./scripts/zinwell/livetv/stopbmitune.sh
2026/09/01 16:11:18 [ENV] REBOOT SCRIPT ./scripts/zinwell/livetv/reboot.sh
2026/09/01 16:11:18 [BLACKFRAMES] made 500ms of black, 12 KB, to go in front of the picture at the hand-off
2026/09/01 16:11:18 [CC] WARNING: /opt/captions is not a bind mount. The speech model, engine and any GPU driver downloaded here are lost when the container is recreated.
2026/09/01 16:11:18 [CC] WARNING: add this volume to your compose file and recreate the container: ${HOST_DIR}/ah4c/captions:/opt/captions
2026/09/01 16:11:18 [CC] Captions are off, so the graphics driver is left where it is. It goes in when captions are switched on.
2026/09/01 16:11:18 [START] ah4c is ready
2026/09/01 16:12:03 Attempting application tune for device ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:12:03 [EXECUTE] Running [./scripts/zinwell/livetv/prebmitune.sh 192.168.1.71 41]
2026/09/01 16:12:03 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:03 [EXECUTE] Stderr: ''
2026/09/01 16:12:03 [EXECUTE] Finished running ./scripts/zinwell/livetv/prebmitune.sh in 4.137829ms
2026/09/01 16:12:03 [EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 41 192.168.1.71]
2026/09/01 16:12:04 [IOINFO] Successfully copied 0 bytes
2026/09/01 16:12:04 [IOINFO] Transfer speed: 0 Mbits/second
2026/09/01 16:12:04 Performing Close() for 192.168.1.71
2026/09/01 16:12:04 [ERR] Failed to kill command: os: process already finished
2026/09/01 16:12:04 [EXECUTE] Running [./scripts/zinwell/livetv/stopbmitune.sh 192.168.1.71 41]
2026/09/01 16:12:04 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:04 [EXECUTE] Stderr: ''
2026/09/01 16:12:04 [EXECUTE] Finished running ./scripts/zinwell/livetv/stopbmitune.sh in 12.56463ms
2026/09/01 16:12:04 [GIN-debug] Request: 192.168.1.1 GET /play/tuner/41, latency: 626.912293ms, status: 200
2026/09/01 16:12:08 Attempting application tune for device ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:12:08 [EXECUTE] Running [./scripts/zinwell/livetv/prebmitune.sh 192.168.1.71 41]
2026/09/01 16:12:08 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:08 [EXECUTE] Stderr: ''
2026/09/01 16:12:08 [EXECUTE] Finished running ./scripts/zinwell/livetv/prebmitune.sh in 3.408423ms
2026/09/01 16:12:08 [EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 41 192.168.1.71]
2026/09/01 16:12:08 [IOINFO] Successfully copied 0 bytes
2026/09/01 16:12:08 [IOINFO] Transfer speed: 0 Mbits/second
2026/09/01 16:12:08 Performing Close() for 192.168.1.71
2026/09/01 16:12:08 [ERR] Failed to kill command: os: process already finished
2026/09/01 16:12:08 [EXECUTE] Running [./scripts/zinwell/livetv/stopbmitune.sh 192.168.1.71 41]
2026/09/01 16:12:08 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:08 [EXECUTE] Stderr: ''
2026/09/01 16:12:08 [EXECUTE] Finished running ./scripts/zinwell/livetv/stopbmitune.sh in 3.919578ms
2026/09/01 16:12:08 [GIN-debug] Request: 192.168.1.1 GET /play/tuner/41, latency: 529.806431ms, status: 200
2026/09/01 16:12:10 Attempting application tune for device ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:12:10 [EXECUTE] Running [./scripts/zinwell/livetv/prebmitune.sh 192.168.1.71 41]
2026/09/01 16:12:10 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:10 [EXECUTE] Stderr: ''
2026/09/01 16:12:10 [EXECUTE] Finished running ./scripts/zinwell/livetv/prebmitune.sh in 3.64142ms
2026/09/01 16:12:10 [EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 41 192.168.1.71]
2026/09/01 16:12:10 [IOINFO] Successfully copied 0 bytes
2026/09/01 16:12:10 [IOINFO] Transfer speed: 0 Mbits/second
2026/09/01 16:12:10 Performing Close() for 192.168.1.71
2026/09/01 16:12:10 [ERR] Failed to kill command: os: process already finished
2026/09/01 16:12:10 [EXECUTE] Running [./scripts/zinwell/livetv/stopbmitune.sh 192.168.1.71 41]
2026/09/01 16:12:10 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:10 [EXECUTE] Stderr: ''
2026/09/01 16:12:10 [EXECUTE] Finished running ./scripts/zinwell/livetv/stopbmitune.sh in 12.6603ms
2026/09/01 16:12:10 [GIN-debug] Request: 192.168.1.1 GET /play/tuner/41, latency: 559.541254ms, status: 200
2026/09/01 16:12:10 [EXECUTE] Stdout: 'bmitune.sh is exiting for 192.168.1.71 with exit code 0
'
2026/09/01 16:12:10 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
'
2026/09/01 16:12:10 [EXECUTE] Finished running ./scripts/zinwell/livetv/bmitune.sh in 7.07450577s
2026/09/01 16:12:12 Attempting application tune for device ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:12:12 [EXECUTE] Running [./scripts/zinwell/livetv/prebmitune.sh 192.168.1.71 41]
2026/09/01 16:12:12 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:12 [EXECUTE] Stderr: ''
2026/09/01 16:12:12 [EXECUTE] Finished running ./scripts/zinwell/livetv/prebmitune.sh in 3.340716ms
2026/09/01 16:12:12 [EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 41 192.168.1.71]
2026/09/01 16:12:12 [IOINFO] Successfully copied 0 bytes
2026/09/01 16:12:12 [IOINFO] Transfer speed: 0 Mbits/second
2026/09/01 16:12:12 Performing Close() for 192.168.1.71
2026/09/01 16:12:12 [ERR] Failed to kill command: os: process already finished
2026/09/01 16:12:12 [EXECUTE] Running [./scripts/zinwell/livetv/stopbmitune.sh 192.168.1.71 41]
2026/09/01 16:12:12 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:12 [EXECUTE] Stderr: ''
2026/09/01 16:12:12 [EXECUTE] Finished running ./scripts/zinwell/livetv/stopbmitune.sh in 3.441394ms
2026/09/01 16:12:12 [GIN-debug] Request: 192.168.1.1 GET /play/tuner/41, latency: 558.069269ms, status: 200
2026/09/01 16:12:14 Attempting application tune for device ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:12:14 [EXECUTE] Running [./scripts/zinwell/livetv/prebmitune.sh 192.168.1.71 41]
2026/09/01 16:12:14 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:14 [EXECUTE] Stderr: ''
2026/09/01 16:12:14 [EXECUTE] Finished running ./scripts/zinwell/livetv/prebmitune.sh in 3.368933ms
2026/09/01 16:12:14 [EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 41 192.168.1.71]
2026/09/01 16:12:14 [IOINFO] Successfully copied 0 bytes
2026/09/01 16:12:14 [IOINFO] Transfer speed: 0 Mbits/second
2026/09/01 16:12:14 Performing Close() for 192.168.1.71
2026/09/01 16:12:14 [ERR] Failed to kill command: os: process already finished
2026/09/01 16:12:14 [EXECUTE] Running [./scripts/zinwell/livetv/stopbmitune.sh 192.168.1.71 41]
2026/09/01 16:12:14 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:14 [EXECUTE] Stderr: ''
2026/09/01 16:12:14 [EXECUTE] Finished running ./scripts/zinwell/livetv/stopbmitune.sh in 4.166803ms
2026/09/01 16:12:14 [GIN-debug] Request: 192.168.1.1 GET /play/tuner/41, latency: 672.964335ms, status: 200
2026/09/01 16:12:14 [EXECUTE] Stdout: 'bmitune.sh is exiting for 192.168.1.71 with exit code 0
'
2026/09/01 16:12:14 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
'
2026/09/01 16:12:14 [EXECUTE] Finished running ./scripts/zinwell/livetv/bmitune.sh in 6.738739683s
2026/09/01 16:12:15 Attempting application tune for device ffmpeg -i http://192.168.1.70:8090/stream0 -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
2026/09/01 16:12:15 [EXECUTE] Running [./scripts/zinwell/livetv/prebmitune.sh 192.168.1.71 41]
2026/09/01 16:12:15 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:15 [EXECUTE] Stderr: ''
2026/09/01 16:12:15 [EXECUTE] Finished running ./scripts/zinwell/livetv/prebmitune.sh in 3.586201ms
2026/09/01 16:12:15 [EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 41 192.168.1.71]
2026/09/01 16:12:16 [EXECUTE] Stdout: 'bmitune.sh is exiting for 192.168.1.71 with exit code 0
'
2026/09/01 16:12:16 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
'
2026/09/01 16:12:16 [EXECUTE] Finished running ./scripts/zinwell/livetv/bmitune.sh in 6.820286589s
2026/09/01 16:12:17 [IOINFO] Successfully copied 0 bytes
2026/09/01 16:12:17 [IOINFO] Transfer speed: 0 Mbits/second
2026/09/01 16:12:17 Performing Close() for 192.168.1.71
2026/09/01 16:12:17 [ERR] Failed to kill command: os: process already finished
2026/09/01 16:12:17 [EXECUTE] Running [./scripts/zinwell/livetv/stopbmitune.sh 192.168.1.71 41]
2026/09/01 16:12:17 [EXECUTE] Stdout: 'Script not required
'
2026/09/01 16:12:17 [EXECUTE] Stderr: ''
2026/09/01 16:12:17 [EXECUTE] Finished running ./scripts/zinwell/livetv/stopbmitune.sh in 3.814653ms
2026/09/01 16:12:17 [GIN-debug] Request: 192.168.1.1 GET /play/tuner/41, latency: 1.855006647s, status: 200
2026/09/01 16:12:18 [EXECUTE] Stdout: 'bmitune.sh is exiting for 192.168.1.71 with exit code 0
'
2026/09/01 16:12:18 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
'
2026/09/01 16:12:18 [EXECUTE] Finished running ./scripts/zinwell/livetv/bmitune.sh in 6.747009989s
2026/09/01 16:12:20 [EXECUTE] Stdout: 'bmitune.sh is exiting for 192.168.1.71 with exit code 0
'
2026/09/01 16:12:20 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
'
2026/09/01 16:12:20 [EXECUTE] Finished running ./scripts/zinwell/livetv/bmitune.sh in 6.781840454s
2026/09/01 16:12:22 [EXECUTE] Stdout: 'bmitune.sh is exiting for 192.168.1.71 with exit code 0
'
2026/09/01 16:12:22 [EXECUTE] Stderr: '+ channelID=41
+ streamerIP=192.168.1.71
+ adbTarget='adb -s 192.168.1.71'
+ trap finish EXIT
+ main
+ tuneChannel
+ (( i=0 ))
+ (( i<2 ))
+ keypress=4
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_4
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ keypress=1
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_1
+ sleep 2
+ (( i++ ))
+ (( i<2 ))
+ adb -s 192.168.1.71 shell input keyevent KEYCODE_DPAD_CENTER
+ finish
+ echo 'bmitune.sh is exiting for 192.168.1.71 with exit code 0'
'
2026/09/01 16:12:22 [EXECUTE] Finished running ./scripts/zinwell/livetv/bmitune.sh in 6.930894004s
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /, latency: 16.856614ms, status: 200
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /static/js/theme.js, latency: 9.313653ms, status: 200
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /static/css/ah4c.css, latency: 12.591199ms, status: 200
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /static/logos/androidhdmi-for-channels.jpeg, latency: 1.284341ms, status: 200
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /favicon.ico, latency: 955.376ยตs, status: 200
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /api/version, latency: 417.442ยตs, status: 200
2026/09/01 16:12:54 [GIN-debug] Request: 192.168.1.19 GET /api/pyatv, latency: 114.617ยตs, status: 200
2026/09/01 16:12:57 [GIN-debug] Request: 192.168.1.19 GET /logs, latency: 2.238595ms, status: 200
2026/09/01 16:12:57 [GIN-debug] Request: 192.168.1.19 GET /static/css/ah4c.css, latency: 389.359ยตs, status: 200
2026/09/01 16:12:57 [GIN-debug] Request: 192.168.1.19 GET /static/js/theme.js, latency: 199.037ยตs, status: 200
2026/09/01 16:12:57 [GIN-debug] Request: 192.168.1.19 GET /static/logos/androidhdmi-for-channels.jpeg, latency: 423.343ยตs, status: 200
2026/09/01 16:12:57 [GIN-debug] Request: 192.168.1.19 GET /api/version, latency: 54.284ยตs, status: 200
2026/09/01 16:12:57 [GIN-debug] Request: 192.168.1.19 GET /api/pyatv, latency: 46.87ยตs, status: 200
I'm happy to help, but I need better, more complete and accurate information from you.
no dash in the m3u in the url.
So I reboot my server and now it is entering the 0 and working except cmd is still broken.
OK, so you're not using the zinwell.m3u from the repo -- which is why I asked you to post it.
However, the good news is that we're finally getting to the core of this issue, which is the GPU contention that's been introduced in recent versions of ah4c -- as we've only recently started using the GPU for AI-assisted Closed Captions. You were probably one of only a few people already using the GPU with ah4c:
This next section I'll ask you to read carefully, as I'm hoping you'll be willing to test something for us. If possible I'd like you to use this Docker Compose (with no edits please!) in a Portainer Stack:
services:
# 2026.09.01
# 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: # This docker-compose typically requires no editing. Use the Environment variables section of Portainer to set your values.
image: bnhf/ah4c:${TAG:-latest}
container_name: ${CONTAINER_NAME:-ah4c}
hostname: ${HOSTNAME:-ah4c}
dns_search: ${DOMAIN:-localdomain} # Specify the name of your LAN's domain, usually local or localdomain
runtime: ${DOCKER_RUNTIME:-runc} # Closed captions only. Set DOCKER_RUNTIME=nvidia for an NVIDIA GPU with the CUDA engine build. Requires the NVIDIA container toolkit.
devices:
- ${GPU_DEVICE:-/dev/null} # Closed captions only. Set GPU_DEVICE=/dev/dri to let the Vulkan engine build use an Intel or AMD GPU. Left at the default it passes /dev/null, which always exists and does nothing.
ports:
- ${HOST_PORT:-7654}:7654 # Port used by this ah4c proxy
environment:
- AH4C_COMPOSE=2026.09.01 # Compose file date stamp - do not change. The startup log flags it when out of date.
# โโ Proxy identity โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- IPADDRESS=${IPADDRESS} # Hostname or IP address of this ah4c extension to be used in M3U file (also add port number if not in M3U)
# โโ Tuners โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# One trio per tuner: TUNERn_IP is the box to tune; video comes from CMDn if set, otherwise ENCODERn_URL.
- NUMBER_TUNERS=${NUMBER_TUNERS} # Number of tuners you'd like defined - add a matching TUNERn_IP, ENCODERn_URL and CMDn trio below for each beyond 9
- TUNER1_IP=${TUNER1_IP} # Streaming device #1 with adb port in the form hostname:port or ip:port
- ENCODER1_URL=${ENCODER1_URL} # Tuner #1 source URL (http://hostname/stream). Streamed directly when CMD1 is blank; otherwise referenced by CMD1 as ${ENCODER1_URL}.
- CMD1=${CMD1} # Optional tuner #1 command; ah4c streams its stdout (end it with "-f mpegts -") instead of fetching ENCODER1_URL. No shell.
- TUNER2_IP=${TUNER2_IP} # Streaming device #2 with adb port in the form hostname:port or ip:port
- ENCODER2_URL=${ENCODER2_URL} # Tuner #2 source URL. Streamed directly when CMD2 is blank; otherwise referenced by CMD2 as ${ENCODER2_URL}.
- CMD2=${CMD2} # Optional tuner #2 command; ah4c streams its stdout instead of fetching ENCODER2_URL. See CMD1.
- TUNER3_IP=${TUNER3_IP} # Streaming device #3 with adb port in the form hostname:port or ip:port
- ENCODER3_URL=${ENCODER3_URL} # Tuner #3 source URL. Streamed directly when CMD3 is blank; otherwise referenced by CMD3 as ${ENCODER3_URL}.
- CMD3=${CMD3} # Optional tuner #3 command; ah4c streams its stdout instead of fetching ENCODER3_URL. See CMD1.
- TUNER4_IP=${TUNER4_IP} # Streaming device #4 with adb port in the form hostname:port or ip:port
- ENCODER4_URL=${ENCODER4_URL} # Tuner #4 source URL. Streamed directly when CMD4 is blank; otherwise referenced by CMD4 as ${ENCODER4_URL}.
- CMD4=${CMD4} # Optional tuner #4 command; ah4c streams its stdout instead of fetching ENCODER4_URL. See CMD1.
- TUNER5_IP=${TUNER5_IP} # Streaming device #5 with adb port in the form hostname:port or ip:port
- ENCODER5_URL=${ENCODER5_URL} # Tuner #5 source URL. Streamed directly when CMD5 is blank; otherwise referenced by CMD5 as ${ENCODER5_URL}.
- CMD5=${CMD5} # Optional tuner #5 command; ah4c streams its stdout instead of fetching ENCODER5_URL. See CMD1.
- TUNER6_IP=${TUNER6_IP} # Streaming device #6 with adb port in the form hostname:port or ip:port
- ENCODER6_URL=${ENCODER6_URL} # Tuner #6 source URL. Streamed directly when CMD6 is blank; otherwise referenced by CMD6 as ${ENCODER6_URL}.
- CMD6=${CMD6} # Optional tuner #6 command; ah4c streams its stdout instead of fetching ENCODER6_URL. See CMD1.
- TUNER7_IP=${TUNER7_IP} # Streaming device #7 with adb port in the form hostname:port or ip:port
- ENCODER7_URL=${ENCODER7_URL} # Tuner #7 source URL. Streamed directly when CMD7 is blank; otherwise referenced by CMD7 as ${ENCODER7_URL}.
- CMD7=${CMD7} # Optional tuner #7 command; ah4c streams its stdout instead of fetching ENCODER7_URL. See CMD1.
- TUNER8_IP=${TUNER8_IP} # Streaming device #8 with adb port in the form hostname:port or ip:port
- ENCODER8_URL=${ENCODER8_URL} # Tuner #8 source URL. Streamed directly when CMD8 is blank; otherwise referenced by CMD8 as ${ENCODER8_URL}.
- CMD8=${CMD8} # Optional tuner #8 command; ah4c streams its stdout instead of fetching ENCODER8_URL. See CMD1.
- TUNER9_IP=${TUNER9_IP} # Streaming device #9 with adb port in the form hostname:port or ip:port
- ENCODER9_URL=${ENCODER9_URL} # Tuner #9 source URL. Streamed directly when CMD9 is blank; otherwise referenced by CMD9 as ${ENCODER9_URL}.
- CMD9=${CMD9} # Optional tuner #9 command; ah4c streams its stdout instead of fetching ENCODER9_URL. See CMD1.
# โโ Streaming app and DVR โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- 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)
- PYATV=${PYATV:-false} # Set to TRUE to run docker-start-pyatv.sh at container start for Apple TV tuners via pyatv, instead of the default docker-start.sh used for adb-based tuners. Case-insensitive; anything else runs the default.
- CHANNELSIP=${CHANNELSIP} # Hostname or IP address of the Channels DVR server itself
# โโ Failure alerts โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Email via SMTP and/or a webhook GET, sent when a tune fails. Leave blank to disable.
- 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=${ALERT_WEBHOOK_URL} # URL to GET when an alert fires (same failures that trigger the e-mail); put $reason in the URL and it's replaced with the URL-encoded message. Blank disables it.
# โโ Guide tuning and content updates โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- LIVETV_ATTEMPTS=${LIVETV_ATTEMPTS} # For FireTV Live Guide tuning only, set maximum number of attempts at finding the desired channel
- CREATE_M3US=${CREATE_M3US:-false} # Set to true to create device-specific M3Us for use with Amazon Prime Premium channels -- requires a FireTV device
- UPDATE_SCRIPTS=${UPDATE_SCRIPTS:-true} # Set to true if you'd like the sample scripts and STREAMER_APP scripts updated whether they exist or not
- UPDATE_M3US=${UPDATE_M3US:-true} # Set to true if you'd like the sample m3us updated whether they exist or not
# โโ Timezone and session handling โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- TZ=${TZ} # Your local timezone in Linux "tz" format
- SPEED_MODE=${SPEED_MODE:-false} # 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.
# โโ Autocrop (LinkPi encoders only) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- AUTOCROP_CHANNELS=${AUTOCROP_CHANNELS} # Space separated list of channels (by number) with black borders on 4 sides to autocrop while maintaining aspect ratio. Requires LinkPi Encoder!
- LINKPI_HOSTNAME=${LINKPI_HOSTNAME} # Hostname or IP of the LinkPi Encoder's web API. Required for AUTOCROP_CHANNELS.
- LINKPI_USERNAME=${LINKPI_USERNAME} # Username for the LinkPi Encoder's web API. Required for AUTOCROP_CHANNELS.
- LINKPI_PASSWORD=${LINKPI_PASSWORD} # Password for the LinkPi Encoder's web API. Required for AUTOCROP_CHANNELS; not currently read by the bundled scripts, which log in with the LinkPi default password instead.
# โโ Custom startup script โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- USER_SCRIPT=${USER_SCRIPT} # Path to a custom script to run alongside ah4c at container startup. Blank runs nothing extra.
# โโ Recording continuity and playback timing โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Keep recordings starting on the program and free of gaps within the DVR's 30s tune window.
- NULL_FRAME_INSERTION=${NULL_FRAME_INSERTION:-false} # Set to TRUE to fill encoder stalls with MPEG-TS NULL packets (PID 0x1FFF) so the DVR never sees a zero-byte gap mid-recording. Case-insensitive (true/True/TRUE all work); anything else, including 1/yes, leaves the feature off.
- PLAYBACK_DETECTION=${PLAYBACK_DETECTION:-false} # Set to TRUE to hold the stream until the device reports audio playing and the picture moving, then start on a keyframe, so recording begins on the program, not the loading screen. Requires adb; network tuners only. Case-insensitive; anything but true leaves it off.
- PLAYBACK_STATIC_TIMEOUT=${PLAYBACK_STATIC_TIMEOUT} # Only used with PLAYBACK_DETECTION=TRUE. Seconds the box may keep its prior player/session before the check falls back to gating on motion alone. Default 2 suits Ospreys; apps like DirecTV that hold one player across channel changes need more. 0 or unset uses the default.
- PLAYBACK_DELAY=${PLAYBACK_DELAY} # Hold every tune this long before handing the DVR the program, so a slow-starting app still records within the DVR's 30s window. Black or a mounted pre-roll fills the wait; the box's own video is never passed through. Accepts a bare number (seconds) or a duration like 30s/1m, capped at 10m. Network tuners only. Empty or 0 disables it.
- ENCODER_CODEC=${ENCODER_CODEC:-h264} # The video codec your encoder outputs: h264 (default) or h265. Filler black/pre-roll must match it, or playback won't cross to the program at hand-off. An H.264 pre-roll is refused on an H.265 encoder (falls back to black). Leave at h264 unless your encoder is H.265. Case-insensitive; h265/hevc both work.
- HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-0} # In supported scripts (currently osprey), seconds between keepalive keyevents sent during playback to stop the app's UI inactivity timer from resetting the stream. Set to 0 to disable.
# โโ NVIDIA GPU โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Used by the CUDA caption engine and any CMDn calling h264_nvenc/hevc_nvenc. Needs the NVIDIA container toolkit.
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES} # For the CUDA caption engine and/or an NVENC CMDn. Set to all alongside DOCKER_RUNTIME=nvidia to expose an NVIDIA GPU. Empty means no GPU and is the default.
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES} # Set to compute,utility for the CUDA caption engine. A CMDn using h264_nvenc/hevc_nvenc also needs video - use compute,utility,video (or all).
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
- ${HOST_DIR}/ah4c/captions:/opt/captions # Closed caption settings, and the speech model, engine and any GPU driver downloaded from the Closed Captions page. Stays empty unless you turn captions on
- ${PREROLL_FILE:-${HOST_DIR}/ah4c/preroll}:/opt/preroll # A video or still image shown to the DVR instead of NULL packets, during a PLAYBACK_DELAY/PLAYBACK_DETECTION hold or a NULL_FRAME_INSERTION stall. Set PREROLL_FILE to a host path, or drop the file into this directory. Anything ffmpeg reads; prepared once at startup, loops until the real stream is ready
restart: unless-stopped
And then, based on the Docker Compose you posted earlier, use this set of env vars overrides (if any changes of values are needed make them here, but I don't believe there will be):
TAG=latest
CONTAINER_NAME=ah4c
HOSTNAME=ah4c
DOMAIN=localdomain
DOCKER_RUNTIME=nvidia
GPU_DEVICE=/dev/null
HOST_PORT=7654
IPADDRESS=192.168.1.28:7654
NUMBER_TUNERS=5
TUNER1_IP=192.168.1.71
ENCODER1_URL=http://192.168.1.70:8090/stream0
CMD1=ffmpeg -ss 5 -i ${ENCODER1_URL} -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
TUNER2_IP=192.168.1.72
ENCODER2_URL=http://192.168.1.70:8090/stream1
CMD2=ffmpeg -ss 5 -i ${ENCODER2_URL} -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
TUNER3_IP=192.168.1.73
ENCODER3_URL=http://192.168.1.70:8090/stream2
CMD3=ffmpeg -ss 5 -i ${ENCODER3_URL} -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
TUNER4_IP=192.168.1.74
ENCODER4_URL=http://192.168.1.70:8090/stream3
CMD4=ffmpeg -ss 5 -i ${ENCODER4_URL} -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
TUNER5_IP=192.168.1.75
ENCODER5_URL=http://192.168.1.70:8090/stream4
CMD5=ffmpeg -ss 5 -i ${ENCODER5_URL} -c:v h264_nvenc -preset hq -vf eq=brightness=0.2:contrast=1.5:saturation=2,unsharp=5:5:1.0:5:5:0.0 -pix_fmt yuv420p -b:v 70M -minrate 50M -maxrate 95M -bufsize 150M -c:a copy -f mpegts -
TUNER6_IP=
ENCODER6_URL=
CMD6=
TUNER7_IP=
ENCODER7_URL=
CMD7=
TUNER8_IP=
ENCODER8_URL=
CMD8=
TUNER9_IP=
ENCODER9_URL=
CMD9=
STREAMER_APP=scripts/zinwell/livetv
PYATV=false
CHANNELSIP=192.168.1.28
ALERT_SMTP_SERVER=
ALERT_AUTH_SERVER=
ALERT_EMAIL_FROM=
ALERT_EMAIL_PASS=
ALERT_EMAIL_TO=
ALERT_WEBHOOK_URL=
LIVETV_ATTEMPTS=
CREATE_M3US=false
UPDATE_SCRIPTS=true
UPDATE_M3US=true
TZ=America/New_York
SPEED_MODE=false
KEEP_WATCHING=
AUTOCROP_CHANNELS=
LINKPI_HOSTNAME=
LINKPI_USERNAME=
LINKPI_PASSWORD=
USER_SCRIPT=
NULL_FRAME_INSERTION=false
PLAYBACK_DETECTION=false
PLAYBACK_STATIC_TIMEOUT=
PLAYBACK_DELAY=
PREROLL_FILE=
ENCODER_CODEC=h264
HEARTBEAT_INTERVAL=
NVIDIA_VISIBLE_DEVICES=GPU-33f9ffcc-3c0a-1d8c-e41d-5cfeaa106512
NVIDIA_DRIVER_CAPABILITIES=all
HOST_DIR=/data
This will be a great help to us, as we haven't been able validate our standard Docker Compose with an NVIDIA user yet.
no dice logs below:
Plus every time I update ah4c, I have to re approve adb on my zinwells. This gets really annoying.
edit: Docker logs below:
reverted my stack started working immediately
That was my fault last time, I missed the way you were doing your bind mounts, which doesn't use a common parent for:
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
- ${HOST_DIR}/ah4c/captions:/opt/captions # Closed caption settings, and the speech model, engine and any GPU driver downloaded from the Closed Captions page. Stays empty unless you turn captions on
- ${PREROLL_FILE:-${HOST_DIR}/ah4c/preroll}:/opt/preroll # A video or still image shown to the DVR instead of NULL packets, during a PLAYBACK_DELAY/PLAYBACK_DETECTION hold or a NULL_FRAME_INSERTION stall. Set PREROLL_FILE to a host path, or drop the file into this directory. Anything ffmpeg reads; prepared once at startup, loops until the real stream is ready
What does this mean? Are you saying everything is fixed now, and working as it should with your original stack?
This looks like the most telling part to me. I'm thinking there's something wrong with your ffmpeg command. You might try starting with a simpler ffmpeg command, and then build from there to see if you can figure out where it's failing:
[EXECUTE] Running [./scripts/zinwell/livetv/bmitune.sh 021 192.168.1.71]
[mpegts @ 0x3dbf0740] Before avformat_find_stream_info() pos: 0 bytes read:21172 seeks:0 nb_streams:2
[mpegts @ 0x3dbf0740] After avformat_find_stream_info() pos: 1165036 bytes read:1167292 seeks:0 frames:104
http://192.168.1.70:8090/stream0: could not seek to position 13119.573
Input #0, mpegts, from 'http://192.168.1.70:8090/stream0':
Duration: N/A, start: 13114.573322, bitrate: N/A
Program 1
Metadata:
service_name : HDMI-1
service_provider: Server
Stream #0:0[0x64]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709, progressive), 1920x1080, 60 fps, 120 tbr, 90k tbn
Stream #0:1[0x65]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 129 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (h264_nvenc))
Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
[AVFilterGraph @ 0x3f634c40] No such filter: 'eq'
Error reinitializing filters!
Failed to inject frame into filter network: Filter not found
Error while processing the decoded data for stream #0:0
Conversion failed!
it works without cmd using my original stack.
ffmpeg runs fine with those options on host machine.
Try running it with the Channels DVR version of ffmpeg (shipped with CDVR server). We switched to that earlier this year due to the MagicYUV exploit, as Channels doesn't enable MagicYUV in their ffmpeg builds.
where would that be located.
found it one moment
it fails with that ffmpeg
edit: Works fine with the ubuntu ffmpeg
I'll have to think about how or if we can address this in the build right now. We had multiple requests to move away from the vulnerable version, and switching to CDVR's build made the most sense.
Understood. Thanks. Let me know what you come up with.
That build actually limited me with the pre-roll functionality because I was unable to convert H.264 to H.265 in software, there was just no way to do it. So when stitching the pre-roll into the actual video, it has to match the same codec. And for whatever reason, their version of FFmpeg.Channel is bundled with doesn't support H.265 transcoding.