diff --git a/encoding.py b/encoding.py
index d48d827c9891d06f2f9104ede3781d245e71817b..a49c5db007f29b2dacb188802d8bc81ea2221f2c 100644
--- a/encoding.py
+++ b/encoding.py
@@ -12,13 +12,6 @@ def set_metadata(dest, course, lecture):
 	dest['metadata'] = metadata
 	dest['chapters'] = chapters
 
-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)
-
 def schedule_remux(lectureid, videoid=None):
 	lecture = query('SELECT * FROM lectures WHERE id = ?', lectureid)[0]
 	course = query('SELECT * FROM courses WHERE id = ?', lecture['course_id'])[0]
@@ -52,7 +45,7 @@ def add_remux_job():
 	schedule_remux(lectureid, videoid)
 	return redirect(request.values.get('ref', url_for('jobs_overview')))
 
-def schedule_transcode(source, fmt_id=None, video=None):
+def schedule_transcode(source, fmt_id=None, video=None, intro_path=None):
 	if video:
 		fmt_id = video['video_format']
 		assert(video['lecture_id'] == source['lecture_id'])
@@ -62,10 +55,23 @@ def schedule_transcode(source, fmt_id=None, video=None):
 	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)
+		data['input']['streams'].append({'name': 'video', 'type': 'video'})
+		data['input']['streams'].append({'name': 'audio', 'type': 'audio'})
+	elif source['type'] == 'autointro':
+		if not intro_path:
+			ctx={'source_id': source['id'], 'fmt_id': fmt['id']}
+			if video:
+				ctx['video_id'] = video['id']
+			schedule_intro(lecture['lecture_id'], transcode_ctx=ctx)
+			return
+		data['input']['streams'].append({'name': 'src_video', 'type': 'video'})
+		data['input']['streams'].append({'name': 'src_audio', 'type': 'audio'})
+		data['filters'].append('movie=$WORKER_RAW/%s, loop=loop=-1:size=1:start=0, fade=out:st=7:d=1, trim=duration=8[intro_video]'%intro_path)
+		data['filters'].append('anullsrc,atrim=duration=8[intro_audio]')
+		data['filters'].append('movie=$WORKER_RAW/outro_slide.png, loop=loop=-1:size=1:start=0, fade=in:st=0:d=1, trim=duration=5[outro_video]')
+		data['filters'].append('anullsrc,atrim=duration=5[outro_audio]')
+		data['filters'].append('[src_video]fade=in:st=0:d=1[tmp_video]')
+		data['filters'].append('[intro_video] [intro_audio] [tmp_video] [src_audio] [outro_video] [outro_audio] concat=n=3:a=1 [video] [audio]')
 	else:
 		assert(False)
 	set_metadata(data['output'], course, lecture)
@@ -92,6 +98,24 @@ def insert_transcoded_video(jobid, jobtype, data, state, status):
 	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)
 
+def schedule_intro(lecture_id, **data):
+	lecture = query('SELECT * FROM lectures where id = ?', lecture_id)
+	course = query('SELECT * FROM course where id = ?', lecture['course_id'])
+	data['path'] = 'intros/l_%i.png'%lecture['id']
+	data['lecture_id'] = lecture_id
+	set_metadata(data, course, lecture)
+	schedule_job('intro', data)
+
+@job_handler('intro')
+def transcode_after_intro(jobid, jobtype, data, state, status):
+	if 'transcode_ctx' not in data:
+		return 
+	source = query('SELECT * FROM sources WHERE id = ?', data['transcode_ctx']['source_id'])[0]
+	video = None
+	if data['transcode_ctx'].get('video_id'):
+		video = query('SELECT * FROM videos WHERE id = ?', data['transcode_ctx']['video_id'])
+	schedule_transcode(source, data['transcode_ctx']['fmt_id'], video=video, intro_path=data['path'])
+
 @app.route('/internal/jobs/add/reencode', methods=['GET', 'POST'])
 @mod_required
 @csrf_protect