encoding.py 6.42 KB
Newer Older
1
from server import *
2
from sorter import insert_video
Julian Rother's avatar
Julian Rother committed
3
import os.path
4
import json
5

Julian Rother's avatar
Julian Rother committed
6
def set_metadata(dest, course, lecture):
7
	chapters = query('SELECT text, time FROM chapters WHERE lecture_id = ? AND visible ORDER BY time', lecture['id'])
Julian Rother's avatar
Julian Rother committed
8
9
10
11
	metadata = {'title': lecture['title'], 'album': course['title'],
		'description': lecture['comment'],
		'date': lecture['time'].strftime('%m/%d/%Y'),
		'artist': lecture['speaker'] if lecture['speaker'] else course['organizer']}
Julian Rother's avatar
Julian Rother committed
12
13
14
	dest['metadata'] = metadata
	dest['chapters'] = chapters

Andreas Valder's avatar
Andreas Valder committed
15
16
17
18
19
20
21
def schedule_intro(lectureid):
	lecture = query('SELECT * FROM lectures where id = ?', lectureid)
	course = query('SELECT * FROM course where id = ?', lecture['course_id'])
	data = {'path': path, 'lecture_id': lectureid}
	set_metadata(data, course, lecture)
	schedule_job('intro', data)

22
def schedule_remux(lectureid, videoid=None):
Julian Rother's avatar
Julian Rother committed
23
24
25
26
27
28
29
	lecture = query('SELECT * FROM lectures WHERE id = ?', lectureid)[0]
	course = query('SELECT * FROM courses WHERE id = ?', lecture['course_id'])[0]
	videos = query('''SELECT videos.*, sources.path AS srcpath, sources.hash AS srchash, formats.options AS fmtopts
			FROM videos
			JOIN sources ON videos.source = sources.id
			JOIN formats ON videos.video_format = formats.id
			WHERE videos.lecture_id = ?''', lectureid)
Julian Rother's avatar
Julian Rother committed
30
31
32
	for video in videos:
		if not video['source']:
			continue
33
34
		if videoid and video['id'] != videoid:
			continue
Julian Rother's avatar
Julian Rother committed
35
36
		data = {'path': video['path'], 'srcpath': video['srcpath'],
			'srchash': video['srchash'], 'video_id': video['id']}
Julian Rother's avatar
Julian Rother committed
37
38
39
40
41
		fmt = json.loads(video['fmtopts'])
		if 'format' in fmt:
			data['format'] = fmt['format']
		data['options'] = fmt.get('options', {})
		set_metadata(data, course, lecture)
Julian Rother's avatar
Julian Rother committed
42
		schedule_job('remux', data)
43
44
45
46
47
48
49
50
51
52
53

@app.route('/internal/jobs/add/remux', methods=['GET', 'POST'])
@mod_required
@csrf_protect
def add_remux_job():
	lectureid = request.values.get('lectureid')
	videoid = int(request.values.get('videoid', 0))
	if not lectureid:
		lectureid = query('SELECT lecture_id FROM videos WHERE id = ?', videoid)[0]['lecture_id']
	schedule_remux(lectureid, videoid)
	return redirect(request.values.get('ref', url_for('jobs_overview')))
Julian Rother's avatar
Julian Rother committed
54

Julian Rother's avatar
Julian Rother committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def schedule_transcode(source, fmt_id=None, video=None):
	if video:
		fmt_id = video['video_format']
		assert(video['lecture_id'] == source['lecture_id'])
	assert(fmt_id != None)
	fmt = query('SELECT * FROM formats WHERE id = ?', fmt_id)[0]
	lecture = query('SELECT * FROM lectures WHERE id = ?', source['lecture_id'])[0]
	course = query('SELECT * FROM courses WHERE id = ?', lecture['course_id'])[0]
	data = {'input': {'path': source['path'], 'streams': []}, 'output': json.loads(fmt['options']), 'filters': []}
	if source['type'] == 'plain':
		stream = {'name': 'video', 'type': 'video'}
		data['input']['streams'].append(stream)
		stream = {'name': 'audio', 'type': 'audio'}
		data['input']['streams'].append(stream)
	else:
		assert(False)
	set_metadata(data['output'], course, lecture)
	basename = os.path.basename(source['path']).rsplit('.', 1)[0]
	data['output']['path'] = 'pub/'+course['handle']+'/'+basename+fmt['suffix']
	if video:
75
		old_source = query('SELECT * FROM sources WHERE id = ?', video['source'])[0]
Julian Rother's avatar
Julian Rother committed
76
77
78
79
80
81
82
83
		data['output']['path'] = video['path']
		data['video_id'] = video['id']
		data['srcpath'] = old_source['path']
		data['srchash'] = old_source['hash']
	else:
		data['lecture_id'] = lecture['id']
	data['format_id'] = fmt['id']
	data['source_id'] = source['id']
84
85
86
87
88
89
90
91
92
93
	return schedule_job('transcode', data, queue="background")

@job_handler('transcode')
def insert_transcoded_video(jobid, jobtype, data, state, status):
	if 'lecture_id' not in data or 'source_id' not in data or 'format_id' not in data:
		return
	if 'video_id' in data:
		return
	video_id = insert_video(data['lecture_id'], data['output']['path'], data['format_id'], status['hash'], status['filesize'], status['duration'], data['source_id'])
	schedule_remux(data['lecture_id'], video_id)
Julian Rother's avatar
Julian Rother committed
94

95
96
97
98
@app.route('/internal/jobs/add/reencode', methods=['GET', 'POST'])
@mod_required
@csrf_protect
@handle_errors('jobs_overview', 'Video nicht gefunden!', 404, IndexError)
99
def add_reencode_job():
100
101
102
103
104
105
106
107
	video = query('SELECT * FROM videos WHERE id = ?', request.values['videoid'])[0]
	if not video['source']:
		flash('Manuell erstellte Videos können nicht neukodiert werden!')
	else:
		source = query('''SELECT sources.* FROM sources WHERE sources.id = ? ORDER BY time_created''', video['source'])[-1]
		schedule_transcode(source, video=video)
	return redirect(request.values.get('ref', url_for('jobs_overview')))

Andreas Valder's avatar
Andreas Valder committed
108
@job_handler('probe-raw', 'intro')
Julian Rother's avatar
Julian Rother committed
109
110
111
def update_lecture_videos(jobid, jobtype, data, state, status):
	if 'lecture_id' not in data:
		return
Andreas Valder's avatar
Andreas Valder committed
112
113
114
115
	if jobtype == 'probe-raw':
		if 'source_id' not in data:
			modify('INSERT INTO sources (lecture_id, path, type, hash, time_created) VALUES (?, ?, ?, ?, ?)',
					data['lecture_id'], data['path'], 'plain', status['hash'], datetime.now())
Julian Rother's avatar
Julian Rother committed
116
117
118
119
	sources = query('SELECT * FROM sources WHERE sources.lecture_id = ? ORDER BY time_created', data['lecture_id'])
	if not sources:
		return
	latest = sources[-1]
Andreas Valder's avatar
Andreas Valder committed
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
	lecture = query('SELECT * FROM lectures where id = ?', data['lecture_id'])
	if 'lecture is autointro' and jobtype == 'probe-raw':
		schedule_intro(data['lecture_id'])
	else:
		videos = query('SELECT * FROM videos WHERE videos.lecture_id = ?', data['lecture_id'])
		current_fmts = [v['video_format'] for v in videos]
		formats = query('''SELECT formats.* FROM formats
				JOIN profiles ON formats.id = profiles.format
				JOIN courses ON profiles.name = courses.profile
				JOIN lectures ON courses.id = lectures.course_id
				WHERE lectures.id = ?''', data['lecture_id'])
		for fmt in formats:
			if fmt['id'] not in current_fmts:
				schedule_transcode(latest, fmt_id=fmt['id'])
		for video in videos:
			if video['source'] != latest['id']:
				schedule_transcode(latest, video=video)
Julian Rother's avatar
Julian Rother committed
137

Julian Rother's avatar
Julian Rother committed
138
@edit_handler('chapters')
139
def chapter_changed(table, column, value, id, user):
Julian Rother's avatar
Julian Rother committed
140
141
142
143
144
145
146
147
	chapters = query('SELECT * FROM chapters WHERE id = ?', id)
	if not chapters:
		return
	chapter = chapters[0]
	if column in ['visible', 'deleted'] or (chapter['visible'] and not chapter['deleted']):
		schedule_remux(chapter['lecture_id'])

@edit_handler('courses')
148
def course_changed(table, column, value, id, user):
Julian Rother's avatar
Julian Rother committed
149
150
151
152
153
154
155
	if column not in ['title', 'organizer']:
		return
	lectures = query('SELECT * FROM lectures WHERE course_id = ?', id)
	for lecture in lectures:
		schedule_remux(lecture['id'])

@edit_handler('lectures')
156
def lecture_changed(table, column, value, id, user):
Julian Rother's avatar
Julian Rother committed
157
158
159
	if column in ['title', 'comment', 'time', 'speaker']:
		schedule_remux(id)