diff --git a/db_example.sql b/db_example.sql
index 26c85b08b8c653de269a6d4dc7d957d56f9e88c4..3c6754b52c22cf065ff3648f41b334a77557b49a 100644
--- a/db_example.sql
+++ b/db_example.sql
@@ -310,37 +310,38 @@ INSERT INTO "courses_data" VALUES(300,1,1,0,'AStA Vortragsabend','Vortragsabend'
 INSERT INTO "courses_data" VALUES(301,1,1,0,'HYP2016','HYP2016','16ss-hyp','Institut für Mathematik','Mathematik',0,60,'2016-08-01 13:21:48','2016-08-01 14:01:30','2016ss','',1,0,'XVI International Conference on Hyperbolic Problems\nTheory, Numerics, Applications				\n\nLearn more at <a href="http://www.hyp2016.de/">hyp2016.de</a>','','','');
 INSERT INTO "courses_data" VALUES(302,0,1,1,'Neue Veranstaltung','','16ss-new302','','',0,64,'2016-08-05 01:21:34','2016-08-05 01:24:59','2016ss','',1,0,'','','','');
 INSERT INTO "courses_data" VALUES(303,1,1,0,'Aachen2025','Aachen2025','160923-aachen2025','REGINA,TEMA','',0,64,'2016-08-05 01:22:04','2016-08-05 01:25:27','2016ss','',1,0,'','','','');
-INSERT INTO "formats" VALUES(0,'Format unbekannt','','','',-100,0);
-INSERT INTO "formats" VALUES(1,'SDV','sd,pal','720x576','4:3',1,0);
-INSERT INTO "formats" VALUES(2,'SDV','ws,palws','720x576','16:9',1,0);
-INSERT INTO "formats" VALUES(3,'HDV','hdv','1440x1080','16:9',9,6);
-INSERT INTO "formats" VALUES(4,'1080p','1080p','1920x1080','16:9',10,7);
-INSERT INTO "formats" VALUES(5,'720p','720p','1280x720','16:9',5,10);
-INSERT INTO "formats" VALUES(6,'640x512','','640x512','16:9',-1,0);
-INSERT INTO "formats" VALUES(7,'MP3','mp3','','',-10,0);
-INSERT INTO "formats" VALUES(8,'720p F4V','','1280x720','16:9',4,10);
-INSERT INTO "formats" VALUES(9,'480p','ipod,480p','640x480','4:3',2,8);
-INSERT INTO "formats" VALUES(10,'360p','ipod,360p','640x360','16:9',3,8);
-INSERT INTO "formats" VALUES(11,'AAC','','','',-2,0);
-INSERT INTO "formats" VALUES(12,'270p','ipodsmall,270p','480x270','16:9',1,3);
-INSERT INTO "formats" VALUES(13,'Screencast','','1024x768','4:3',4,5);
-INSERT INTO "formats" VALUES(14,'WAV','wav','48 kHz','',0,0);
-INSERT INTO "formats" VALUES(15,'DVD','dvd,iso','720x576','',1,0);
-INSERT INTO "formats" VALUES(16,'WMV','wmv','','',-1,0);
-INSERT INTO "formats" VALUES(17,'iPod','','','',0,3);
-INSERT INTO "formats" VALUES(18,'original','','','',0,0);
-INSERT INTO "formats" VALUES(19,'Screencast','','800x600','4:3',3,4);
-INSERT INTO "formats" VALUES(20,'Screencast','','1280x800','16:10',2,5);
-INSERT INTO "formats" VALUES(21,'Tonspur','tonspur,m4a','','',-10,0);
-INSERT INTO "formats" VALUES(22,'360p WebM','360p webm','640x360','16:9',3,0);
-INSERT INTO "formats" VALUES(23,'720p WebM','720p webm','1280x720','16:9',5,0);
-INSERT INTO "formats" VALUES(24,'1080p WebM','1080p webm','1920x1080','16:9',10,0);
-INSERT INTO "formats" VALUES(25,'Test 1','','1280x720','16:9',0,0);
-INSERT INTO "formats" VALUES(26,'Test 2','','1280x720','16:9',0,0);
-INSERT INTO "formats" VALUES(27,'Test 3','','1280x720','16:9',0,0);
-INSERT INTO "formats" VALUES(28,'LQ iPod','','640x360','16:9',-7,-2);
-INSERT INTO "formats" VALUES(29,'1080p 8M','1080p','1920x1080','16:9',0,14);
-INSERT INTO "formats" VALUES(30,'Streamdump','streamdump','1920x1080','16:9',0,-10);
+INSERT INTO "formats" VALUES(0,'Format unbekannt','','','',-100,0,'video/mp4');
+INSERT INTO "formats" VALUES(1,'SDV','sd,pal','720x576','4:3',1,0,'video/mp4');
+INSERT INTO "formats" VALUES(2,'SDV','ws,palws','720x576','16:9',1,0,'video/mp4');
+INSERT INTO "formats" VALUES(3,'HDV','hdv','1440x1080','16:9',9,6,'video/mp4');
+INSERT INTO "formats" VALUES(4,'1080p','1080p','1920x1080','16:9',10,7,'video/mp4');
+INSERT INTO "formats" VALUES(5,'720p','720p','1280x720','16:9',5,10,'video/mp4');
+INSERT INTO "formats" VALUES(6,'640x512','','640x512','16:9',-1,0,'video/mp4');
+INSERT INTO "formats" VALUES(7,'MP3','mp3','','',-10,0,'video/mp4');
+INSERT INTO "formats" VALUES(8,'720p F4V','','1280x720','16:9',4,10,'video/mp4');
+INSERT INTO "formats" VALUES(9,'480p','ipod,480p','640x480','4:3',2,8,'video/mp4');
+INSERT INTO "formats" VALUES(10,'360p','ipod,360p','640x360','16:9',3,8,'video/mp4');
+INSERT INTO "formats" VALUES(11,'AAC','','','',-2,0,'video/mp4');
+INSERT INTO "formats" VALUES(12,'270p','ipodsmall,270p','480x270','16:9',1,3,'video/mp4');
+INSERT INTO "formats" VALUES(13,'Screencast','','1024x768','4:3',4,5,'video/mp4');
+INSERT INTO "formats" VALUES(14,'WAV','wav','48 kHz','',0,0,'video/mp4');
+INSERT INTO "formats" VALUES(15,'DVD','dvd,iso','720x576','',1,0,'video/mp4');
+INSERT INTO "formats" VALUES(16,'WMV','wmv','','',-1,0,'video/mp4');
+INSERT INTO "formats" VALUES(17,'iPod','','','',0,3,'video/mp4');
+INSERT INTO "formats" VALUES(18,'original','','','',0,0,'video/mp4');
+INSERT INTO "formats" VALUES(19,'Screencast','','800x600','4:3',3,4,'video/mp4');
+INSERT INTO "formats" VALUES(20,'Screencast','','1280x800','16:10',2,5,'video/mp4');
+INSERT INTO "formats" VALUES(21,'Tonspur','tonspur,m4a','','',-10,0,'video/mp4');
+INSERT INTO "formats" VALUES(22,'360p WebM','360p webm','640x360','16:9',3,0,'video/mp4');
+INSERT INTO "formats" VALUES(23,'720p WebM','720p webm','1280x720','16:9',5,0,'video/mp4');
+INSERT INTO "formats" VALUES(24,'1080p WebM','1080p webm','1920x1080','16:9',10,0,'video/mp4');
+INSERT INTO "formats" VALUES(25,'Test 1','','1280x720','16:9',0,0,'video/mp4');
+INSERT INTO "formats" VALUES(26,'Test 2','','1280x720','16:9',0,0,'video/mp4');
+INSERT INTO "formats" VALUES(27,'Test 3','','1280x720','16:9',0,0,'video/mp4');
+INSERT INTO "formats" VALUES(28,'LQ iPod','','640x360','16:9',-7,-2,'video/mp4');
+INSERT INTO "formats" VALUES(29,'1080p 8M','1080p','1920x1080','16:9',0,14,'video/mp4');
+INSERT INTO "formats" VALUES(30,'Streamdump','streamdump','1920x1080','16:9',0,-10,'video/mp4');
+INSERT INTO "formats" VALUES(31,'Livestream','hls','1920x1080','16:9',-15,-10,'application/x-mpegURL');
 INSERT INTO "lectures_data" VALUES(1,2,1,NULL,0,'egal',0,'Einführung zur Berechenbarkeit','','','','','2007-10-19 12:00:00',0,'0000-00-00 00:00:00','0000-00-00 00:00:00','','pub/07ws-buk/07ws-buk-071019-title.jpg');
 INSERT INTO "lectures_data" VALUES(2,2,1,NULL,0,'egal',0,'Einführung zur Berechenbarkeit','','','','','2007-10-23 08:30:00',0,'0000-00-00 00:00:00','0000-00-00 00:00:00','','pub/07ws-buk/07ws-buk-071023-title.jpg');
 INSERT INTO "lectures_data" VALUES(3,2,1,NULL,0,'egal',0,'Einführung zur Berechenbarkeit','','','','','2007-10-26 12:00:00',0,'0000-00-00 00:00:00','0000-00-00 00:00:00','','pub/07ws-buk/07ws-buk-071026-title.jpg');
diff --git a/db_schema.sql b/db_schema.sql
index d02c4fabd6aa4ef0f6e2df62d01a75a67463eb4c..b4b0b54c056b34d43ab362ca11940194216e72f7 100644
--- a/db_schema.sql
+++ b/db_schema.sql
@@ -76,7 +76,8 @@ CREATE TABLE IF NOT EXISTS `formats` (
   `resolution` varchar(16) NOT NULL,
   `aspect` varchar(16) NOT NULL,
   `prio` INTEGER NOT NULL DEFAULT '0',
-  `player_prio` INTEGER NOT NULL DEFAULT '0'
+  `player_prio` INTEGER NOT NULL DEFAULT '0',
+	`mimetype` varchar(32) NOT NULL
 );
 CREATE TABLE IF NOT EXISTS `lectures_data` (
 `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
diff --git a/server.py b/server.py
index 4ae2bed0c5388b0bb17b0d8fc47e29a04543a8dd..111eeceee0477621bfd890858121d2b11ab41084 100644
--- a/server.py
+++ b/server.py
@@ -312,8 +312,14 @@ def index():
 		GROUP BY videos.lecture_id
 		ORDER BY MAX(videos.time_updated) DESC
 		LIMIT 6	''',ismod())
+	livestreams = query('''SELECT streams.handle AS live, lectures.*, "course" AS sep, courses.*
+		FROM streams
+		JOIN lectures ON lectures.id = streams.lecture_id
+		JOIN courses ON courses.id = lectures.course_id
+		WHERE streams.active AND (? OR (streams.visible AND courses.visible AND courses.listed AND lectures.visible))
+		''', ismod())
 	featured = query('SELECT * FROM featured WHERE NOT deleted AND (? OR visible)', ismod())
-	return render_template('index.html', latestvideos=latestvideos, upcomming=upcomming, featured=featured)
+	return render_template('index.html', latestvideos=livestreams+latestvideos, upcomming=upcomming, featured=featured)
 
 @app.route('/course')
 @register_navbar('Videos', icon='film')
@@ -327,6 +333,14 @@ def courses():
 		groupedby = 'semester'
 	return render_template('courses.html', courses=courses, groupedby=groupedby)
 
+def genlive(streams):
+	for stream in streams:
+		stream['visible'] = True
+		stream['downloadable'] = False
+		stream['path'] = 'pub/hls/%s.m3u8'%stream['live']
+		stream['file_size'] = 0
+	return streams
+
 @app.route('/course/<handle>')
 @app.route('/course/<int:id>')
 @handle_errors('courses', 'Diese Veranstaltung existiert nicht!', 404, IndexError)
@@ -354,6 +368,13 @@ def course(id=None, handle=None):
 			WHERE lectures.course_id= ? AND (? OR videos.visible)
 			ORDER BY lectures.time, formats.prio DESC
 			''', course['id'], ismod())
+	livestreams = query('''SELECT streams.handle AS live, streams.lecture_id, formats.description AS format_description, formats.player_prio, formats.prio
+			FROM streams
+			JOIN lectures ON lectures.id = streams.lecture_id
+			JOIN formats ON formats.keywords = "hls"
+			WHERE streams.active AND (? OR streams.visible) AND lectures.course_id = ?
+			''', ismod(), course['id'])
+	videos += genlive(livestreams)
 	return render_template('course.html', course=course, lectures=lectures, videos=videos)
 
 @app.route('/faq')
@@ -367,13 +388,20 @@ def faq():
 def lecture(id):
 	lecture = query('SELECT * FROM lectures WHERE id = ? AND (? OR visible)', id, ismod())[0]
 	videos = query('''
-			SELECT videos.*, (videos.downloadable AND courses.downloadable) as downloadable, formats.description AS format_description, formats.player_prio, formats.prio
+			SELECT videos.*, (videos.downloadable AND courses.downloadable) as downloadable, formats.description AS format_description, formats.player_prio, formats.prio, formats.mimetype
 			FROM videos
 			JOIN formats ON (videos.video_format = formats.id)
 			JOIN courses ON (courses.id = ?)
 			WHERE videos.lecture_id = ? AND (? OR videos.visible)
 			ORDER BY formats.prio DESC
 			''', lecture['course_id'], lecture['id'], ismod())
+	livestreams = query('''SELECT streams.handle AS live, streams.lecture_id, formats.description AS format_description, formats.player_prio, formats.prio, formats.mimetype
+			FROM streams
+			JOIN lectures ON lectures.id = streams.lecture_id
+			JOIN formats ON formats.keywords = "hls"
+			WHERE streams.active AND (? OR streams.visible) AND lectures.id = ?
+			''', ismod(), id)
+	videos += genlive(livestreams)
 	perms = query('SELECT perm.* FROM perm WHERE ((NOT perm.deleted) AND (perm.lecture_id = ? OR perm.course_id = ?))',
 			lecture['id'], lecture['course_id'])
 	if not videos:
@@ -531,7 +559,7 @@ def auth(): # For use with nginx auth_request
 		cookie = int(request.cookies['tracking'])
 	else:
 		cookie = random.getrandbits(8*8-1)
-	if url.endswith('jpg') or ismod():
+	if url.endswith('jpg') or ismod() or url.startswith('pub/hls/'):
 		return "OK", 200
 	perms = query('''SELECT videos.path, videos.id AS vid, perm.*
       FROM videos
diff --git a/templates/macros.html b/templates/macros.html
index 87de4e31bdd5d04859a769a5d9d800ef8ff21905..7f7c80b4cc76d18a6d1eed5753a13d08e505609a 100644
--- a/templates/macros.html
+++ b/templates/macros.html
@@ -5,7 +5,7 @@
 			<div class="row">
 				<img class="col-xs-4" style="max-height: 120px; height: auto; width:170px" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'; this.onerror=''; ">
 				<div class="col-xs-4">
-					<span><strong>{{ lecture.course.short }}</strong>{% if ismod() %} <i>({{lecture.course_id}})</i>{% endif %}</span><br>
+					<span>{% if lecture.live %}<span class="label label-danger">Live</span> {% endif %}<strong>{{ lecture.course.short }}</strong>{% if ismod() %} <i>({{lecture.course_id}})</i>{% endif %}</span><br>
 					<span>{% if ismod() %}ID: {{lecture.id}}{% endif %}</span><br>
 					<span>{{ lecture['time'] }}</span>
 					{% if lecture['speaker'] %}
@@ -24,6 +24,7 @@
 					<img style="width: 100%;" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'; this.onerror=''; ">
 				</li>
 				<li>
+					{% if lecture.live %}<span class="label label-danger">Live</span> {% endif %}
 					<strong>{{ lecture.course.short }}</strong> {{ lecture['time'] }}
 				</li>
 				{% if lecture['speaker'] %}
@@ -47,7 +48,7 @@
 {% macro player(lecture, videos) %}
 <video id="videoplayer" style="width: 100%" class="video-js vjs-default-skin vjs-big-play-centered" width="640" height="320" controls data-wasnotplayed="1"  data-setup='{ "plugins" : {"hotkeys": {"seekStep": 15, "enableVolumeScroll": false, "alwaysCaptureHotkeys": true}, "videoJsResolutionSwitcher": { "ui": true, "default": "720p", "dynamicLabel": true } }, "customControlsOnMobile": true, "playbackRates": [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4] }'>
 	{% for v in videos|sort(attribute='player_prio', reverse=True) %}
-		<source type="video/mp4" src="{{ config.VIDEOPREFIX }}/{{ v.path }}" label="{{ v.format_description }}"/>
+		<source type="{{ v.mimetype }}" src="{{ config.VIDEOPREFIX }}/{{ v.path }}" label="{{ v.format_description }}"/>
 	{% endfor %}
 	<track srclang="de" kind="chapters" src="{{ url_for('chapters',lectureid=lecture.id) }}" />
 </video>
@@ -171,7 +172,7 @@ $('#embedcodebtn').popover(
 		</div>
 		<span class="col-sm-3 col-xs-12">
 			<ul class="list-unstyled">
-				<li>{{ moderator_editor(['lectures',lecture.id,'title'], lecture.title) }}</li>
+				<li>{% if videos|selectattr("live")|list|length %}<span class="label label-danger">Live</span> {% endif %}{{ moderator_editor(['lectures',lecture.id,'title'], lecture.title) }}</li>
 				{% if lecture.speaker or ismod() %}<li>Gehalten von {{ moderator_editor(['lectures',lecture.id,'speaker'], lecture.speaker) }}</li>{% endif %}
 				<li>{{ moderator_editor(['lectures',lecture.id,'time'], lecture.time) }} </li>
 				<li>Dauer: {{ moderator_editor(['lectures',lecture.id,'duration'], lecture.duration) }} min</li>