M3U from Tablo

I know Tablo isn't supported, but I wanted to test out the M3U capability with Tablo.

I was able to grab the M3U path using Chrome Dev Tools.

In Channels I created a Text M3U Playlist for a single station

#EXTM3U
#EXTINF:-1
http://192.168.1.92/stream/pls.m3u8?ID2AlU3IkDc6cY2SE49FNA&fmt=v4

It says 1 channel found and when I tune it, it plays. But it only plays a clip that is a few seconds long over and over again.

When I open that URL in a browser. It downloads a new M3U file named pls.m3u8. In there is a long playlist of streams.

If I wait a minute and download that M3U file again, it has appended many more streams into the file.

Is Channels capable opening this playlist, refresh it for the appended streams, and play them in sequential order?

Example of the M3U8 playlist

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-TARGETDURATION:1
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:1.001,
#EXT-X-PROGRAM-DATE-TIME:2021-02-18T22:59:35.000Z
#EXT-X-BYTERANGE:681876@0
/stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ
#EXTINF:1.001,
#EXT-X-PROGRAM-DATE-TIME:2021-02-18T22:59:36.001Z
#EXT-X-BYTERANGE:894316@681876
/stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ
#EXTINF:1.001,
#EXT-X-PROGRAM-DATE-TIME:2021-02-18T22:59:37.002Z
#EXT-X-BYTERANGE:1410188@1576192
/stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ
#EXTINF:1.001,
#EXT-X-PROGRAM-DATE-TIME:2021-02-18T22:59:38.003Z
#EXT-X-BYTERANGE:871944@2986380
/stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ
#EXTINF:1.001,
#EXT-X-PROGRAM-DATE-TIME:2021-02-18T22:59:39.004Z
#EXT-X-BYTERANGE:850700@3858324
/stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ
#EXTINF:1.001,
#EXT-X-PROGRAM-DATE-TIME:2021-02-18T22:59:40.005Z
#EXT-X-BYTERANGE:766100@4709024
/stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ

1 Like

Thanks for the example. This is not something we currently support, but it should be possible to add.

2 Likes

Some some useful information if you're interested in adding Tablo support. I've been messing with some API calls.

Get settings from the unit
GET http://192.168.1.92:8885/settings/info

{"led":"on","recording_quality":"/settings/recording_qualities/10","extend_live_recordings":false,"auto_delete_recordings":false,"exclude_duplicates":false,"fast_live_startup":true,"audio":"aac","livetv_quality":"/settings/recording_qualities/10"}

Get a list of available channels
GET http://192.168.1.92:8885/guide/channels

["/guide/channels/767579","/guide/channels/767580","/guide/channels/767581","/guide/channels/767582","/guide/channels/767570","/guide/channels/767583","/guide/channels/767584","/guide/channels/767585","/guide/channels/767586","/guide/channels/767587","/guide/channels/767588","/guide/channels/767571","/guide/channels/767572","/guide/channels/767573","/guide/channels/767574","/guide/channels/767575","/guide/channels/767576","/guide/channels/767577","/guide/channels/767589","/guide/channels/767590","/guide/channels/767578"]

Get info on a channel
GET http://192.168.1.92:8885/guide/channels/767579

{"object_id":767579,"path":"/guide/channels/767579","channel":{"call_sign":"removed-HD","call_sign_src":"removed-HD","major":7,"minor":1,"network":"CW","resolution":"hd_720"}}

Get a playlist url for a channel
POST http://192.168.1.92:8885/guide/channels/767579/watch

{"token":"09148319-7e38-426a-a4c0-7d4d9c400b59","expires":"2021-02-19T02:15:49Z","playlist_url":"http://192.168.1.92:80/stream/pl.m3u8?8l_dbs7hs09z67fXyq6gWw","bif_url_sd":null,"bif_url_hd":null,"video_details":{"width":1280,"height":720}}

3 Likes

I'd be willing to provide access via a VPN if you want to do some testing at some point.

This isn't something we're interested in integrating directly into Channels. But again, if someone were to put in the effort, I bet a project could be built around the stuff you're figuring out to make it easier to integrate with Channels using the Custom Channels feature.

Good work on this investigation!

1 Like

Fair enough. I had it laying around and was bored. If anyone wants to continue this I'll be happy to provide some help or testing.

2 Likes

Please press-and-hold on the Check For Updates button in the Settings page of your DVR. Try playing that m3u8 again and let me know if it works.

3 Likes

You guys did it again. It seems to be working really well.

Now I'm curious how hard the reported expiration date on the playlist URL per channel is.

I think OP asked not about integrating Tablo support directly into channels but to add support for sequential M3u8 playlists.

@TGZRyo I assume you need some script to create M3U tablo playlist from the API Calls?
with VPN connection Is it possible to watch channels from your box using Tablo app on iPad?

EDIT: Ok, I saw post higer and I see it is working now for you, great!

Yeah it's working quite well. I have an HDHomeRun so this is more of a hobby thing at the moment.

It appears the link generated via the Tablo API expires after 6 hours and 20 minutes. I might make a script that makes API calls to the Tablo to generate new playlists per channel.

Does Channels DVR have an API I can call to pass an updated text format 'Source' to an existing playlist source I created?

Yep! And we got it. This is certainly within the bounds of our responsibility. We want to make sure these things work on our end, so you guys can do the other stuff on yours!

Yes, but as we always state, the API is private and we reserve the right to change it. It's listed below.

An even better way to do this would be to create a new project that essentially proxies the M3U. So, the project handles the fetching of the M3U from the Tablo, then you point Channels at the project and it gets served a sanitized M3U.

HTTP Method: PUT
Path: /providers/m3u/sources/$YOUR_M3U_NAME

Payload:

{
    "name": "IPTV",
    "type": "HLS",
    "source": "Text",
    "url": "",
    "text": "#EXTM3U\n\n#EXTINF:-1 tvg-ID=\"XXX\" tvg-name=\"XXX\" channel-number=\"530\" tvg-logo=\"XXX.png\" group-title=\"XXX\",XXX\nhttps://XXX.m3u8\n\n",
    "refresh": "",
    "limit": "",
    "satip": "",
    "numbering": ""
}

You can do a GET on that same URL to fetch your M3U. Then just update the text field with your new content and update it with the PUT.

1 Like

Could you PATCH with just the {"text":"…"}?

I thought about doing something like this and just hosting my own M3U that Channels would use. I see that Channels can be set to 'Never Refresh' or 'Refresh Daily'. Would it be possible to have this refresh more frequently? Like every 4 hours, 12 hours, Daily.

We can add more refresh options for the M3U.

I'm curious if you've found any API on the Tablo to list and download recordings?

Yes. I don't have storage attached to it right now to test functionality of playing them. But I was able to return info from the database.

GET http://192.168.1.92:8885/recordings/airings

["/recordings/series/episodes/580287","/recordings/series/episodes/580286","/recordings/series/episodes/580285","/recordings/series/episodes/580284","/recordings/series/episodes/580282","/recordings/series/episodes/580279","/recordings/series/episodes/452104","/recordings/series/episodes/388109","/recordings/series/episodes/380702","/recordings/series/episodes/365831","/recordings/series/episodes/353605","/recordings/series/episodes/343417","/recordings/series/episodes/329127","/recordings/series/episodes/321684","/recordings/series/episodes/318535","/recordings/series/episodes/313737","/recordings/series/episodes/306893","/recordings/series/episodes/299750","/recordings/series/episodes/292900","/recordings/series/episodes/285083","/recordings/series/episodes/277910","/recordings/series/episodes/195106","/recordings/series/episodes/79346","/recordings/series/episodes/79343","/recordings/series/episodes/79340"]

GET http://192.168.1.92:8885/recordings/series/episodes/79340

{"object_id":79340,"path":"/recordings/series/episodes/79340","series_path":"/recordings/series/79341","season_path":"/recordings/series/seasons/79342","snapshot_image":{"image_id":79349,"has_title":false},"airing_details":{"datetime":"2018-11-24T01:00Z","duration":1920,"channel_path":"/recordings/channels/15097","channel":{"object_id":15097,"path":"/recordings/channels/15097","channel":{"call_sign":"CBSX","call_sign_src":"CBSXX","major":XX,"minor":1,"network":"CBS","resolution":"hd_1080"}},"show_title":"Frosty the Snowman"},"video_details":{"state":"finished","clean":true,"cloud":false,"uploading":false,"audio":"aac","size":1804001280,"duration":2000,"width":1920,"height":1080,"schedule_offsets":{"start":-15,"end":64,"deprecated":true},"recorded_offsets":{"start":-15,"end":64},"airing_offsets":{"start":0,"end":0,"source":"none"},"seek":15,"error":null,"warnings":[]},"user_info":{"position":15,"watched":false,"protected":false},"episode":{"title":null,"description":"Based on the popular song with the same title, this holiday classic tells the story of a snowman named Frosty, brought to life by a magic hat. As the temperature begins to rise, Frosty worries that he'll melt, so his human friends come up with a plan to put him on a train to the North Pole, where he'll never melt. But the owner of the magic hat, Professor Hinkle, realizes it's really magic, after all, and wants it back. As they journey toward the North Pole, the cold takes its toll on Frosty's human companion, Karen, and he seeks help from none other than Santa himself, who takes Karen home, Frosty to the North Pole and shames Professor Hinkle into letting Frosty keep the cap.","number":0,"season_number":0,"orig_air_date":"1969-12-07","tms_id":"SH000148960000"},"qualifiers":["cc"]}

1 Like

Unfortunately it looks like I can only have as many active playlist URLs as I have tuners. I was hoping I'd be able to generate a list of all available stations. Then create an M3U that I could use until the playlists expired.

Once I generate a third playlist and start watching, it will stop the first stream (which I expected). Then I have to generate a new playlist to watch a different channel.

For this to work properly I'd have to run a GET URL and POST it to Channels anytime I wanted to tune to a specific station. Either that or limit the project to two channels.

Here's additional API calls for recordings
M3U to watch a recording: POST http://192.168.1.92:8885/recordings/programs/airings/769550/watch
Delete a recording: DELETE http://192.168.1.92:8885/recordings/programs/airings/769550

Other random ones I documented
GET http://192.168.1.92:8885/server/info
GET http://192.168.1.92:8885/server/capabilities

Does it mean now it will work with AES encrypted m3u ? I asked about this in Hacks section but no response and I assumed playlist with sequence of chunks was not supported. So if I have the key can I play and decrypt such list or I need separate projects that decrypt stream and send it reencoded to channels directly?

I don't think it works thay way. I have 2 tuners in HDHomeRun and certainly CHannels contain internally playlist with all channels that are tuned from the air. Not sure why the Tablo would be any different, and you should use only one M3u for entire box, am I wrong?

also I see in your playlist each line in the stream is always the same /stream/segw.ts?YVP4BtOYiH4aI7s7icXEKQ Have you tried in VLC e.g. playing that?

1 Like