HDMI for Channels

Agreed, just sharing real-world experience with this experiment so far, so others know what to expect, before buying hardware and diving in.

I'm having some problems with the channel guide mappings though. I handled them all manually. I'm unsure why some have numbers to the left of their logo (70, 106, 91, 24, 49, 108) and others don't.

Most work fine, but E!, Bravo and USA are off by 3 hours from the original guide that I see on YTTV, and I can't figure out how to fix or adjust them. When I search for a zip code and assign a local cable company, and then refresh, I notice later that added provider is removed.

I tried different matches for the same channel, and then refresh and wait a while, but none seem to stick or ever display with the proper guide data for what's playing now. Also, searching for "E" or "E!" on "Search All Lineups" just spins and spins, no selections offered.`

I then tried adding tvg-shift="+3" (and also tvg-shift="-3") to the M3U for these channels, refreshed and waited for guide data to fully repopulate but it didn't make any changes.

#EXTINF:-1 channel-id="Bravo" tvc-guide-placeholders="86402", tvg-shift="+3, Bravo
http://10.0.1.21:7654/play/tuner/bravo

What am I doing wrong? And do I need "tvc-guide-placeholders" at all? This tag just has successive numbers that start at 86400, but I'm not sure why or if that's actually necessary in this context.

Any feedback or ideas appreciated.

2 Likes

Shouldn't that be tvg-shift="+3" ?

can't have a comma in here

this is normal and harmless

this is confusing but normal. you don't need to add more providers any more now that there's a Search All

here are the station ids for for those three est vs pst

//  "usa", "58452",
//  "usap", "74030",
//  "e", "61812",
//  "ep", "91579",
//  "bravo", "58625",
//  "bravop", "73994",

Great, thanks!

I also found the answer to this question:

Answered fully here:

When your custom channel has no guide data, Channels will create airings for your channel. This way you can record them. It will even create special titles, series IDs, and program IDs based on the time slot so that you can make a Series Pass for them. By default it creates them with 1 hour durations. But you can control this yourself by providing their duration in seconds.
tvc-guide-placeholders: Duration of the placeholder. comma delimited. example (2 hours): "7200"
You can set the value to "false" to tell Channels to not make any placeholder airings at all. Setting the value to 24 hours or longer ("86400") will create 24 hour airings, but will drop the extra titles it creates for these airings.

2 Likes

Yep, I've been using the HD version of the CwGTV and it's been fine. As a general streaming device I was disappointed by it a couple of years ago given how limited the storage is. This bit of good news notwithstanding: Chromecast with Google TV HD has extra storage available

I was just tinkering with it, installed a bunch of core apps, and filled it up in no time! But for HDMI-IPTV streaming, this dongle seems like a perfect fit. And the price is right. As far as performance goes, the length of time from clicking the channel -- which sends the adb commands on my server to wake the dongle, go to its home page, launch the YouTube TV app directly to the desired channel and start streaming... is about 5-6 seconds on my setup. Not too bad, and I'm grateful to be able to get these channels integrated back into the DVR. And PQ is great, too! Not sure what I expected, but I'm impressed. Most of all, I really appreciate the flexibility this project inserts into the mix.

For anyone following along, or who might have the same ingredients, this is the M3U that's working for me with the channels I've added from YouTube TV, working with proper guide data on the west coast:

#EXTM3U

#EXTINF:-1 channel-id="NBC",NBC
http://10.0.1.21:7654/play/tuner/nbc

#EXTINF:-1 channel-id="MSNBC",MSNBC
http://10.0.1.21:7654/play/tuner/msnbc

#EXTINF:-1 channel-id=E!" tvc-guide-stationid="61812"  tvg-shift="+3",E!
http://10.0.1.21:7654/play/tuner/e!

#EXTINF:-1 channel-id="Bravo" tvc-guide-stationid="58625",Bravo
http://10.0.1.21:7654/play/tuner/bravo

#EXTINF:-1 channel-id="Oxygen",Oxygen
http://10.0.1.21:7654/play/tuner/oxygen

#EXTINF:-1 channel-id="USA", tvc-guide-stationid="58452" tvg-shift="+3",USA
http://10.0.1.21:7654/play/tuner/usa

#EXTINF:-1 channel-id="SyFy" tvg-shift="+3",SyFy
http://10.0.1.21:7654/play/tuner/syfy

#EXTINF:-1 channel-id="CNBC",CNBC
http://10.0.1.21:7654/play/tuner/cnbc

#EXTINF:-1 channel-id="Golf",Golf
http://10.0.1.21:7654/play/tuner/golf

#EXTINF:-1 channel-id="NFL",NFL Network
http://10.0.1.21:7654/play/tuner/nfl

#EXTINF:-1 channel-id="NewsNation",NewsNation
http://10.0.1.21:7654/play/tuner/newsnation

#EXTINF:-1 channel-id="MTV Classic" tvg-shift="+9",MTV Classic
http://10.0.1.21:7654/play/tuner/mtvclassic

#EXTINF:-1 channel-id="BBC News",BBC News
http://10.0.1.21:7654/play/tuner/bbcnews

#EXTINF:-1 channel-id="Smithsonian" tvc-guide-stationid="65799", Smithsonian Channel
http://10.0.1.21:7654/play/tuner/smithsonian

FWIW I did try the PST station IDs first for E!, USA, SyFy, etc. but the guide data wasn't lining up. Only when I used the EST station IDs with the 3 hour shift, was I able to get them to line up :man_shrugging:

I also just received the ONN 4K box, so will set it up later this week with the same channels as a "second tuner" via the 2nd IPTV encoder I got off eBay. I'm curious to see if the adb commands work the same. It'll also be interesting to see how it compares, performance wise, to the first tuner. Stay tuned! :slight_smile:

2 Likes

The Smithsonian Channel is another great candidate for this, I've added it to the HDMI mix:

Here is my working bmitune.sh file:

#!/bin/bash
HOME="input keyevent KEYCODE_HOME; sleep 1"
PRIME1="input keyevent 19 19 19 19; sleep 1; input keyevent 21 21 21; sleep 1; input keyevent 22; sleep 1; input keyevent 23; sleep 1"
PRIME2="input keyevent 19; sleep 1"
PRIME3="input keyevent --longpress 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67"
SEARCH1="input keyevent 66; sleep 2"
SEARCH2="input keyevent 66"


#NBC
if [ $1 = "nbc" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/9iwfkw-dMAw?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#MSNBC
if [ $1 = "msnbc" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/q6bWEVqhP8o?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#E!
if [ $1 = "e!" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/ILTrUfLFrHI?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#Bravo
if [ $1 = "bravo" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/xNk2Sv4t4Tc?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#Oxygen
if [ $1 = "oxygen" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/v4upAc0UExk?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#USA
if [ $1 = "usa" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/DJ7m0fdLKEY?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#SYFY
if [ $1 = "syfy" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/2_WogcoZ1cY?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#CNBC
if [ $1 = "cnbc" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/GIBoX-XF5i0?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#Golf
if [ $1 = "golf" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/XK34g7QRvGk?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#NFL Network
if [ $1 = "nfl" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/_pYg9qMKKIA?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#NFL Network
if [ $1 = "newsnation" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/ZIzM3eNrylg?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#MTV Classic
if [ $1 = "mtvclassic" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/isxl2N52bUQ?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#BBC News
if [ $1 = "bbcnews" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/g5BmB1qXulc?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

#Smithsonian Channel
if [ $1 = "smithsonian" ];then
HOME="input keyevent KEYCODE_HOME; sleep 1"
adb shell am start -a android.intent.action.VIEW -d https://tv.youtube.com/watch/c05ACdzJxiE?onboard=1 -n com.google.android.youtube.tvunplugged/com.google.android.apps.youtube.tvunplugged.activity.MainActivity
fi

1 Like

So how does this integrate with streamlinks to start and record the NBC channels directly, i.e. not with YTTV but directly on specific apps? You have to run both containers?

To clarify, I’m not actually recording with YTTV. (And those other NBC apps don’t have cloud recording functionality either, their content is “on demand” instead and often with commercials.)

So the way this is working is, the stream that’s launched on the Android dongle is fed through the HDMI>IPTV encoder, and Channels DVR is then recording it like all of its other custom sources. This setup doesn't exit the Channels app, your interactions on the client remain there and you still use the Channels interface to pause, skip back, etc. The IPTV feed simply acts like a live channel you're tuned into.

All things considered, it's a clever and effective workaround for the DRM turd that NBCU dropped in our punchbowl last month. And as I've also discovered, a great way to pull in live streams that were previously unavailable to my CDVR setup too, such as MTV Classic, NewsNation, The Smithsonian Channel, BBC World News, etc.

Anyway, back to your question. Your own bmitune.sh file could launch different streamlinks for whatever you channels you choose instead, and it could work similarly. You'd just need to code it so your adb key sequence gets to the intended playing video, as not all apps begin streaming automatically, by default, upon launch.

These lists for “launching apps” and “live TV” may help get you started: Stream Link URLs

1 Like

I have my own setup working with one of these encoders, but I use a script to tail the log file looking for specific channels to kick off and tune the remote device and then to stop it. However, there are reasons why this method might be better so I'd like to switch to it.

Currently, my custom channel for USA is:

#EXTINF:-1 channel-number="101" tvg-logo="https://tmsimg.fancybits.co/assets/s11207_ll_h15_af.png?w=360\u0026h=270" tvc-stream-vcodec="h264" tvc-stream-acodec="aac" tvc-guide-stationid="11207" tvg-name="USA", USA
http://192.168.1.24/0.ts

which is quite a bit different than an example above:

#EXTINF:-1 channel-id="USA", tvc-guide-stationid="58452" tvg-shift="+3",USA
http://10.0.1.21:7654/play/tuner/usa

Since I am on Spectrum, I'd like to keep my channel numbers, and I'm assuming the guide data would need to come from my Spectrum lineup. Do I need to change anything other than the URL?

And right now the Stream Format is set to MPEG-TS. Do I need to change it to StreamLink?

2 Likes

Well, I answered my own questions. When I tried to get it working last night I accidentally put in the wrong IP of my androidhdmi-for-channels server. Fixing that has made it work with the guide setup as I have it, so all I had to do was change the URL.

Nice job! :partying_face:

Now you've got me curious about this script, can you share more details about it here?

There is another post on the forum about using tail to parse the channels-dvr.log file, so I took that and modified it for my own use. Since at the time (a month ago!) there wasn't a mechanism to start, tune, and stop a remote device like a STB or Shield, I modified the script to look for phrases like "Starting live stream", "Finished job", etc., then parsed out the channel number and sent it to my own tuning setup that uses EventGhost on a Windows PC.

I'm happy to share the script but I'm not sure how useful it is now that we have the androidhdmi solution. But it's a good learning tool possibly so here it is. Note that some things like the channel substitution and the URL at the end to send an event message to EventGhost are very specific to my setup, which I'm not quite ready to reveal all the details of.

And, to be clear, this is a Linux script. I am running Channels on Unraid, so I set this up as a User Script that runs in the background of Unraid.

#!/bin/bash

EG="http://192.168.1.14:8088/index-blank.htm?WebCtrl."
LOG1="/mnt/user/Fileshare/cdvr/swc-log.txt"

tail -Fn0 "/mnt/user/appdata/channels-dvr/data/channels-dvr.log" | \
while read line ; do

# For each log file line read, reset these values. Channel number, started flag, and/or
#   ended flag will be set according to what is parsed out.

  channel=0
  ended=0
  started=0

# Example: 2023/05/08 11:10:26.556892 [DVR] Recording for job 1683561600-ch6033 from 
#           TVE-Spectrum ch6033 into "TV/Friends/Friends S06E08 1999-11-18 The One With 
#           Ross Teeth 2023-05-08-1110.mpg" for 22m34.24945689s

  echo "$line" | egrep -s "Recording for job"
  if [ $? = 0 ]
  then
    data=$(echo ${line} | cut -d' ' -f 10) # cut 10th field using blank as separator
    prefix=`echo ${data} | cut -b 1-2`     # cut characters 1-2
	if [[ $prefix = "ch" ]]
	then
	  channel=`echo ${data} | cut -b 3-5`  # cut characters 3-5
	else
	  channel=`echo ${data} | cut -b 1-3`  # cut characters 1-3
	fi
	started=1
    echo Job Started for Channel "$channel" >> "$LOG1"
  fi

# Example: 2023/05/07 23:55:21.563204 [HLS] Starting live stream for channel 167 
#           from 192.168.1.114

  echo "$line" | egrep -s "Starting live stream | Opened connection"
  if [ $? = 0 ]
  then
    data=$(echo ${line} | cut -d' ' -f 9)
    prefix=$(echo ${data} | cut -b 1-2)
	if [[ $prefix = "ch" ]]
	then
	  channel=`echo ${data} | cut -b 3-5`
	else
	  channel=`echo ${data} | cut -b 1-3`
	fi
	started=1
    echo Live Stream Started for Channel "$channel" >> "$LOG1"
  fi

# Example: 2023/05/10 20:03:00.000488 [TNR] Closed connection to M3U-CustomWebChannels
#            for ch161 Magnolia

  echo "$line" | egrep -s "Closed connection"
  if [ $? = 0 ]
  then
    data=$(echo ${line} | cut -d' ' -f 9)
    prefix=$(echo ${data} | cut -b 1-2)
	if [[ $prefix = "ch" ]]
	then
	  channel=`echo ${data} | cut -b 3-5`
	else
	  channel=`echo ${data} | cut -b 1-3`
	fi
	ended=1
    echo Closed Connection to Channel "$channel" >> "$LOG1"
  fi

# Example: 2023/05/07 23:31:00.035136 [DVR] Finished job 1683518340-ch168 Modern Family
# Example: 2023/05/08 11:21:14.509105 [DVR] Job cancelled: 1683561600-ch6033 Friends
  
  echo "$line" | egrep -s "Finished job | Job cancelled"
  if [ $? = 0 ]
  then
    data=$(echo ${line} | cut -d' ' -f 6)
    prefix=`echo ${data} | cut -b 12-13`
	if [[ $prefix = "ch" ]]
	then
	  channel=`echo ${data} | cut -b 14-16`
	else
	  channel=`echo ${data} | cut -b 12-14`
	fi
	ended=1
    echo Job Finished for Channel "$channel" >> "$LOG1"
  fi

# Example: 2023/05/08 00:01:07.716137 [ENC] Stopped encoder for ch167 in 
#           /shares/DVR/Streaming/ch167-dANY-ip192.168.1.114-837426963/encoder-1-1133237114 
#           after encoding 1 to 343
  
  echo "$line" | egrep -s "Stopped encoder"
  if [ $? = 0 ]
  then
    data=$(echo ${line} | cut -d' ' -f 7)
    prefix=`echo ${data} | cut -b 1-2`
	if [[ $prefix = "ch" ]]
	then
	  channel=`echo ${data} | cut -b 3-5`
	else
	  channel=`echo ${data} | cut -b 1-3`
	fi
	ended=1
    echo Job Cancelled or Encoder Stopped for Channel "$channel" >> "$LOG1"
  fi

# Channel substitution as needed for actual Spectrum channel numbers

  if [[ $channel = "101" ]]
  then
    channel=46
  elif [[ $channel = "111" ]]
  then
    channel=65
  elif [[ $channel = "131" ]]
  then
    channel=131
  elif [[ $channel = "161" ]]
  then
    channel=161
  elif [[ $channel = "167" ]]
  then
    channel=76
  elif [[ $channel = "168" ]]
  then
    channel=49
  elif [[ $channel = "205" ]]
  then
    channel=43
  elif [[ $channel = "310" ]]
  then
    channel=310
  elif [[ $channel = "318" ]]
  then
    channel=318
  else
    channel=0
  fi

# If channel has been set from our list then need to send to EventGhost
# But if the job/stream has ended then send Channel Zero

  if [[ $channel != 0 ]] && [[ $started = "1" || $ended = "1" ]]
  then
    date >> "$LOG1"
    echo --- Channel is "$channel" Started flag "$started" Ended flag is "$ended" >> "$LOG1"
	if [[ $ended = "1" ]]
	then
	  channel=0   # Have to set channel to zero here to tell EventGhost to end it
      date >> "$LOG1"
      echo --- End of Job so Channel set to 0 >> "$LOG1"
	fi
    curl -s -o /dev/null "$EG""$channel"
  fi

done
2 Likes

I meant to share that article here yesterday. There’s also a big difference between well-known actual Android TV dongles like the CCwGTv dongle and Onn.TV puck, and those super cheapo boxes running some older version of basic Android, identified as a Nexus tablet or whatever, with various apps and repositories pre-installed on them to facilitate piracy.

And yes, malware too.

1 Like

I have an Onn TV 4K and started experimenting with it last night. After installing and setting up adb and enabling developer mode, I got it to tune MSNBC in YTTV by sending the adb command (copied from the bmitune.sh file in this thread) from the Windows PC hosting Channels DVR. (I don't have an HDMI encoder yet, still investigating).

1 Like

Let's mix this up a bit and take a look at Roku.

For whatever reason, Roku devices have an actual, but somewhat limited, REST API. In addition, Roku provides a "Deep Linking Tester" tool that can be used to figure out how to link to specific content items.

Looking at YouTube TV, the following configuration will get you ESPN.
Note: assumes cURL is available.

prebmitune.sh

#!/bin/bash
# Loads home screen to set the device to a known state. Probably not required.
ROKU_TARGET=ip.address.of.roku
curl -d '' "http://$ROKU_TARGET:8060/keypress/home"

bmitune.sh

#!/bin/bash
# 195316 is Roku's application id for YouTube TV
# YouTube TV content ids can be pulled from the address bar when viewing a channel on a PC.

if [ $1 = "espn" ];then
    TARGET_CONTENT_ID=k-KlMzmHTAo
    curl -d '' "http://$ROKU_TARGET:8060/launch/195316?contentId=$TARGET_CONTENT_ID&mediaType=live"
fi

stopbmitune.sh

#Loads home screen and stops video playback.
curl -d '' "http://$ROKU_TARGET:8060/keypress/home"

That's it.

For many reasons I dislike Roku, but for this application a cheap Roku device might actually be a good choice.

3 Likes

This is fascinating stuff.
Thinking about trying some of this, but I am a Windows user, and pretty far from what would be called a programmer. I am a tech head though, and program industrial equipment, just a little different...LOL
I'm hoping some version of this gets incorporated into channels..

1 Like

Just for reference for people who are interested in Spectrum on Roku - the channel ID for the Spectrum app is 23048. I'm able to get the app itself to launch with this curl command

curl -d '' "http://$ROKU_TARGET:8060/launch/23048"

but I have not yet figured out what the launch parameters are to open a specific channel or even if those exist on this app to begin with.

I've been trying a number of things with the Spectrum app on a Roku for several days to no avail. I suppose you could brute force a channel with a script by assuming the channel that pops up is the last one played, which always seems to be the case, but the script would be flying blind.

1 Like

The Roku's API is indeed easy, and thanks for the example script snips. Wouldn't that be an interesting turn of the worm if these become the defacto easy option as a front-end for the HDMI input into Channels!

2 Likes