I am starting to work on an Android TV TIF (TV Input Framework) Plex frontend add-on for Android Live Channels for watching Live TV and Scheduling recordings through the plex api to the Plex Media Server backend.
I need a bit of help on how to query the PMS for a list of channels and xmltv epg either in xml format or sql format for the TIF to add channels and sync epg data into Live Channels.
I have been working with SQLite data from another Live Channels plugin and also examining “plexapp-rest-library” for querying such data and working with account syncing (AccountService.java) for getting the Plex Token for account sync.
Could someone in the dev community here point me in the correct direction for querying such data as live tv channels and xmltv data? I can see some channel data in the tv.plex.providers.epg.onconnect-hash.db database so I should be able to query this information for ChannelSync data in the Android TV Input Framework.
Any pointers are greatly appreciated
dane22
April 16, 2018, 9:05pm
2
Your best friend is Chrome browser in debug mode!
I did pull the avail channels for a tuner here:
https://github.com/ukdtom/epg-dk.bundle/blob/master/Contents/Code/ init .py#L296
YOU ARE THE MAN! Great place to start THANK YOU!
What would the api call with Plex Token to generate a channel list?
http://plex-ip-address ::32400/livetv/dvrs/&X-Plex-Token=xxxxxxxxxxxxxxxxxxxxxxxx
I’ll work on debugging and catching logs, looks like lots of segmented transport stream parts via /livetv/sessions still trying to catch a log on an actual json channel list and xmltv.db data with matching channel tvg-id’s. All the code is out there to implement this add-on I just need a bit of help from some more experienced android/java plex API developers:
Example for syncing plex epg xmltv.xml data and channel data in json format all we need is plex_link_channel_url and plex_link_epg_url.
XmlTvParser.TvListing listings = PlexUtil.getTvListings(context,
context.getString(R.string.plex_link_epg_url), PlexUtil.FORMAT_XMLTV);
XmlTvParser.TvListing channelListings = PlexUtil.getTvListings(context,
context.getString(R.string.plex_link_channel_url), PlexUtil.FORMAT_JSON);
listings.setChannels(channelListings.channels);
// channel entry
ContentValues values = new ContentValues();
values.put(TvContract.Channels.COLUMN_INPUT_ID, inputId);
values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, Integer.toString(entry.getNumber()));
values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, entry.getName());
values.put(TvContract.Channels.COLUMN_SERVICE_ID, 0);
values.put(TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID, 0);
values.put(TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID, entry.getUid());
values.put(TvContract.Channels.COLUMN_SERVICE_TYPE, entry.isRadio() ? TvContract.Channels.SERVICE_TYPE_AUDIO : TvContract.Channels.SERVICE_TYPE_AUDIO_VIDEO);
values.put(TvContract.Channels.COLUMN_TYPE, TvContract.Channels.TYPE_DVB_S2);
values.put(TvContract.Channels.COLUMN_SEARCHABLE, 1);
values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, Integer.toString(entry.getUid()));
// channel link needs Android M
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
values.put(TvContract.Channels.COLUMN_APP_LINK_POSTER_ART_URI, getUriToResource(context, R.drawable.banner_timers).toString());
values.put(TvContract.Channels.COLUMN_APP_LINK_INTENT_URI, link);
values.put(TvContract.Channels.COLUMN_APP_LINK_TEXT, context.getString(R.string.timer_title));
values.put(TvContract.Channels.COLUMN_APP_LINK_COLOR, Utils.getColor(context, R.color.primary_color));
values.put(TvContract.Channels.COLUMN_APP_LINK_ICON_URI, "");
}
Uri channelUri = existingChannels.get(entry.getNumber());
@dane22 said:
Your best friend is Chrome browser in debug mode!
I did pull the avail channels for a tuner here:
https://github.com/ukdtom/epg-dk.bundle/blob/master/Contents/Code/__init__.py#L296
How are you getting the list of channels via:
# Start by getting enabled channels
url = 'http://127.0.0.1:32400/livetv/dvrs'
I have been trying with my Plex Auth token and I must be missing some header or .json response file needed
Plex.tv · Arcanemagus/plex-api Wiki · GitHub
using:
curl -X "GET" "http://127.0.0.1:32400/livetv/dvrs'" \
-H "X-Plex-Version: 1.0.0" \
-H "X-Plex-Product: Plex Media Server" \
-H "X-Plex-Client-Identifier: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" \
--data-urlencode "user[password]=pw" \
--data-urlencode "user[login]=username"
dane22
April 17, 2018, 9:38pm
7
Ups…sorry
/media/grabbers/devices/**DEVICEKEY**/channels?X-Plex-Token=XXXXXXXXXXXX
dane22
April 17, 2018, 9:39pm
8
And you get the device key from the first call
@dane22 said:
Ups…sorry
/media/grabbers/devices/**DEVICEKEY**/channels?X-Plex-Token=XXXXXXXXXXXX
Perfect thanks a million dane22. Exactly what I needed
So perfect that lead me to find the header for stream info now to pipe that into a channelsync with transportstream data and then lineup the xmltv epg data (need to figure out this next)
:32400/livetv/sessions/77225251-e993-4bc0-97fb-94764cc6c98d?X-Plex-Token=xxxxxxxxxxxxxxxxxxxxxxxx
<MediaContainer size="1">
<Video type="clip" title="Live Session " summary="" index="1" ratingCount="0" genuineMediaAnalysis="1" key="/livetv/sessions/77225251-e993-4bc0-97fb-94764cc6c98d" live="1">
<Media videoResolution="720" width="1280" height="720" aspectRatio="1.78" audioChannels="2" audioCodec="ac3" videoCodec="mpeg2video" container="mpegts" origin="livetv" protocol="hls" uuid="77225251-e993-4bc0-97fb-94764cc6c98d">
<Part size="0" container="mpegts" protocol="hls">
<Stream streamType="1" codec="mpeg2video" index="0" closedCaptions="1" frameRate="59.940" height="720" level="4" pixelAspectRatio="1:1" profile="main" width="1280"/>
<Stream streamType="2" selected="1" codec="ac3" index="1" channels="2" bitrate="192" language="English" languageCode="eng" audioChannelLayout="stereo" samplingRate="48000"/>
</Part>
<TranscodeSession key="/transcode/sessions/77225251-e993-4bc0-97fb-94764cc6c98d" throttled="0" complete="0" progress="-1" speed="0.89999997615814209" duration="7200000" context="static" sourceVideoCodec="" sourceAudioCodec="" videoDecision="copy" audioDecision="copy" protocol="hls" container="mpegts" videoCodec="*" audioCodec="*" audioChannels="2" transcodeHwRequested="1" transcodeHwFullPipeline="0" timeStamp="1524004887.2486539" maxOffsetAvailable="110.663267" minOffsetAvailable="1"/>
</Media>
</Video>
</MediaContainer>
And some more media info in the chrome console
[Player] Timeline, {
"ratingKey": "com.gracenote.onconnect://episode/EP000014578224",
"key": "/livetv/sessions/77225251-e993-4bc0-97fb-94764cc6c98d",
"playQueueItemID": "2",
"state": "playing",
"hasMDE": 1,
"time": 518000,
"duration": 4294967296000
}
This gets the segmented transport streams in m3u8 which will play in vlc for testing but as stated it is segmented .ts parts so its not smooth or buffered. Good start for app dev just need the function calls now and im thinking i could learn something from https://github.com/NineWorlds/serenity-android Plexapp REST Library
:32400/livetv/sessions/77225251-e993-4bc0-97fb-94764cc6c98d/rs1eyndhqe9qtgb7qdrkfb9f/index.m3u8
just need to find the plex api call for gracenote xmltv output with matching plex channel ids and session info…
This definitely helps
"ratingKey": "com.gracenote.onconnect://episode/EP000014578224",
So basically makes sense that the m3u8 is segmented due to time-shift support so this should help when creating a large buffer at stream startup.
On android the link looks like this for livetv playback:
/livetv/sessions/de2138bc-ce52-4d6b-8441-32cacd853522/d151a70a0bcff461-com-plexapp-android /index.m3u8
Well this is interesting. In this FFMPEG streaming guide it segments all ts files into an m3u8 just as plex does:
http://www.bogotobogo.com/VideoStreaming/ffmpeg_http_live_streaming_hls.php
ffmpeg -i source.mp4 -map 0
-codec:v libx264 -codec:a libfaac
-f ssegment -segment_list playlist.m3u8
-segment_list_flags +live -segment_time 10
out%03d.ts
Here is plex ffmpeg segmenter command
'/usr/lib/plexmediaserver/Plex Transcoder' '-noaccurate_seek' '-ignore_unknown' '-scan_all_pmts' '-1' '-rw_timeout' '30000000' '-fflags' '+discardcorruptts+fillwallclockdts' '-i' 'http://192.168.1.218:5004/auto/v514' '-map' '0:V?' '-codec:V' 'copy' '-map' '0:a?' '-codec:a' 'copy' '-copypriorss:a' '0' '-map' '0:s?' '-codec:s' 'copy' '-segment_format' 'mpegts' '-f' 'ssegment' '-individual_header_trailer' '0' '-segment_time' '1' '-segment_start_number' '0' '-segment_time_delta' '0.0625' '-segment_list' 'http://127.0.0.1:32400/video/:/transcode/session/0d4ad6fe-217d-444b-9ddc-9cf6e6f50ac2/77baa0c9-8b02-4a93-89bc-557f9036e7bf/seglist' '-segment_list_type' 'csv' '-segment_list_size' '2147483647' '-segment_list_separate_stream_times' '1' '-max_delay' '5000000' '-map_metadata' '-1' '-map_chapters' '-1' 'media-%05d.ts' '-y' '-nostats' '-loglevel' 'quiet' '-loglevel_plex' 'error' '-progressurl' 'http://127.0.0.1:32400/video/:/transcode/session/0d4ad6fe-217d-444b-9ddc-9cf6e6f50ac2/77baa0c9-8b02-4a93-89bc-557f9036e7bf/progress'
I really need to find a way to GET actual channel id’s ie http://127.0.0.1:32400/livetv/stream/channelnumber/600
Just as tvheadend does for the frontend app to work in Android Live Channels…
127.0.0.1:9981/stream/channelnumber/600
Hmmm grepping logs I do get a unique channel id:
POST /livetv/dvrs/23/channels/600/tune
That doesnt seem to work but im getting close and im basically using this topic for notes so I can come back and see progress. Here are a few more GET commands for livetv info:
GET 127.0.0.1:32400/transcode/sessions/?X-Plex-Token=xxxxxxxxxxxxxxxxx >> enc.xml
GET 127.0.0.1:32400/livetv/sessions/?X-Plex-Token=xxxxxxxxxxxxxxxx >> livetv.xml
GET 127.0.0.1:32400/media/grabbers/devices/3/channels?X-Plex-Token=xxxxxxxxxxxxxxxxxx >> channels.xml
GET 127.0.0.1:32400/livetv/dvrs/?X-Plex-Token=xxxxxxxxxxxxxxxxx >> dvrs.xml