1
|
#!/usr/bin/env python3
|
2
|
# -*- coding: UTF-8 -*-
|
3
|
|
4
|
|
5
|
#This script has the purpose to import old TVHeadend recordings in a new TVHeadend installation. It scans a folder with TVHeadend recordings and sets for each file a recording timer in TVHeadend. This is adapted from the following skript:
|
6
|
#https://tvheadend.org/boards/5/topics/28252?r=29113#message-29113 by user ullix tv.
|
7
|
#The folder is expected to be in untouched format. My recordings have a filenamescheme of "name-YYYY-MM-DDHH-MM.ts" because I had %F%R in the recording String. Looks ugly but helps now. Getting the time string with filedate2num has to be adapted. Variables have to be adapted to personal situation.
|
8
|
import json, urllib, time, datetime, subprocess, os
|
9
|
|
10
|
|
11
|
#Input variables
|
12
|
recdir = "/storage/recordings/"
|
13
|
api_url = "http://user:password@IP:9981/api/dvr/entry/create?conf="
|
14
|
mask = """{
|
15
|
"enabled": true,
|
16
|
"start": 1000,
|
17
|
"stop": 2000,
|
18
|
"channelname": "Imported",
|
19
|
"title": {
|
20
|
"ger": "my title"
|
21
|
},
|
22
|
"comment": "added by tvh_rec_import.py",
|
23
|
"files": [
|
24
|
{
|
25
|
"filename": "/full/path/to/videofile.ts"
|
26
|
}
|
27
|
]
|
28
|
}"""
|
29
|
mask = mask.replace("\n", "") # remove the line feeds
|
30
|
|
31
|
|
32
|
|
33
|
#Functions
|
34
|
def filedate2num(filepath):
|
35
|
"""Convert filename that ends with 'YYYY-MM-DDHH-MM.ts' to Unix timestamp; use cdate, i.e. last inode change time not creation, on error"""
|
36
|
|
37
|
|
38
|
try:
|
39
|
dt = int(time.mktime(datetime.datetime.strptime(filepath[-18:-3], "%Y-%m-%d%H-%M").timetuple()))
|
40
|
except:
|
41
|
print "ERROR in filestr2num: file name doesn't end with 'YYYY-MM-DDHH-MM.ts'. Use Inode Change Time instead."
|
42
|
dt = int(os.stat(filepath).st_ctime)
|
43
|
return dt
|
44
|
|
45
|
|
46
|
def videoDuration(video_file_path):
|
47
|
"""Get video duration in sec from a ffprobe call, using json output"""
|
48
|
|
49
|
|
50
|
#command is: ffprobe -loglevel quiet -print_format json -show_format /full/path/to/videofile
|
51
|
command = ["ffprobe", "-loglevel", "quiet", "-print_format", "json", "-show_format", video_file_path]
|
52
|
pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
53
|
out, err = pipe.communicate()
|
54
|
js = json.loads(out)
|
55
|
return int(float(js['format']['duration']) + 1.)
|
56
|
|
57
|
|
58
|
def importRecord(filepath, mask, url):
|
59
|
"""Creates a json file with the information from video file and sends a recording timer to the server."""
|
60
|
video_start = filedate2num(filepath)
|
61
|
new_mask = json.loads(mask)
|
62
|
new_mask['files'][0]['filename'] = filepath[8:]
|
63
|
new_mask['title']['ger'] = filepath.split("/")[-1][:-3]
|
64
|
new_mask['start'] = video_start
|
65
|
new_mask['stop'] = video_start + videoDuration(filepath)
|
66
|
print "New File Info: \n", json.dumps(new_mask, sort_keys = True, indent = 4)
|
67
|
api_string = url + json.dumps(new_mask)
|
68
|
filehandle = urllib.urlopen(api_string)
|
69
|
print "Server Answer:", filehandle.read()
|
70
|
|
71
|
|
72
|
#Iterating through recordings folder
|
73
|
directories = os.listdir(recdir)
|
74
|
for folder in directories:
|
75
|
for root, dirs, files in os.walk(recdir+folder):
|
76
|
for filename in files:
|
77
|
importRecord(recdir+folder+"/"+filename, mask, api_url)
|