encoding.py 6.41 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
	lecture = query('SELECT * FROM lectures where id = ?', data['lecture_id'])
121
	if False and jobtype == 'probe-raw':
Andreas Valder's avatar
Andreas Valder committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
		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)