Our forum migration to Discourse is underway and scheduled to last through June 21. During the migration, the forums will be read-only, except for a single temporary forum (contents of which will not be getting transferred). Read our announcement post for more information about the forum migration.
Hey folks, there is a new Podcast category for forums https://forums.plex.tv/categories/podcasts
If you have not already, we suggest setting your Plex username to something else rather than email which is displayed on your posts in forum. You can change the username at https://app.plex.tv/desktop#!/account
Welcome to our forums! Please take a few moments to read through our Community Guidelines (also conveniently linked in the header at the top of each page). There, you'll find guidelines on conduct, tips on getting the help you may be searching for, and more!

Android Live Channels integration for Live TV and DVR Scheduling

matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

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 :smile:

Best Answer

«1

Answers

  • dane22dane22 Members, Plex Pass, Plex Ninja Posts: 10,922 Plex Ninja

    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

    I hate bugs - Tommy Lee Jones, MIB
    Join me in developing: epg-dk, str2utf-8, remidx, ExportTools, WebTools
    Support the Samsung Client:Donate
    Guides I use: Media Naming Guide, Local subtitles, Log-Files, QNAP FAQ, The Plex Dance

    NO Support via PM, unless called by me

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    YOU ARE THE MAN! Great place to start THANK YOU!

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 16

    What would the api call with Plex Token to generate a channel list?

    http://plex-ip-address::32400/livetv/dvrs/&X-Plex-Token=xxxxxxxxxxxxxxxxxxxxxxxx

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 17

    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());
    
  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 17

    @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

    https://github.com/Arcanemagus/plex-api/wiki/Plex.tv

    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"
    
  • dane22dane22 Members, Plex Pass, Plex Ninja Posts: 10,922 Plex Ninja
    Accepted Answer

    Ups....sorry

    /media/grabbers/devices/**DEVICEKEY**/channels?X-Plex-Token=XXXXXXXXXXXX

    I hate bugs - Tommy Lee Jones, MIB
    Join me in developing: epg-dk, str2utf-8, remidx, ExportTools, WebTools
    Support the Samsung Client:Donate
    Guides I use: Media Naming Guide, Local subtitles, Log-Files, QNAP FAQ, The Plex Dance

    NO Support via PM, unless called by me

  • dane22dane22 Members, Plex Pass, Plex Ninja Posts: 10,922 Plex Ninja

    And you get the device key from the first call

    I hate bugs - Tommy Lee Jones, MIB
    Join me in developing: epg-dk, str2utf-8, remidx, ExportTools, WebTools
    Support the Samsung Client:Donate
    Guides I use: Media Naming Guide, Local subtitles, Log-Files, QNAP FAQ, The Plex Dance

    NO Support via PM, unless called by me

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    @dane22 said:
    Ups....sorry

    /media/grabbers/devices/**DEVICEKEY**/channels?X-Plex-Token=XXXXXXXXXXXX

    Perfect thanks a million dane22. Exactly what I needed :)

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    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>
    
  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 17

    And some more media info in the chrome console :smile:

    [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
    }
    
  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    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",

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    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.

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    On android the link looks like this for livetv playback:

    /livetv/sessions/de2138bc-ce52-4d6b-8441-32cacd853522/d151a70a0bcff461-com-plexapp-android/index.m3u8

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 20

    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
    
  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    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'

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    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

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass

    Hmmm grepping logs I do get a unique channel id:

    POST /livetv/dvrs/23/channels/600/tune

  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 23

    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
    
  • matt.gorskimatt.gorski Members, Plex Pass Posts: 33 Plex Pass
    edited April 24

    This SEEMS* to be the way to export all epg data to xml (However not in standard xmltv.xml format)

    GET 127.0.0.1:32400/tv.plex.providers.epg.onconnect:23/all?X-Plex-Token=xxxxxxxxxxxxxxxxxx >> epgdata.xml

    *Don't try this in a browser only via terminal to file output ;)

«1
Sign In or Register to comment.