Documentation for api access/programming

Added by stepher ru 10 months ago

I've been sniffing around TVHeadEnd's website looking for docs on the api interface (that I've seen referred to in the forums) but have been unable to find it/them.

Could someone please provide a pointer to the right doc(s) or website area. Apparently I am finding myself somewhat incompetent over the past couple of days.

Thx and cheers.....


Replies (24)

RE: Documentation for api access/programming - Added by stepher ru 10 months ago

Appreciate the response. I should have been more clear. What I'm looking for are docs for programming thru the webgui api (i.e. using a command like "curl -s http://user:[email protected]:9981/api/dvr/entry/grid_upcoming...")

Thx and cheers....

Robert Cameron wrote:

A little out of date, but a start: http://tvheadend.org/projects/tvheadend/wiki/Htsp

RE: Documentation for api access/programming - Added by stepher ru 10 months ago

Thx for the link. However, that means I have to sort things out in the source code :( Anywhere those api calls might be set out in some kind of informative and organized reference manual somewhere?

Again, thx and cheers....

RE: Documentation for api access/programming - Added by Nic Butcher 8 months ago

Hello,

Did you find out how to do this in the end. I am also trying to do something similar with curl

curl -v "http://admin:[email protected]:9981/api/dvr/entry/filemoved" --data-urlencode "src=/storage/tvshows/xxxxx.ts" --data-urlencode "dst=/nas/tv/xxxxx.ts"

(not my real username / password obviously!)

I just get a 400 Bad request response

Thanks

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

Assuming your filenames don't have special characters, you could try the more straightforward:

curl -v 'http://admin:[email protected]:9981/api/dvr/entry/filemoved?src=/storage/tvshows/xxxxx.ts&dst=/nas/tv/xxxxx.ts'

If you've used the --http_root option then your root goes before the /api...

This function seems to only tells TVH that the file has been moved by other means, it does not actually move the file.

I've been tinkering with the HTTP API for a while and the lack of documentation is a nuisance. One day I'll write-up what I've learned and maybe others will add their own knowledge.

RE: Documentation for api access/programming - Added by Nic Butcher 8 months ago

Thanks Dave,

I'm not using the --http_root option (should I be?). And just to confirm that I am using rsync to move the files to my NAS. Unfortunately the filenames do contain special characters (e.g. spaces). In any case I understood that '/' was a special character i.e. the request needs to look something like this:

http://admin:[email protected]:9981/api/dvr/entry/filemoved?src=%2Fstorage%2Ftvshows%2Fxxxxx.ts&dst=%2Fstorage%2Fnas%2Ftv%2Fxxxxx.ts

Which was why I was using the --date-urlencode option to encode the source and data directories. (see also - http://tvheadend.org/issues/3818 )

I agree - there is a real shortage of documentation on this - especially some good examples. If I ever get this working I'd be glad to contribute to your write-up.

RE: Documentation for api access/programming - Added by Nic Butcher 8 months ago

Update - apologies - it looks like this was correct:

curl -s "http://admin:[email protected]:9981/api/dvr/entry/filemoved" --data-urlencode "src=/storage/tvshows/xxxxx.ts" --data-urlencode "dst=/nas/tv/xxxxx.ts" 

The reason I was getting a Bad request was a mistake in my parsing of the source and destination paths into the above command - Doh!

Anyway - in case anybody else is trying this, I can confirm the above works.

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

Oops...

I've started my user-written documentation of the API at https://github.com/dave-p/TVH-API-docs - much more to follow!

RE: Documentation for api access/programming - Added by ullix tv 8 months ago

Dave: great! an api docu is sorely needed.

What I am currently interested in -- at least I believe this is what I need -- is dvr/entry/create. Which unfortunately offers only 3 question marks :-(

It probably needs json coded info, as you find the files in */dvr/log/, so something like

{u'comment': u'none', u'files': [{u'filename': '/home/videos/tvheadend/myvideo.ts'}], ....and so forth

This string is correct when I write this into a file in */dvr/log/ under an existing filename. My attempts to post this from python2 with various ways of url endoding have all failed, making tvheadend crash.

Question: How do you post a json string? What goes after the final ? in this url:

http://user:[email protected]:9981/api/dvr/entry/create?

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

Last things first. A simple way of passing JSON to the API is to use HTTP POST rather than GET - no need then to url encode anything. From the command line do something like:

curl --data 'conf={ ... }' 'http://user:[email protected]:9981/api/dvr/entry/create'

As to the info to be provided, a json object is needed in the same format as the /dvr/log files, and it must be labelled 'conf' as in the curl example above. I don't know how much data is needed but these are the items specifically mentioned in the source code:

"config_name" - this should be the uuid of the profile which is used for the recording
"disp_title"
"disp_subtitle"
"stop"
"start"
"channel"
"files" (this should be an array as in the log files)

I have been tinkering with json inputs and it seems sometimes that the { } wrapping round the entire object should be left off.

One annoying 'feature' of the API is that there is no feedback in the event of error - you get the same error return right until you do everything perfectly when it suddenly works. Good luck!

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

I've done some experiments and this seems to be the minimum that will be accepted, though I haven't verified that the created timer actually records the wanted event.

curl --data 'conf={"start":1509397200,"stop":1509400800,"channelname":"Channel 5","title":{"eng":"Paddington Station 24/7"},"subtitle":{"eng":"More real-life dramas..."} }' 'http://user:[email protected]:9981/api/dvr/entry/create'

If successful the server returns the uuid of the created timer.

RE: Documentation for api access/programming - Added by Mark Clarkstone 8 months ago

Dave Pickles wrote:

I've done some experiments and this seems to be the minimum that will be accepted, though I haven't verified that the created timer actually records the wanted event.
[...]

If successful the server returns the uuid of the created timer.

Thanks for working on the API docs :). One quick question though, Github has a built-in wiki why not use that?

RE: Documentation for api access/programming - Added by ullix tv 8 months ago

Dave: great, works here as well! My failure had resulted from missing the "conf=" part. Make sure to mention it in your docu ;-)

So, the URL to use is:

http://user:[email protected]:9981/api/dvr/entry/create?conf={"enabled": true, "start": 1000, <other json info>}

My interest is to add a local video, e.g. from a digital camera, to the tvh registered recordings, to play it like a recording. Here is a simple Python2 script. The start/stop times will be listed in tvh plus/minus the default padding. Not sure whether there is an "any" language category? You can exchange "ger" to "eng" but it does not seem to matter if there is only one listed.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

""" 
usage: tvh_addfile.py

registers a local file in tvheadend as recorded by sending json formed conf info via http api:
http://user:[email protected]:9981/api/dvr/entry/create?conf={"enabled": true, "start": 1000, <other json info>}

If successful returns the uuid of the created timer
""" 

import json, urllib, time, datetime, subprocess

def datestr2num(string_date):
    """Convert Date&Time string YYYY-MM-DD HH:MM:SS to Unix timestamp; use default date on error""" 

    try:
        dt=time.mktime(datetime.datetime.strptime(string_date, "%Y-%m-%d %H:%M:%S").timetuple())
    except:
        defaultdate = '2000-01-01 12:00:00'
        print "ERROR in datestr2num: Date as String: '{}'".format(string_date)
        print "                      replacing with: '{}'".format(defaultdate)
        dt=time.mktime(datetime.datetime.strptime(defaultdate, "%Y-%m-%d %H:%M:%S").timetuple())

    return dt

def videoDuration(video_file_path):
    """Get video duration in sec from a ffprobe call, using json output""" 

    #command is:  ffprobe -loglevel quiet -print_format json -show_format /full/path/to/videofile
    command     = ["ffprobe", "-loglevel", "quiet", "-print_format", "json", "-show_format",  video_file_path]
    pipe        = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    out, err    = pipe.communicate()
    js          = json.loads(out)

    return  int(float(js['format']['duration']) + 1.)

############# enter your data here ############################################
video_storage       = "/home/videos/tvheadend/"        # must end with "/" 
video_name          = "myvideo.MOV"                    # your video name with
                                                       # proper extension!
video_title         = "my title"                       # your text (any)
video_description   = "my description of my video"     # your text (any)
video_starttime     = "2017-10-25 00:00:00"            # your start time (any)
###############################################################################

video_path          = video_storage + video_name
video_subtitle      = "filename: " + video_name
video_startstmp     = datestr2num(video_starttime)
video_stopstmp      = video_startstmp + videoDuration(video_path)

mask = """{
    "enabled": true,
    "start": 1000,
    "stop":  2000,
    "channelname": "local file",
    "title": {
        "ger": "my title" 
    },
    "subtitle": {
        "ger": "filename: my video" 
    },
    "description": {
        "ger": "my description" 
    },
    "comment": "added by tvh_addfile.py",
    "files": [
        {
            "filename": "/full/path/to/videofile.ts" 
        }
    ]
}""" 
mask = mask.replace("\n", "")                          # remove the line feeds

new_mask                         = json.loads(mask)
new_mask['files'][0]['filename'] = video_path
new_mask['title']['ger']         = video_title
new_mask['subtitle']['ger']      = video_subtitle
new_mask['description']['ger']   = video_description
new_mask['start']                = video_startstmp
new_mask['stop']                 = video_stopstmp

print "New File Info: \n", json.dumps(new_mask, sort_keys = True, indent = 4)

api_url     = 'http://tv:[email protected]:9981/api/dvr/entry/create'
post        = 'conf=' + json.dumps(new_mask)
filehandle  = urllib.urlopen(api_url + "?" + post)
print "Server Answer:", filehandle.read()

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

@ullix tv - yes that's what I thought you might be doing. I'm no expert but I'm not sure it's going to work -this API call is for setting a future timer for an event which exists in the EPG. All you can do is try it. Don't forget if you're using HTTP GET that your data has to be URL encoded, eg

%7B%22enabled%22%3Atrue%2C%22start%22%3A1000%2C%3Cother%20json%20info%3E%7D

@Mark - Perhaps a wiki would have been easier! I'm hoping if others find the documentation useful that it could eventually be included in the main tvheadend wiki.

RE: Documentation for api access/programming - Added by ullix tv 8 months ago

Well, what I can tell is that it works and no, with using the script above, a url encoding is not needed. Kodi plays it well.

Look at other file infos: when the recording has not been started, no "files" section exist. After completion of recording, it does exist.

RE: Documentation for api access/programming - Added by ullix tv 8 months ago

I did this test:
with start time set to a future time, I registered an exiting video file with my script. On the tvh web page this entry shows up under "upcoming recordings". When the start time came, nothing happened, in particular no red dot indicating ongoing recording. When the stop time passed, also nothing happened: the entry remained under upcoming, and never moved to Finished. Therefore the file is not available for playing via Kodi.

Same when the start time was in the past, and only the stop time in the future.

When both times are in the past, all is ok. The file is seen under Finished, and Kodi can play it.

It is fair to assume that tvh never planned for such a thing.

The script could be supplemented with a check to verify stop time being in the past, but this may be overkill.

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

Great, thanks. I've added your information to my docs.

RE: Documentation for api access/programming - Added by Em Smith 8 months ago

The fact Tvheadend didn't crash when calling dvr/entry/create to create an upcoming recording event in the past, on an unavailable channel and with parameters missing is great, but it's probably not something on which you should rely. I'd suggest it's a bug that it allowed it through and Tvheadend should've rejected it.

Why not just import the videos on Kodi?

Could you add a warning section to the documentation to say the API stability is "unstable" and an advanced feature and that incorrect calls could cause Tvheadend to misbehave now or in the future? Otherwise when the API and code changes for bug fixes and new behaviour then people may get upset.

Also, probably best to dual licence the documentation as "GPL3 or later" or "distributed on the same licence terms as any OSI-approved licence under which Tvheadend is distributed."

RE: Documentation for api access/programming - Added by Dave Pickles 8 months ago

I've added a caveat to the docs as suggested and also updated the licence.

RE: Documentation for api access/programming - Added by Ivan Mara 5 days ago

Hello. How can i using curl delete object with eg uuid = 2104cbe9fd2cec1298ae1575128138c7 ?

RE: Documentation for api access/programming - Added by Dave Pickles 5 days ago

It depends what 'object' your uuid represents. For example to delete a completed recording use

curl 'http://user:[email protected]:9981/api/dvr/entry/remove?uuid=2104cbe9fd2cec1298ae1575128138c7'

RE: Documentation for api access/programming - Added by Ivan Mara 5 days ago

Ok. In my app i want delete all channels tags (Configuration - Channel/EPG - Channel Tags list). Tracing in firefox development tool showed api POST request: http://10.0.0.2:9981/api/idnode/delete and data (for 4 tags in list):

uuid:["2f53276d5f8dc339751dc54dec52a7c6","4d04dcf36d9dbda5fc7566804e569ba7","b9de98661b0fe72c13c822271a58f8d5","33dfc74ac7cbac60e31b8dfe181ba848","cce069ae2c81dc616a92972c332beee4"]

How can i make corect curl command to delete channels tags ?

RE: Documentation for api access/programming - Added by Dave Pickles 4 days ago

Untested but this should work:
curl --data 'uuid=["2f53276d5f8dc339751dc54dec52a7c6","4d04dcf36d9dbda5fc7566804e569ba7","b9de98661b0fe72c13c822271a58f8d5","33dfc74ac7cbac60e31b8dfe181ba848","cce069ae2c81dc616a92972c332beee4"]' http://10.0.0.2:9981/api/idnode/delete

Of course if you don't know the UUIDs in advance you would have to find them with api/channeltag/list.

(1-24/24)