diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties
index 1c800dff2429a503448a48b7e7e9b5292b533a8d..f773b8d01063ad8c00cd748821ae23f80ba83a4f 100644
--- a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties
@@ -20,6 +20,7 @@ FileResource.GLOSSARY=Glossar
 FileResource.IMAGE=Bild
 FileResource.IMSCP=CP-Lerninhalt
 FileResource.MOVIE=Film
+FileResource.VIDEO=Video
 FileResource.PDF=PDF
 FileResource.PODCAST=Podcast
 FileResource.PPT=PowerPoint
diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties
index 76b679bc8efce957219a6c5ef5b042ffdab2021f..126cd1bc498d0e6818f1fa99321fd9413df16d3e 100644
--- a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties
@@ -21,6 +21,7 @@ FileResource.GLOSSARY=Glossary
 FileResource.IMAGE=Image
 FileResource.IMSCP=CP learning content
 FileResource.MOVIE=Movie
+FileResource.VIDEO=Video
 FileResource.PDF=PDF
 FileResource.PODCAST=Podcast
 FileResource.PPT=PowerPoint
diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java
index 131065ef0e4dd952cc79271b2b3769b9b50a2649..a5eec4fd52f27cba527c8be97fb207267397dffb 100644
--- a/src/main/java/org/olat/course/CourseFactory.java
+++ b/src/main/java/org/olat/course/CourseFactory.java
@@ -141,13 +141,13 @@ import org.olat.util.logging.activity.LoggingResourceable;
  * Description: <BR>
  * Use the course factory to create course run and edit controllers or to load a
  * course from disk
- * 
+ *
  * Initial Date: Oct 12, 2004
  * @author Felix Jost
  * @author guido
  */
 public class CourseFactory {
-		
+
 	private static CacheWrapper<Long,PersistingCourseImpl> loadedCourses;
 	private static ConcurrentMap<Long, ModifyCourseEvent> modifyCourseEvents = new ConcurrentHashMap<Long, ModifyCourseEvent>();
 
@@ -158,8 +158,8 @@ public class CourseFactory {
 	private static RepositoryManager repositoryManager;
 	private static ReferenceManager referenceManager;
 	private static RepositoryService repositoryService;
-	
-	
+
+
 	/**
 	 * [used by spring]
 	 */
@@ -173,7 +173,7 @@ public class CourseFactory {
 
 	/**
 	 * Create an editor controller for the given course resourceable
-	 * 
+	 *
 	 * @param ureq
 	 * @param wControl
 	 * @param courseEntry
@@ -206,7 +206,7 @@ public class CourseFactory {
 	/**
 	 * Creates an empty course with a single root node. The course is linked to
 	 * the resourceable ores. The efficiency statment are enabled per default!
-	 * 
+	 *
 	 * @param ores
 	 * @param shortTitle Short title of root node
 	 * @param longTitle Long title of root node
@@ -217,9 +217,9 @@ public class CourseFactory {
 			String shortTitle, String longTitle, String learningObjectives) {
 		OLATResource courseResource = courseEntry.getOlatResource();
 		PersistingCourseImpl newCourse = new PersistingCourseImpl(courseResource);
-		// Put new course in course cache    
+		// Put new course in course cache
 		loadedCourses.put(newCourse.getResourceableId(), newCourse);
-		
+
 		Structure initialStructure = new Structure();
 		CourseNode runRootNode = new STCourseNode();
 		runRootNode.setShortTitle(shortTitle);
@@ -234,7 +234,7 @@ public class CourseFactory {
 		editorTreeModel.setRootNode(editorRootNode);
 		newCourse.setEditorTreeModel(editorTreeModel);
 		newCourse.saveEditorTreeModel();
-		
+
 		//enable efficiency statement per default
 		CourseConfig courseConfig = newCourse.getCourseConfig();
 		courseConfig.setEfficencyStatementIsEnabled(true);
@@ -242,8 +242,8 @@ public class CourseFactory {
 
 		return newCourse;
 	}
-	
-	
+
+
 
 	/**
 	 * Gets the course from cache if already there, or loads the course and puts it into cache.
@@ -263,7 +263,7 @@ public class CourseFactory {
 			// that no invalidate cache event was missed
 			PersistingCourseImpl theCourse = new PersistingCourseImpl(courseEntry);
 			theCourse.load();
-			
+
 			PersistingCourseImpl cachedCourse = loadedCourses.putIfAbsent(resourceableId, theCourse);
 			if(cachedCourse != null) {
 				course = cachedCourse;
@@ -274,10 +274,10 @@ public class CourseFactory {
 		} else {
 			course.updateCourseEntry(courseEntry);
 		}
-		
+
 		return course;
 	}
-	
+
 	public static ICourse loadCourse(final Long resourceableId) {
 		if (resourceableId == null) throw new AssertException("No resourceable ID found.");
 		PersistingCourseImpl course = loadedCourses.get(resourceableId);
@@ -287,7 +287,7 @@ public class CourseFactory {
 			OLATResource resource = OLATResourceManager.getInstance().findResourceable(resourceableId, "CourseModule");
 			PersistingCourseImpl theCourse = new PersistingCourseImpl(resource);
 			theCourse.load();
-			
+
 			PersistingCourseImpl cachedCourse = loadedCourses.putIfAbsent(resourceableId, theCourse);
 			if(cachedCourse != null) {
 				course = cachedCourse;
@@ -300,7 +300,7 @@ public class CourseFactory {
 
 	/**
 	 * Load the course for the given course resourceable
-	 * 
+	 *
 	 * @param olatResource
 	 * @return the course for the given course resourceable
 	 */
@@ -308,30 +308,30 @@ public class CourseFactory {
 		Long resourceableId = olatResource.getResourceableId();
 		return loadCourse(resourceableId);
 	}
-			
+
 	/**
-	 * 
+	 *
 	 * @param resourceableId
 	 */
 	private static void removeFromCache(Long resourceableId) { //o_clusterOK by: ld
-		loadedCourses.remove(resourceableId);	
+		loadedCourses.remove(resourceableId);
 		log.debug("removeFromCache");
 	}
-	
+
 	/**
 	 * Puts the current course in the local cache and removes it from other caches (other cluster nodes).
 	 * @param resourceableId
 	 * @param course
 	 */
-	private static void updateCourseInCache(Long resourceableId, PersistingCourseImpl course) { //o_clusterOK by:ld    
-		loadedCourses.update(resourceableId, course);				
+	private static void updateCourseInCache(Long resourceableId, PersistingCourseImpl course) { //o_clusterOK by:ld
+		loadedCourses.update(resourceableId, course);
 		log.debug("updateCourseInCache");
 	}
 
 	/**
 	 * Delete a course including its course folder and all references to resources
 	 * this course holds.
-	 * 
+	 *
 	 * @param res
 	 */
 	public static void deleteCourse(RepositoryEntry entry, OLATResource res) {
@@ -344,7 +344,7 @@ public class CourseFactory {
 		} catch (CorruptedCourseException e) {
 			log.error("Try to delete a corrupted course, I make want I can.");
 		}
-		
+
 		// call cleanupOnDelete for nodes
 		if(course != null) {
 			Visitor visitor = new NodeDeletionVisitor(course);
@@ -364,7 +364,7 @@ public class CourseFactory {
 		if(course != null) {
 			CourseConfigManagerImpl.getInstance().deleteConfigOf(course);
 		}
-		
+
 		CoreSpringFactory.getImpl(TaskExecutorManager.class).delete(res);
 
 		// delete course group- and rightmanagement
@@ -405,7 +405,7 @@ public class CourseFactory {
 		CalendarManager calMan = CoreSpringFactory.getImpl(CalendarManager.class);
 		CalendarNotificationManager notificationManager = CoreSpringFactory.getImpl(CalendarNotificationManager.class);
 		NotificationsManager nfm = NotificationsManager.getInstance();
-		
+
 		if(course != null) {
 			CourseGroupManager courseGroupManager = course.getCourseEnvironment().getCourseGroupManager();
 			List<BusinessGroup> learningGroups = courseGroupManager.getAllBusinessGroups();
@@ -423,7 +423,7 @@ public class CourseFactory {
 		try {
 			/**
 			 * TODO:gs 2010-01-26
-			 * OLAT-4947: if we do not have an repo entry we get an exception here. 
+			 * OLAT-4947: if we do not have an repo entry we get an exception here.
 			 * This is normal in the case of courseimport and click canceling.
 			 */
 			KalendarRenderWrapper courseCalendar = calMan.getCalendarForDeletion(res);
@@ -436,12 +436,12 @@ public class CourseFactory {
 			//if we have a broken course (e.g. canceled import or no repo entry somehow) skip calendar deletion...
 		}
 	}
-	
+
 	/**
 	 * Copies a course. More specifically, the run and editor structures and the
 	 * course folder will be copied to create a new course.
-	 *  
-	 * 
+	 *
+	 *
 	 * @param sourceRes
 	 * @param ureq
 	 * @return copy of the course.
@@ -450,10 +450,10 @@ public class CourseFactory {
 		PersistingCourseImpl sourceCourse = (PersistingCourseImpl)loadCourse(sourceRes);
 		PersistingCourseImpl targetCourse = new PersistingCourseImpl(targetRes);
 		File fTargetCourseBasePath = targetCourse.getCourseBaseContainer().getBasefile();
-		
+
 		//close connection before file copy
 		DBFactory.getInstance().commitAndCloseSession();
-		
+
 		synchronized (sourceCourse) { // o_clusterNOK - cannot be solved with doInSync since could take too long (leads to error: "Lock wait timeout exceeded")
 			// copy configuration
 			CourseConfig courseConf = CourseConfigManagerImpl.getInstance().copyConfigOf(sourceCourse);
@@ -467,7 +467,7 @@ public class CourseFactory {
 			// copy course folder
 			File fSourceCourseFolder = sourceCourse.getIsolatedCourseBaseFolder();
 			if (fSourceCourseFolder.exists()) FileUtils.copyDirToDir(fSourceCourseFolder, fTargetCourseBasePath, false, "copy course folder");
-			
+
 			// copy folder nodes directories
 			File fSourceFoldernodesFolder = new File(FolderConfig.getCanonicalRoot()
 					+ BCCourseNode.getFoldernodesPathRelToFolderBase(sourceCourse.getCourseEnvironment()));
@@ -477,7 +477,7 @@ public class CourseFactory {
 			File fSourceTaskfoldernodesFolder = new File(FolderConfig.getCanonicalRoot()
 					+ TACourseNode.getTaskFoldersPathRelToFolderRoot(sourceCourse.getCourseEnvironment()));
 			if (fSourceTaskfoldernodesFolder.exists()) FileUtils.copyDirToDir(fSourceTaskfoldernodesFolder, fTargetCourseBasePath, false, "copy task folder directories");
-			
+
 			// update references
 			List<Reference> refs = referenceManager.getReferences(sourceCourse);
 			int count = 0;
@@ -487,7 +487,7 @@ public class CourseFactory {
 					DBFactory.getInstance().intermediateCommit();
 				}
 			}
-			
+
 			// set quotas
 			Quota sourceQuota = VFSManager.isTopLevelQuotaContainer(sourceCourse.getCourseFolderContainer());
 			Quota targetQuota = VFSManager.isTopLevelQuotaContainer(targetCourse.getCourseFolderContainer());
@@ -499,12 +499,12 @@ public class CourseFactory {
 				}
 			}
 		}
-		return targetRes;			
+		return targetRes;
 	}
 
 	/**
-	 * Exports an entire course to a zip file. 
-	 * 
+	 * Exports an entire course to a zip file.
+	 *
 	 * @param sourceRes
 	 * @param fTargetZIP
 	 * @return true if successfully exported, false otherwise.
@@ -532,7 +532,7 @@ public class CourseFactory {
 
 	/**
 	 * Import a course from a ZIP file.
-	 * 
+	 *
 	 * @param ores
 	 * @param zipFile
 	 * @return New Course.
@@ -541,17 +541,17 @@ public class CourseFactory {
 		// Generate course with filesystem
 		PersistingCourseImpl newCourse = new PersistingCourseImpl(ores);
 		CourseConfigManagerImpl.getInstance().deleteConfigOf(newCourse);
-		
+
 		// Unzip course strucure in new course
 		File fCanonicalCourseBasePath = newCourse.getCourseBaseContainer().getBasefile();
 		if (ZipUtil.unzip(zipFile, fCanonicalCourseBasePath)) {
 			// Load course strucure now
 			try {
 				newCourse.load();
-				CourseConfig cc = CourseConfigManagerImpl.getInstance().loadConfigFor(newCourse);								
+				CourseConfig cc = CourseConfigManagerImpl.getInstance().loadConfigFor(newCourse);
 				//newCourse is not in cache yet, so we cannot call setCourseConfig()
 				newCourse.setCourseConfig(cc);
-				loadedCourses.put(newCourse.getResourceableId(), newCourse);						
+				loadedCourses.put(newCourse.getResourceableId(), newCourse);
 				return newCourse;
 			} catch (AssertException ae) {
 				// ok failed, cleanup below
@@ -568,7 +568,7 @@ public class CourseFactory {
 	 * Deploys a course from an exported course ZIP file. This process is unatended and
 	 * therefore relies on some default assumptions on how to setup the entry and add
 	 * any referenced resources to the repository.
-	 * 
+	 *
 	 * @param exportedCourseZIPFile
 	 */
 	public static RepositoryEntry deployCourseFromZIP(File exportedCourseZIPFile, String softKey, int access) {
@@ -582,21 +582,21 @@ public class CourseFactory {
 			log.info("RepositoryEntry with softkey " + softKey + " already exists. Course will not be deployed.");
 			return existingEntry;
 		}
-		
-		
+
+
 		RepositoryHandler courseHandler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(CourseModule.getCourseTypeName());
 		RepositoryEntry re = courseHandler.importResource(null, importExport.getInitialAuthor(), importExport.getDisplayName(), importExport.getDescription(),
 				true, Locale.ENGLISH, exportedCourseZIPFile, exportedCourseZIPFile.getName());
-		
+
 		re.setSoftkey(softKey);
 		repositoryService.update(re);
-		
+
 		ICourse course = loadCourse(re);
 		publishCourse(course, access, false,  null, Locale.ENGLISH);
 		return re;
 	}
 
-	
+
 	/**
 	 * Publish the course with some standard options
 	 * @param course
@@ -617,7 +617,7 @@ public class CourseFactory {
 		 //RepositoryEntry.ACC_USERS_GUESTS // users and guests can see the course
 		 //fxdiff VCRP-1,2: access control of resources
 		 publishProcess.changeGeneralAccess(identity, newAccess, membersOnly);
-		 
+
 		 if (publishTreeModel.hasPublishableChanges()) {
 			 List<String>nodeToPublish = new ArrayList<String>();
 			 visitPublishModel(publishTreeModel.getRootNode(), publishTreeModel, nodeToPublish);
@@ -632,7 +632,7 @@ public class CourseFactory {
 					 return;
 				 }
 			 }
-			 
+
 			 try {
 				 course = CourseFactory.openCourseEditSession(course.getResourceableId());
 				 publishProcess.applyPublishSet(identity, locale);
@@ -646,7 +646,7 @@ public class CourseFactory {
 
 	/**
 	 * Create a user locale dependent help-course run controller
-	 * 
+	 *
 	 * @param ureq The user request
 	 * @param wControl The current window controller
 	 * @return The help-course run controller
@@ -670,19 +670,19 @@ public class CourseFactory {
 			// Increment launch counter
 			rs.incrementLaunchCounter(entry);
 			ICourse course = loadCourse(entry);
-			
+
 			ContextEntry ce = BusinessControlFactory.getInstance().createContextEntry(entry);
-			WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ce, wControl);	
+			WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ce, wControl);
 			RepositoryEntrySecurity reSecurity = new RepositoryEntrySecurity(false, false, false, false, false, false, false, true);
 			RunMainController launchC = new RunMainController(ureq, bwControl, null, course, entry, reSecurity, null);
-			return launchC;			
-		}		
+			return launchC;
+		}
 	}
 
 	/**
 	 * visit all nodes in the specified course and make them archiving any data
 	 * into the identity's export directory.
-	 * 
+	 *
 	 * @param res
 	 * @param charset
 	 * @param locale
@@ -697,11 +697,11 @@ public class CourseFactory {
 		boolean isOresInstitutionalManager = RepositoryManager.getInstance().isInstitutionalRessourceManagerFor(identity, roles, courseRe);
 		archiveCourse(identity, course, charset, locale, exportDirectory, isOLATAdmin, isOresOwner, isOresInstitutionalManager);
 	}
-		
+
 	/**
 	 * visit all nodes in the specified course and make them archiving any data
 	 * into the identity's export directory.
-	 * 
+	 *
 	 * @param res
 	 * @param charset
 	 * @param locale
@@ -711,25 +711,25 @@ public class CourseFactory {
 		// archive course results overview
 		List<Identity> users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment());
 		List<AssessableCourseNode> nodes = ScoreAccountingHelper.loadAssessableNodes(course.getCourseEnvironment());
-		
+
 		String result = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, locale);
 		String fileName = ExportUtil.createFileNameWithTimeStamp(course.getCourseTitle(), "xls");
 		ExportUtil.writeContentToFile(fileName, result, exportDirectory, charset);
-		
+
 		// archive all nodes content
 		Visitor archiveV = new NodeArchiveVisitor(locale, course, exportDirectory, charset);
 		TreeVisitor tv = new TreeVisitor(archiveV, course.getRunStructure().getRootNode(), true);
 		tv.visitAll();
 		// archive all course log files
-		//OLATadmin gets all logfiles independent of the visibility configuration		
+		//OLATadmin gets all logfiles independent of the visibility configuration
 		boolean isOresOwner = (oresRights.length > 0)?oresRights[0]:false;
 		boolean isOresInstitutionalManager = (oresRights.length > 1)?oresRights[1]:false;
-		
+
 		boolean aLogV = isOresOwner || isOresInstitutionalManager || isOLATAdmin;
 		boolean uLogV = isOLATAdmin;
 		boolean sLogV = isOresOwner || isOresInstitutionalManager || isOLATAdmin;
-		
-		// make an intermediate commit here to make sure long running course log export doesn't 
+
+		// make an intermediate commit here to make sure long running course log export doesn't
 		// cause db connection timeout to be triggered
 		//@TODO transactions/backgroundjob:
 		// rework when backgroundjob infrastructure exists
@@ -741,15 +741,15 @@ public class CourseFactory {
 		}, course.getResourceableId(), exportDirectory.getPath(), null, null, aLogV, uLogV, sLogV, charset, null, null);
 
 		course.getCourseEnvironment().getCourseGroupManager().archiveCourseGroups(exportDirectory);
-		
+
 		CoreSpringFactory.getImpl(ChatLogHelper.class).archive(course, exportDirectory);
-		
+
 	}
 
 	/**
 	 * Returns the data export directory. If the directory does not yet exist the
 	 * directory will be created
-	 * 
+	 *
 	 * @param ureq The user request
 	 * @param courseName The course name or title. Will be used as directory name
 	 * @return The file representing the dat export directory
@@ -767,11 +767,11 @@ public class CourseFactory {
 		}
 		return exportFolder;
 	}
-	
-	
+
+
 	/**
-	 * Returns the data export directory. 
-	 * 
+	 * Returns the data export directory.
+	 *
 	 * @param ureq The user request
 	 * @param courseName The course name or title. Will be used as directory name
 	 * @return The file representing the dat export directory
@@ -783,7 +783,7 @@ public class CourseFactory {
 						+ Formatter.makeStringFilesystemSave(courseName));
 		return exportFolder;
 	}
-	
+
 	/**
 	 * Returns the personal folder of the given identity.
 	 * <p>
@@ -797,13 +797,13 @@ public class CourseFactory {
 		if (identity==null) {
 			return null;
 		}
-		return new File(FolderConfig.getCanonicalRoot() + FolderConfig.getUserHomes() + "/" + identity.getName());		
+		return new File(FolderConfig.getCanonicalRoot() + FolderConfig.getUserHomes() + "/" + identity.getName());
 	}
-	
+
 	/**
 	 * Returns the data export directory. If the directory does not yet exist the
 	 * directory will be created
-	 * 
+	 *
 	 * @param ureq The user request
 	 * @param courseName The course name or title. Will be used as directory name
 	 * @return The file representing the dat export directory
@@ -821,14 +821,14 @@ public class CourseFactory {
 		}
 		return exportFolder;
 	}
-	
+
 	/**
 	 * Stores the editor tree model AND the run structure (both xml files). Called at publish.
 	 * @param resourceableId
 	 */
 	public static void saveCourse(final Long resourceableId) {
 		if (resourceableId == null) throw new AssertException("No resourceable ID found.");
-				
+
 		PersistingCourseImpl theCourse = getCourseEditSession(resourceableId);
 		if(theCourse!=null) {
 			//o_clusterOK by: ld (although the course is locked for editing, we still have to insure that load course is synchronized)
@@ -839,10 +839,10 @@ public class CourseFactory {
 						course.initHasAssessableNodes();
 						course.saveRunStructure();
 						course.saveEditorTreeModel();
-		        
+
 						//clear modifyCourseEvents at publish, since the updateCourseInCache is called anyway
 						modifyCourseEvents.remove(resourceableId);
-						updateCourseInCache(resourceableId, course);		        
+						updateCourseInCache(resourceableId, course);
 					} else if(!course.isReadAndWrite()) {
 						throw new AssertException("Cannot saveCourse because theCourse is readOnly! You have to open an courseEditSession first!");
 					}
@@ -852,20 +852,20 @@ public class CourseFactory {
 			throw new AssertException("Cannot saveCourse because theCourse is null! Have you opened a courseEditSession yet?");
 		}
 	}
-	
+
 	/**
 	 * Stores ONLY the editor tree model (e.g. at course tree editing - add/remove/move course nodes).
 	 * @param resourceableId
 	 */
 	public static void saveCourseEditorTreeModel(Long resourceableId) {
 		if (resourceableId == null) throw new AssertException("No resourceable ID found.");
-				
-		PersistingCourseImpl course = getCourseEditSession(resourceableId);		
-		if(course!=null && course.isReadAndWrite()) {	
+
+		PersistingCourseImpl course = getCourseEditSession(resourceableId);
+		if(course!=null && course.isReadAndWrite()) {
 			synchronized(loadedCourses) { //o_clusterOK by: ld (clusterOK since the course is locked for editing)
 		    course.saveEditorTreeModel();
-		   
-		    modifyCourseEvents.putIfAbsent(resourceableId, new ModifyCourseEvent(resourceableId));	
+
+		    modifyCourseEvents.putIfAbsent(resourceableId, new ModifyCourseEvent(resourceableId));
 			}
 		} else if(course==null) {
 			throw new AssertException("Cannot saveCourseEditorTreeModel because course is null! Have you opened a courseEditSession yet?");
@@ -873,25 +873,25 @@ public class CourseFactory {
 			throw new AssertException("Cannot saveCourse because theCourse is readOnly! You have to open an courseEditSession first!");
 		}
 	}
-	
+
 	/**
 	 * Updates the course cache forcing other cluster nodes to reload this course. <br/>
 	 * This is triggered after the course editor is closed. <br/>
 	 * It also removes the courseEditSession for this course.
-	 * 
+	 *
 	 * @param resourceableId
 	 */
 	public static void fireModifyCourseEvent(Long resourceableId) {
-		ModifyCourseEvent modifyCourseEvent = modifyCourseEvents.get(resourceableId); 
+		ModifyCourseEvent modifyCourseEvent = modifyCourseEvents.get(resourceableId);
 		if(modifyCourseEvent!=null){
 			synchronized(modifyCourseEvents) { //o_clusterOK by: ld
 				modifyCourseEvent = modifyCourseEvents.remove(resourceableId);
-				if(modifyCourseEvent != null) {					
+				if(modifyCourseEvent != null) {
 					PersistingCourseImpl course = getCourseEditSession(resourceableId);
 			    if(course!=null) {
-			    	updateCourseInCache(resourceableId, course);			    	
+			    	updateCourseInCache(resourceableId, course);
 			    }
-				}				
+				}
 			}
 		}
 		//close courseEditSession if not already closed
@@ -901,7 +901,7 @@ public class CourseFactory {
 	/**
 	 * Create a custom css object for the course layout. This can then be set on a
 	 * MainLayoutController to activate the course layout
-	 * 
+	 *
 	 * @param usess The user session
 	 * @param courseEnvironment the course environment
 	 * @return The custom course css or NULL if no course css is available
@@ -931,7 +931,7 @@ public class CourseFactory {
 			throw new OLATRuntimeException(PersistingCourseImpl.class, "Could not resolve course base path:" + courseRootContainer, null);
 		return courseRootContainer;
 	}
-	
+
 	/**
 	 * Save courseConfig and update cache.
 	 * @param resourceableId
@@ -939,7 +939,7 @@ public class CourseFactory {
 	 */
 	public static void setCourseConfig(final Long resourceableId, final CourseConfig cc) {
 		if (resourceableId == null) throw new AssertException("No resourceable ID found.");
-		
+
 		PersistingCourseImpl theCourse = getCourseEditSession(resourceableId);
 		if(theCourse!=null) {
 			//o_clusterOK by: ld (although the course is locked for editing, we still have to insure that load course is synchronized)
@@ -954,14 +954,14 @@ public class CourseFactory {
 			});
 		} else {
 			throw new AssertException("Cannot setCourseConfig because theCourse is null! Have you opened a courseEditSession yet?");
-		}	
+		}
 	}
-	
+
 	/**
 	 * Loads the course or gets it from cache, and adds it to the courseEditSessionMap. <br/>
 	 * It guarantees that the returned value is never null. <br/>
 	 * The courseEditSession object should live between acquire course lock and release course lock.
-	 * 
+	 *
 	 * TODO: remove course from courseEditSessionMap at close course editor
 	 * @param resourceableId
 	 * @return
@@ -976,19 +976,19 @@ public class CourseFactory {
 			course.setReadAndWrite(true);
 			courseEditSessionMap.put(resourceableId, course);
 			log.debug("getCourseEditSession - put course in courseEditSessionMap: " + resourceableId);
-		}	
+		}
 		return course;
 	}
-	
+
 	public static boolean isCourseEditSessionOpen(Long resourceableId) {
 		return courseEditSessionMap.containsKey(resourceableId);
 	}
-	
+
 	/**
 	 * Provides the currently edited course object with this id. <br/>
 	 * It guarantees that the returned value is never null if the openCourseEditSession was called first. <br/>
 	 * The CourseEditSession object should live between acquire course lock and release course lock.
-	 * 
+	 *
 	 * TODO: remove course from courseEditSessionMap at close course editor
 	 * @param resourceableId
 	 * @return
@@ -998,10 +998,10 @@ public class CourseFactory {
 		PersistingCourseImpl course = courseEditSessionMap.get(resourceableId);
 		if(course==null) {
 			throw new AssertException("No edit session open for this course: " + resourceableId + " - Open a session first!");
-		}	
+		}
 		return course;
 	}
-	
+
 	/**
 	 * TODO: remove course from courseEditSessionMap at releaseLock
 	 * @param resourceableId
@@ -1016,7 +1016,7 @@ public class CourseFactory {
 		  log.debug("removeCourseEditSession for course: " + resourceableId);
 		}
 	}
-	
+
 	private static void visitPublishModel(TreeNode node, PublishTreeModel publishTreeModel, Collection<String> nodeToPublish) {
 		int numOfChildren = node.getChildCount();
 		for (int i = 0; i < numOfChildren; i++) {
@@ -1027,7 +1027,7 @@ public class CourseFactory {
 			}
 		}
 	}
-	
+
 	private static class NodeArchiveVisitor implements Visitor {
 		private File exportPath;
 		private Locale locale;
@@ -1057,7 +1057,7 @@ public class CourseFactory {
 			String archiveName = cn.getType() + "_"
 					+ StringHelper.transformDisplayNameToFileSystemName(cn.getShortName())
 					+ "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis()));
-			
+
 			FileOutputStream fileStream = null;
 			ZipOutputStream exportStream = null;
 			try {
@@ -1073,14 +1073,14 @@ public class CourseFactory {
 			}
 		}
 	}
-	
+
 	private static class NodeDeletionVisitor implements Visitor {
 
 		private ICourse course;
 
 		/**
 		 * Constructor of the node deletion visitor
-		 * 
+		 *
 		 * @param course
 		 */
 		public NodeDeletionVisitor(ICourse course) {
@@ -1089,7 +1089,7 @@ public class CourseFactory {
 
 		/**
 		 * Visitor pattern to delete the course nodes
-		 * 
+		 *
 		 * @see org.olat.core.util.tree.Visitor#visit(org.olat.core.util.nodes.INode)
 		 */
 		public void visit(INode node) {
@@ -1100,11 +1100,11 @@ public class CourseFactory {
 }
 
 /**
- * 
+ *
  * Description:<br>
- * Event triggered if a course was edited - namely the course tree model have changed 
+ * Event triggered if a course was edited - namely the course tree model have changed
  * (e.g. nodes added, deleted)
- * 
+ *
  * <P>
  * Initial Date:  22.07.2008 <br>
  * @author Lavinia Dumitrescu
@@ -1117,9 +1117,9 @@ class ModifyCourseEvent extends MultiUserEvent {
 	 */
 	public ModifyCourseEvent(Long resourceableId) {
 		super("modify_course");
-		courseId = resourceableId;		
+		courseId = resourceableId;
 	}
-	
+
 	public Long getCourseId() {
 		return courseId;
 	}
diff --git a/src/main/java/org/olat/course/nodes/VideoCourseNode.java b/src/main/java/org/olat/course/nodes/VideoCourseNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..73a6011d2471b7cdd1c1a083c5aaa9a172811a37
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/VideoCourseNode.java
@@ -0,0 +1,159 @@
+/**
+* OLAT - Online Learning and Training<br>
+* http://www.olat.org
+* <p>
+* Licensed under the Apache License, Version 2.0 (the "License"); <br>
+* you may not use this file except in compliance with the License.<br>
+* You may obtain a copy of the License at
+* <p>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p>
+* Unless required by applicable law or agreed to in writing,<br>
+* software distributed under the License is distributed on an "AS IS" BASIS, <br>
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+* See the License for the specific language governing permissions and <br>
+* limitations under the License.
+* <p>
+* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
+* University of Zurich, Switzerland.
+* <hr>
+* <a href="http://www.openolat.org">
+* OpenOLAT - Online Learning and Training</a><br>
+* This file has been modified by the OpenOLAT community. Changes are licensed
+* under the Apache 2.0 license as the original file.
+*/
+
+package org.olat.course.nodes;
+
+import java.io.File;
+import java.util.List;
+import java.util.Locale;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.stack.BreadcrumbPanel;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.tabbable.TabbableController;
+import org.olat.core.id.Identity;
+import org.olat.core.util.Util;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.course.ICourse;
+import org.olat.course.condition.ConditionEditController;
+import org.olat.course.editor.CourseEditorEnv;
+import org.olat.course.editor.NodeEditController;
+import org.olat.course.editor.StatusDescription;
+import org.olat.course.nodes.video.VideoEditController;
+import org.olat.course.nodes.video.VideoPeekviewController;
+import org.olat.course.nodes.video.VideoRunController;
+import org.olat.course.run.navigation.NodeRunConstructionResult;
+import org.olat.course.run.userview.NodeEvaluation;
+import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.fileresource.types.ImsCPFileResource;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryImportExport;
+import org.olat.repository.handlers.RepositoryHandler;
+import org.olat.repository.handlers.RepositoryHandlerFactory;
+
+public class VideoCourseNode extends AbstractAccessableCourseNode {
+
+	private static final long serialVersionUID = -3808867902051897291L;
+	private static final String TYPE = "video";
+
+	public VideoCourseNode() {
+		super(TYPE);
+		updateModuleConfigDefaults(true);
+	}
+
+	@Override
+	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) {
+		updateModuleConfigDefaults(false);
+		VideoEditController childTabCntrllr = new VideoEditController(this, ureq, wControl, stackPanel, course, euce);
+		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
+		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, childTabCntrllr);
+	}
+
+	@Override
+	public RepositoryEntry getReferencedRepositoryEntry() {
+		RepositoryEntry entry = VideoEditController.getVideoReference(getModuleConfiguration(), false);
+		return entry;
+	}
+
+	@Override
+	public boolean needsReferenceToARepositoryEntry() {
+		return true;
+	}
+
+	@Override
+	public NodeRunConstructionResult createNodeRunConstructionResult(
+			UserRequest ureq, WindowControl wControl,
+			UserCourseEnvironment userCourseEnv, NodeEvaluation ne,
+			String nodecmd) {
+		NodeRunConstructionResult ncr;
+		updateModuleConfigDefaults(false);
+		VideoRunController cprunC = new VideoRunController(getModuleConfiguration(), wControl, ureq, this);
+		ncr = cprunC.createNodeRunConstructionResult(ureq);
+		return ncr;
+	}
+
+	@Override
+	public StatusDescription isConfigValid(){
+		if (oneClickStatusCache != null) { return oneClickStatusCache[0]; }
+
+		StatusDescription sd = StatusDescription.NOERROR;
+		boolean isValid = VideoEditController.isModuleConfigValid(getModuleConfiguration());
+		if (!isValid) {
+			// FIXME: refine statusdescriptions
+			String shortKey = "no.video.chosen";
+			String longKey = "error.noreference.long";
+			String[] params = new String[] { this.getShortTitle() };
+			String translPackage = Util.getPackageName(VideoEditController.class);
+			sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translPackage);
+			sd.setDescriptionForUnit(getIdent());
+			// set which pane is affected by error
+			sd.setActivateableViewIdentifier(VideoEditController.PANE_TAB_VIDEOCONFIG);
+		}
+		return sd;
+	}
+
+	@Override
+	public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
+		// only here we know which translator to take for translating condition
+		// error messages
+		String translatorStr = Util.getPackageName(ConditionEditController.class);
+		List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		return StatusDescriptionHelper.sort(statusDescs);
+	}
+
+	@Override
+	public void exportNode(File exportDirectory, ICourse course) {
+		RepositoryEntry re = VideoEditController.getVideoReference(getModuleConfiguration(), false);
+		if (re == null) return;
+		File fExportDirectory = new File(exportDirectory, getIdent());
+		fExportDirectory.mkdirs();
+		RepositoryEntryImportExport reie = new RepositoryEntryImportExport(re, fExportDirectory);
+		reie.exportDoExport();
+	}
+
+	@Override
+	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale, boolean withReferences) {
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(withReferences && rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(ImsCPFileResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getInitialAuthor(), rie.getDisplayName(),
+					rie.getDescription(), false, locale, rie.importGetExportedFile(), null);
+			VideoEditController.setVideoReference(re, getModuleConfiguration());
+		} else {
+			VideoEditController.removeVideoReference(getModuleConfiguration());
+		}
+	}
+
+	@Override
+	public Controller createPeekViewRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
+			NodeEvaluation ne) {
+//		updateModuleConfigDefaults(false);
+		VFSContainer mediaFolder = FileResourceManager.getInstance().getFileResourceMedia(getReferencedRepositoryEntry().getOlatResource());
+		Controller controller = new VideoPeekviewController(ureq, wControl, mediaFolder);
+		return controller;
+	}
+}
diff --git a/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_de.properties
index c020cc1c29988bf615d20907f491259ba51f4d24..c4feec424fd8b38b5bf8a63e2bc77780ca69fa4a 100644
--- a/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_de.properties
@@ -31,3 +31,4 @@ title_projectbroker=Themenvergabe
 title_podcast=Podcast
 title_blog=Blog
 personal.title=Leistungsübersicht
+title_video=Video
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_en.properties
index 50c0dde4c6090394f8a7e3b61f2454cb4ebf4a45..0ad67566bcd973c4b2be8e1e6d23f9f82ced9151 100644
--- a/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/_i18n/LocalStrings_en.properties
@@ -30,4 +30,5 @@ title_st=Structure
 title_ta=<s>Task (deprecated)</s>
 title_tu=External page
 title_wiki=Wiki
+title_video=Video
 personal.title=Performance summary
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
index 3ced0e9cb3c474a0db929aef15cbb14c189e766a..9c91f7dfb363927f6176844b70c9331d6f634594 100644
--- a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
+++ b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
@@ -89,6 +89,10 @@
 		</property>
 	</bean>
 	
+	<bean id="video" class="org.olat.course.nodes.video.VideoCourseNodeConfiguration" scope="prototype">
+		<property name="order" value="220" />
+	</bean>
+	
 	<bean id="ita" class="org.olat.course.nodes.gta.GTACourseNodeConfiguration" scope="prototype">
 		<constructor-arg index="0" value="true" />
 		<property name="order" value="131" />
diff --git a/src/main/java/org/olat/course/nodes/video/VideoCourseNodeConfiguration.java b/src/main/java/org/olat/course/nodes/video/VideoCourseNodeConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0ccbdd8dd0704d669abd0d6c54fa549269a830b
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/VideoCourseNodeConfiguration.java
@@ -0,0 +1,53 @@
+package org.olat.course.nodes.video;
+
+import java.util.Locale;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.gui.translator.Translator;
+import org.olat.core.util.Util;
+import org.olat.course.nodes.AbstractCourseNodeConfiguration;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.CourseNodeConfiguration;
+import org.olat.course.nodes.CourseNodeGroup;
+import org.olat.course.nodes.VideoCourseNode;
+import org.olat.modules.video.VideoModule;
+
+public class VideoCourseNodeConfiguration  extends AbstractCourseNodeConfiguration {
+
+	private VideoCourseNodeConfiguration() {
+		super();
+	}
+
+	@Override
+	public CourseNode getInstance() {
+		return new VideoCourseNode();
+	}
+
+	@Override
+	public String getLinkText(Locale locale) {
+		Translator fallback = Util.createPackageTranslator(CourseNodeConfiguration.class, locale);
+		Translator translator = Util.createPackageTranslator(this.getClass(), locale, fallback);
+		return translator.translate("title_video");
+	}
+
+	@Override
+	public String getIconCSSClass() {
+		return "o_FileResource-MOVIE_icon";
+	}
+
+	@Override
+	public String getAlias() {
+		return "video";
+	}
+
+	@Override
+	public String getGroup() {
+		return CourseNodeGroup.content.name();
+	}
+
+	@Override
+	public boolean isEnabled() {
+		return CoreSpringFactory.getImpl(VideoModule.class).isCoursenodeEnabled();
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/video/VideoEditController.java b/src/main/java/org/olat/course/nodes/video/VideoEditController.java
new file mode 100644
index 0000000000000000000000000000000000000000..feffe2b50d13b9e4c753c045ff7fa3c8b4f43841
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/VideoEditController.java
@@ -0,0 +1,370 @@
+package org.olat.course.nodes.video;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
+import org.olat.core.gui.components.form.flexible.elements.SelectionElement;
+import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.panel.Panel;
+import org.olat.core.gui.components.stack.BreadcrumbPanel;
+import org.olat.core.gui.components.tabbedpane.TabbedPane;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.ControllerEventListener;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.gui.control.generic.tabbable.ActivateableTabbableDefaultController;
+import org.olat.core.logging.AssertException;
+import org.olat.core.util.StringHelper;
+import org.olat.course.ICourse;
+import org.olat.course.assessment.AssessmentHelper;
+import org.olat.course.condition.Condition;
+import org.olat.course.condition.ConditionEditController;
+import org.olat.course.editor.NodeEditController;
+import org.olat.course.nodes.VideoCourseNode;
+import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.fileresource.types.VideoFileResource;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.modules.video.ui.VideoDisplayController;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.controllers.ReferencableEntriesSearchController;
+import org.olat.resource.OLATResource;
+
+public class VideoEditController  extends ActivateableTabbableDefaultController implements ControllerEventListener {
+
+	public static final String PANE_TAB_VIDEOCONFIG = "pane.tab.videoconfig";
+	private static final String PANE_TAB_ACCESSIBILITY = "pane.tab.accessibility";
+	final static String[] paneKeys = { PANE_TAB_VIDEOCONFIG, PANE_TAB_ACCESSIBILITY };
+
+	// NLS support:
+	public static final String NLS_ERROR_VIDEOREPOENTRYMISSING = "error.videorepoentrymissing";
+	private static final String NLS_CONDITION_ACCESSIBILITY_TITLE = "condition.accessibility.title";
+	private static final String NLS_COMMAND_CHOOSEVIDEO = "command.choosevideo";
+	private static final String NLS_COMMAND_CREATEVID = "command.createvideo";
+	private static final String NLS_COMMAND_CHANGEVID = "command.changevideo";
+
+	public static final String CONFIG_KEY_REPOSITORY_SOFTKEY = "reporef";
+	public static final String CONFIG_KEY_AUTOPLAY = "autoplay";
+	public static final String CONFIG_KEY_COMMENTS = "comments";
+	public static final String CONFIG_KEY_RATING = "rating";
+	public static final String CONFIG_KEY_DESCRIPTION_SELECT = "descriptionSelect";
+	public static final String CONFIG_KEY_DESCRIPTION_CUSTOMTEXT = "descriptionText";
+
+	private static final String VC_CHOSENVIDEO = "chosenvideo";
+	private static final String NLS_NO_VIDEO_CHOSEN = "no.video.chosen";
+
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+
+	private Panel main;
+	private VelocityContainer videoConfigurationVc;
+
+	private ModuleConfiguration config;
+	private RepositoryEntry re;
+
+	private ReferencableEntriesSearchController searchController;
+
+	private Link previewLink;
+	private Link chooseVideoButton;
+	private Link changeVideoButton;
+
+	private ConditionEditController accessibilityCondContr;
+	private Controller previewCtr;
+	private TabbedPane myTabbedPane;
+	private CloseableModalController cmc;
+
+	public VideoEditController(VideoCourseNode videoNode, UserRequest ureq, WindowControl wControl,  BreadcrumbPanel stackPanel,ICourse course, UserCourseEnvironment euce) {
+		super(ureq, wControl);
+		this.config = videoNode.getModuleConfiguration();
+		main = new Panel("videomain");
+
+		videoConfigurationVc = createVelocityContainer("edit");
+		chooseVideoButton = LinkFactory.createButtonSmall(NLS_COMMAND_CREATEVID, videoConfigurationVc, this);
+		chooseVideoButton.setElementCssClass("o_sel_cp_choose_repofile");
+		changeVideoButton = LinkFactory.createButtonSmall(NLS_COMMAND_CHANGEVID, videoConfigurationVc, this);
+		changeVideoButton.setElementCssClass("o_sel_cp_change_repofile");
+
+		if (config.get(CONFIG_KEY_REPOSITORY_SOFTKEY) != null) {
+			// fetch repository entry to display the repository entry title of the chosen cp
+						re = getVideoReference(config, false);
+						if (re == null) { // we cannot display the entries name, because the
+							// repository entry had been deleted between the time when it was chosen here, and now
+							showError(NLS_ERROR_VIDEOREPOENTRYMISSING);
+							videoConfigurationVc.contextPut("showPreviewButton", Boolean.FALSE);
+							videoConfigurationVc.contextPut(VC_CHOSENVIDEO, translate("no.video.chosen"));
+						} else {
+							videoConfigurationVc.contextPut("showPreviewButton", Boolean.TRUE);
+							String displayname = StringHelper.escapeHtml(re.getDisplayname());
+							previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayname, Link.NONTRANSLATED, videoConfigurationVc, this);
+							previewLink.setTitle(getTranslator().translate("command.preview"));
+							previewLink.setEnabled(true);
+						}
+						videoConfigurationVc.contextPut("showOptions", Boolean.TRUE);
+						VideoOptionsForm videoOptions = new VideoOptionsForm(ureq, getWindowControl(), re.getOlatResource(), config);
+						videoConfigurationVc.put("videoOptions", videoOptions.getInitialComponent());
+						listenTo(videoOptions);
+		} else {
+			// no valid config yet
+			videoConfigurationVc.contextPut("showPreviewButton", Boolean.FALSE);
+			videoConfigurationVc.contextPut("showOptions", Boolean.FALSE);
+			videoConfigurationVc.contextPut(VC_CHOSENVIDEO, translate(NLS_NO_VIDEO_CHOSEN));
+		}
+
+
+
+		// Accessibility precondition
+		Condition accessCondition = videoNode.getPreConditionAccess();
+		accessibilityCondContr = new ConditionEditController(ureq, getWindowControl(),
+		accessCondition, AssessmentHelper.getAssessableNodes(course.getEditorTreeModel(), videoNode), euce);
+		listenTo(accessibilityCondContr);
+
+		main.setContent(videoConfigurationVc);
+	}
+
+	@Override
+	public void addTabs(TabbedPane tabbedPane) {
+		myTabbedPane = tabbedPane;
+
+		tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), accessibilityCondContr.getWrappedDefaultAccessConditionVC(translate(NLS_CONDITION_ACCESSIBILITY_TITLE)));
+		tabbedPane.addTab(translate(PANE_TAB_VIDEOCONFIG), main);
+	}
+
+	@Override
+	public String[] getPaneKeys() {
+		return paneKeys;
+	}
+
+	@Override
+	public TabbedPane getTabbedPane() {
+		return myTabbedPane;
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if (source == chooseVideoButton || source == changeVideoButton) {
+			removeAsListenerAndDispose(searchController);
+			searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, new String[] {VideoFileResource.TYPE_NAME}, translate(NLS_COMMAND_CHOOSEVIDEO), true, false, false, false);
+			listenTo(searchController);
+
+			removeAsListenerAndDispose(cmc);
+			cmc = new CloseableModalController(
+					getWindowControl(), translate("close"), searchController.getInitialComponent(), true, translate(NLS_COMMAND_CHOOSEVIDEO)
+			);
+			listenTo(cmc);
+			cmc.activate();
+		}
+		if(source == previewLink){
+			VideoDisplayController previewController = null;
+			switch(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT)){
+
+			case "resourceDescription":
+					previewController = new VideoDisplayController(ureq, getWindowControl(), re, config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY), config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS), config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING), "", false, "");
+					break;
+			case "customDescription":
+					previewController = new VideoDisplayController(ureq, getWindowControl(), re, config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY), config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS), config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING), "", true, config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT));
+					break;
+			case "none":
+					previewController = new VideoDisplayController(ureq, getWindowControl(), re, config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY), config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS), config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING), "", true, "");
+					break;
+			}
+			cmc = new CloseableModalController(
+					getWindowControl(), translate("close"), previewController.getInitialComponent(), true, translate(NLS_COMMAND_CHOOSEVIDEO)
+			);
+			listenTo(cmc);
+			cmc.activate();
+		}
+	}
+
+	/**
+	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
+	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
+	 */
+	public void event(UserRequest urequest, Controller source, Event event) {
+		if (source == searchController) {
+			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
+				// search controller done
+				// -> close closeable modal controller
+				cmc.deactivate();
+				re = searchController.getSelectedEntry();
+				if (re != null) {
+					setVideoReference(re, config);
+					videoConfigurationVc.contextPut("showPreviewButton", Boolean.TRUE);
+					String displayname = StringHelper.escapeHtml(re.getDisplayname());
+					previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayname, Link.NONTRANSLATED, videoConfigurationVc, this);
+					previewLink.setCustomEnabledLinkCSS("o_preview");
+					previewLink.setTitle(getTranslator().translate("command.preview"));
+					// fire event so the updated config is saved by the editormaincontroller
+					fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+
+					videoConfigurationVc.contextPut("showOptions", Boolean.TRUE);
+					VideoOptionsForm videoOptions = new VideoOptionsForm(urequest, getWindowControl(), re.getOlatResource(), config);
+					videoConfigurationVc.put("videoOptions", videoOptions.getInitialComponent());
+					listenTo(videoOptions);
+				}
+			}
+		}
+
+		if (event == NodeEditController.NODECONFIG_CHANGED_EVENT){
+			fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+		}
+	}
+	@Override
+	protected void doDispose() {
+		//child controllers registered with listenTo() get disposed in BasicController
+		if (previewCtr != null) {
+			previewCtr.dispose();
+			previewCtr = null;
+		}
+	}
+
+	public static RepositoryEntry getVideoReference(ModuleConfiguration config, boolean strict) {
+		if (config == null) {
+			if (strict) throw new AssertException("missing config in Video");
+			else return null;
+		}
+		String repoSoftkey = (String) config.get(VideoEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
+		if (repoSoftkey == null) {
+			if (strict) throw new AssertException("invalid config when being asked for references");
+			else return null;
+		}
+		RepositoryManager rm = RepositoryManager.getInstance();
+		RepositoryEntry entry = rm.lookupRepositoryEntryBySoftkey(repoSoftkey, strict);
+		// entry can be null only if !strict
+		return entry;
+	}
+
+	/**
+	 * @param moduleConfiguration
+	 * @return boolean
+	 */
+	public static boolean isModuleConfigValid(ModuleConfiguration moduleConfiguration) {
+		return (moduleConfiguration.get(CONFIG_KEY_REPOSITORY_SOFTKEY) != null);
+	}
+
+	/**
+	 * Set the referenced repository entry.
+	 *
+	 * @param re
+	 * @param moduleConfiguration
+	 */
+	public static void setVideoReference(RepositoryEntry re, ModuleConfiguration moduleConfiguration) {
+		moduleConfiguration.set(CONFIG_KEY_REPOSITORY_SOFTKEY, re.getSoftkey());
+	}
+
+	public static void removeVideoReference(ModuleConfiguration moduleConfiguration){
+		moduleConfiguration.remove(CONFIG_KEY_REPOSITORY_SOFTKEY);
+	}
+}
+
+class VideoOptionsForm extends FormBasicController{
+
+	/**
+	 * Simple form for the Videooptions
+	 *
+	 * @author Dirk Furrer
+	 */
+	protected VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
+
+	private OLATResource video;
+	private SelectionElement videoComments;
+	private SelectionElement videoRating;
+	private SelectionElement videoAutoplay;
+	private SingleSelection description;
+	private RichTextElement descriptionField;
+	private boolean commentsEnabled;
+	private boolean ratingEnabled;
+	private boolean autoplay;
+	private ModuleConfiguration config;
+
+
+
+	VideoOptionsForm(UserRequest ureq, WindowControl wControl, OLATResource video, ModuleConfiguration moduleConfiguration) {
+		super(ureq, wControl);
+		this.config = moduleConfiguration;
+		this.video = video;
+		this.commentsEnabled = config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS);
+		this.ratingEnabled = config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING);
+		this.autoplay = config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY);
+		initForm(ureq);
+	}
+
+	public boolean isVideoComments() {
+		return videoComments.isSelected(0);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		config.setBooleanEntry(VideoEditController.CONFIG_KEY_COMMENTS, videoComments.isSelected(0));
+		config.setBooleanEntry(VideoEditController.CONFIG_KEY_RATING, videoRating.isSelected(0));
+		config.setBooleanEntry(VideoEditController.CONFIG_KEY_AUTOPLAY, videoAutoplay.isSelected(0));
+		config.setStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT, description.getSelectedKey());
+		if(description.getSelectedKey() == "customDescription"){
+			config.setStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT, descriptionField.getValue());
+		}
+		fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		videoComments = uifactory.addCheckboxesHorizontal("videoComments", "video.config.comments", formLayout, new String[]{"xx"}, new String[]{null});
+		videoComments.select("xx",commentsEnabled);
+		videoRating = uifactory.addCheckboxesHorizontal("videoRating", "video.config.rating", formLayout, new String[]{"xx"}, new String[]{null});
+		videoRating.select("xx",ratingEnabled);
+		videoAutoplay = uifactory.addCheckboxesHorizontal("videoAutoplay", "video.config.autoplay", formLayout, new String[]{"xx"}, new String[]{null});
+		videoAutoplay.select("xx",autoplay);
+
+		Map<String, String> descriptionOptions = new HashMap<String, String>();
+		descriptionOptions.put("none" ,"none");//TODO: internationalize
+		descriptionOptions.put("resourceDescription", "Resource description");
+		descriptionOptions.put("customDescription", "custom description");
+
+		description = uifactory.addDropdownSingleselect("video.config.description", formLayout, descriptionOptions.keySet().toArray(new String[3]), descriptionOptions.values().toArray(new String[3]), new String[3]);
+		description.addActionListener(FormEvent.ONCHANGE);
+		description.select(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT,"none"), true);
+		descriptionField = uifactory.addRichTextElementForStringDataMinimalistic("description", "", videoManager.getDescription(video), -1, -1, formLayout, getWindowControl());
+		updateDescriptionField();
+		uifactory.addFormSubmitButton("submit", formLayout);
+	}
+
+	private void updateDescriptionField(){
+		switch(description.getSelected()){
+		case 2:
+			descriptionField.setVisible(false);
+			break;
+		case 1:
+			descriptionField.setVisible(true);
+			descriptionField.setValue(videoManager.getDescription(video));
+			descriptionField.setEnabled(false);
+			break;
+		case 0:
+			descriptionField.setVisible(true);
+			descriptionField.setValue(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT, ""));
+			descriptionField.setEnabled(true);
+			break;
+		}
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(source == description){
+			updateDescriptionField();
+		}
+	}
+	@Override
+	protected void doDispose() {
+		//
+	}
+}
diff --git a/src/main/java/org/olat/course/nodes/video/VideoPeekviewController.java b/src/main/java/org/olat/course/nodes/video/VideoPeekviewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..baacc298b7b00e4743a05df4710baf564533dade
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/VideoPeekviewController.java
@@ -0,0 +1,33 @@
+package org.olat.course.nodes.video;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.modules.video.managers.MediaMapper;
+
+public class VideoPeekviewController  extends BasicController implements Controller{
+
+	public VideoPeekviewController(UserRequest ureq, WindowControl wControl,  VFSContainer posterFolder) {
+		super(ureq, wControl);
+		VelocityContainer peekviewVC = createVelocityContainer("peekview");
+		String mediaUrl = registerMapper(ureq, new MediaMapper(posterFolder));
+		peekviewVC.contextPut("mediaUrl", mediaUrl);
+		peekviewVC.contextPut("nodeLink", posterFolder);
+		putInitialPanel(peekviewVC);
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+	}
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/video/VideoRunController.java b/src/main/java/org/olat/course/nodes/video/VideoRunController.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc65bb9d790b50f63bbd769b9a549f7244336067
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/VideoRunController.java
@@ -0,0 +1,150 @@
+package org.olat.course.nodes.video;
+
+import java.io.File;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.panel.Panel;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.context.BusinessControl;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.logging.AssertException;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+import org.olat.course.nodes.TitledWrapperHelper;
+import org.olat.course.nodes.VideoCourseNode;
+import org.olat.course.nodes.cp.CPRunController;
+import org.olat.course.run.navigation.NodeRunConstructionResult;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.video.ui.VideoDisplayController;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
+import org.olat.util.logging.activity.LoggingResourceable;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class VideoRunController extends BasicController {
+	private static final OLog log = Tracing.createLoggerFor(CPRunController.class);
+
+	private ModuleConfiguration config;
+	private File videoRoot;
+	private Panel main;
+	
+	private VideoDisplayController videoDispCtr;
+	private VideoCourseNode videoNode;
+	
+
+	@Autowired
+	private RepositoryManager repositoryManager;
+	
+	/**
+	 * Constructor for single page run controller 
+	 * @param wControl
+	 * @param ureq
+	 * @param userCourseEnv
+	 * @param videoNode
+	 */
+	public VideoRunController(ModuleConfiguration config, WindowControl wControl, UserRequest ureq, VideoCourseNode videoNode) {
+		super(ureq,wControl);
+		
+		// assertion to make sure the moduleconfig is valid
+		if (!VideoEditController.isModuleConfigValid(config)) throw new AssertException("videorun controller had an invalid module config:"	+ config.toString());
+		this.config = config;
+		this.videoNode = videoNode;
+		addLoggingResourceable(LoggingResourceable.wrap(videoNode));
+
+		// jump to either the forum or the folder if the business-launch-path says so.
+		BusinessControl bc = getWindowControl().getBusinessControl();
+		ContextEntry ce = bc.popLauncherContextEntry();
+		if ( ce != null ) { // a context path is left for me
+			if(log.isDebug()) log.debug("businesscontrol (for further jumps) would be:"+bc);
+			OLATResourceable popOres = ce.getOLATResourceable();
+			if(log.isDebug()) log.debug("OLATResourceable=" + popOres);
+			String typeName = popOres.getResourceableTypeName();
+			// typeName format: 'path=/test1/test2/readme.txt'
+			// First remove prefix 'path='
+			String path = typeName.substring("path=".length());
+			if  (path.length() > 0) {
+			  if(log.isDebug()) log.debug("direct navigation to container-path=" + path);
+//			  this.nodecmd = path;
+			}
+		}
+		
+		
+		main = new Panel("videorunmain");
+		doLaunch(ureq);
+		putInitialPanel(main);
+	}
+	
+	/**
+	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
+	 */
+	public void event(UserRequest ureq, Component source, Event event) {
+		
+	}
+	
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(source == videoDispCtr){
+			if(VideoDisplayController.ENDED_EVENT.equals(event)){
+				//TODO: catch even fired when video ended
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
+	 */
+	@Override
+	protected void doDispose() {
+		if (videoDispCtr != null) {
+			videoDispCtr.dispose();
+			videoDispCtr = null;
+		}	
+	}
+	
+	private void doLaunch(UserRequest ureq){
+		VelocityContainer myContent = createVelocityContainer("run");
+		if (videoRoot == null) {
+			RepositoryEntry re = VideoEditController.getVideoReference(config, false);
+			if (re == null) {
+				showError(VideoEditController.NLS_ERROR_VIDEOREPOENTRYMISSING);
+				return;
+			}
+
+
+		}
+		switch(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT,"none")){
+		case "resourceDescription":
+				videoDispCtr = new VideoDisplayController(ureq, getWindowControl(), videoNode.getReferencedRepositoryEntry(), config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY), config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS), config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING), videoNode.getIdent(), false, "");
+				break;
+		case "customDescription":
+				videoDispCtr = new VideoDisplayController(ureq, getWindowControl(), videoNode.getReferencedRepositoryEntry(), config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY), config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS), config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING), videoNode.getIdent(), true, config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT));
+				break;
+		case "none":
+				videoDispCtr = new VideoDisplayController(ureq, getWindowControl(), videoNode.getReferencedRepositoryEntry(), config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY), config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS), config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING), videoNode.getIdent(), true, "");
+				break;
+		}
+		
+		videoDispCtr.addControllerListener(this);
+		
+		myContent.put("videoDisplay", videoDispCtr.getInitialComponent());
+		main.setContent(myContent);
+	}
+	
+
+	
+	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq) {
+		NodeRunConstructionResult ncr;
+
+			Controller ctrl = TitledWrapperHelper.getWrapper(ureq, getWindowControl(), this, videoNode, "o_cp_icon");
+			ncr = new NodeRunConstructionResult(ctrl);
+		
+		return ncr;
+	}
+}
diff --git a/src/main/java/org/olat/course/nodes/video/_content/edit.html b/src/main/java/org/olat/course/nodes/video/_content/edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..94297ce07a987e6fd966d1fb0570f40f906bf312
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/_content/edit.html
@@ -0,0 +1,30 @@
+<fieldset class="o_form form-horizontal clearfix">
+	<legend>
+	$r.translate("header")</legend>
+
+	#if ($showPreviewButton)
+		<div class="form-group">
+			<label class="control-label col-sm-3">$r.translate("chosenvideo")</label>
+			<div class="col-sm-9"><p class="form-control-static">$r.render("command.preview")</p></div>
+		</div>
+		<div class="form-group">
+			<div class="col-sm-offset-3 col-sm-9">
+			$r.render("command.changevideo")
+			</div>
+		</div>
+	#else
+		<div class="form-group">
+			<label class="control-label col-sm-3">$r.translate("chosenvideo")</label>
+			<div class="col-sm-9"><p class="form-control-static">$chosenvideo</p></div>
+		</div>
+		<div class="form-group">
+			<div class="col-sm-offset-3 col-sm-9">$r.render("command.createvideo")</div>
+		</div>
+	#end
+
+	#if ($showOptions)
+		<legend>$r.translate("optionsSection")</legend>
+		$r.render("videoOptions")
+	#end
+</fieldset>
+
diff --git a/src/main/java/org/olat/course/nodes/video/_content/peekview.html b/src/main/java/org/olat/course/nodes/video/_content/peekview.html
new file mode 100644
index 0000000000000000000000000000000000000000..cdb432b9a8bef517600ec117cc68b9c6685f8d7d
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/_content/peekview.html
@@ -0,0 +1,2 @@
+
+	<img src="$mediaUrl/poster.jpg" alt="poster" />
diff --git a/src/main/java/org/olat/course/nodes/video/_content/run.html b/src/main/java/org/olat/course/nodes/video/_content/run.html
new file mode 100644
index 0000000000000000000000000000000000000000..71113c0931420ecf2bcabbee185d5218c78ee791
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/_content/run.html
@@ -0,0 +1 @@
+$r.render("videoDisplay")
diff --git a/src/main/java/org/olat/course/nodes/video/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/video/_i18n/LocalStrings_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..3b81d60bf0d8cc32358091890e2f5264b658b937
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/_i18n/LocalStrings_de.properties
@@ -0,0 +1,19 @@
+chosenvideo=ausgewählte Videoresource
+command.changevideo=Videoresource ersetzten
+command.choosevideo=Videoresource auswählen
+command.closevideo=Fenster schliessen
+command.createvideo=Videoressource auswählen oder importieren
+title_video=Video
+condition.accessibility.title=Zugang
+header=Video auswählen
+optionsSection=Optionen
+no.video.chosen=Kein Video ausgew\u00E4hlt
+preview.video=Vorschau
+title_cvideo=Videoressource
+pane.tab.accessibility=Zugang
+pane.tab.videoconfig=Video
+pane.tab.deliveryOptions=$org.olat.core.gui.control.generic.iframe\:option.delivery
+video.config.comments=Video Kommentare
+video.config.rating=Video Bewertung
+video.config.autoplay=Video automatisch wiedergeben
+video.config.description=Beschreibung
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/video/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/video/_i18n/LocalStrings_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cf46a52933aa2dfa758c09e40f3445e6c1f12cd1
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/video/_i18n/LocalStrings_en.properties
@@ -0,0 +1,19 @@
+chosenvideo=Selected Videoressource
+command.changevideo=Replace Videoressource
+command.choosevideo=Choose Videoressource
+command.closevideo=Close window
+command.createvideo=Select or import Videoressource
+title_video=Video
+condition.accessibility.title=Access
+header=Select Video
+optionsSection=Options
+no.video.chosen=No Videoressource selected
+preview.video=Preview
+title_cvideo=Videoressource
+pane.tab.accessibility=Zugang
+pane.tab.videoconfig=Video
+pane.tab.deliveryOptions=$org.olat.core.gui.control.generic.iframe\:option.delivery
+video.config.comments=Video comments
+video.config.rating=Video rating
+video.config.autoplay=Video autoplay
+video.config.description=Description
\ No newline at end of file
diff --git a/src/main/java/org/olat/fileresource/types/MovieFileResource.java b/src/main/java/org/olat/fileresource/types/MovieFileResource.java
index 1b106df5189171ed32e949bb0d5522474501b46a..3f6e7d779eb5eedd317e3d18693a8955e6a63cbb 100644
--- a/src/main/java/org/olat/fileresource/types/MovieFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/MovieFileResource.java
@@ -56,7 +56,6 @@ public class MovieFileResource extends FileResource {
 		return f.endsWith(".avi") || f.endsWith(".mpeg") ||
 				f.endsWith(".mpg") || f.endsWith(".qt") ||
 				f.endsWith(".rm") || f.endsWith(".ram") ||
-				f.endsWith(".mp4") || f.endsWith(".m4v") ||
-				f.endsWith(".mov");
+				f.endsWith(".m4v");
 	}
 }
diff --git a/src/main/java/org/olat/fileresource/types/VideoFileResource.java b/src/main/java/org/olat/fileresource/types/VideoFileResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b932116944b639318db6a6c8e27790618b90a22
--- /dev/null
+++ b/src/main/java/org/olat/fileresource/types/VideoFileResource.java
@@ -0,0 +1,64 @@
+/**
+* OLAT - Online Learning and Training<br>
+* http://www.olat.org
+* <p>
+* Licensed under the Apache License, Version 2.0 (the "License"); <br>
+* you may not use this file except in compliance with the License.<br>
+* You may obtain a copy of the License at
+* <p>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p>
+* Unless required by applicable law or agreed to in writing,<br>
+* software distributed under the License is distributed on an "AS IS" BASIS, <br>
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+* See the License for the specific language governing permissions and <br>
+* limitations under the License.
+* <p>
+* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
+* University of Zurich, Switzerland.
+* <hr>
+* <a href="http://www.openolat.org">
+* OpenOLAT - Online Learning and Training</a><br>
+* This file has been modified by the OpenOLAT community. Changes are licensed
+* under the Apache 2.0 license as the original file.
+*/
+
+package org.olat.fileresource.types;
+
+import java.io.File;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.modules.video.VideoModule;
+
+/**
+ * Initial Date:  Mar 27, 2015
+ *
+ * @author Dirk Furrer
+ */
+public class VideoFileResource extends FileResource {
+
+
+	private static VideoModule videomodule = CoreSpringFactory.getImpl(VideoModule.class);
+
+	/**
+	 * Movie file resource dientifier.
+	 */
+	public static final String TYPE_NAME = "FileResource.VIDEO";
+
+	public VideoFileResource() {
+		super(TYPE_NAME);
+	}
+
+	/**
+	 * @param f file to validate
+	 * @return True if is of type.
+	 */
+	public static boolean validate(File f) {
+		return validate(f.getName());
+	}
+
+	public static boolean validate(String filename) {
+		String f = filename.toLowerCase();
+		return videomodule.isEnabled() && (f.endsWith(".mp4")|| f.endsWith(".mov"));
+	}
+}
diff --git a/src/main/java/org/olat/modules/_spring/modulesContext.xml b/src/main/java/org/olat/modules/_spring/modulesContext.xml
index ae070c234f3088a3ed64d5792b3e9d6e5f05e842..09b396dc179c35f017023819add302e43a6ef4a8 100644
--- a/src/main/java/org/olat/modules/_spring/modulesContext.xml
+++ b/src/main/java/org/olat/modules/_spring/modulesContext.xml
@@ -18,6 +18,7 @@
 	<import resource="classpath:/org/olat/modules/webFeed/_spring/webFeedContext.xml"/>
 	<import resource="classpath:/org/olat/modules/wiki/_spring/wikiContext.xml"/>
 	<import resource="classpath:/org/olat/modules/reminder/_spring/reminderContext.xml"/>
+	<import resource="classpath:/org/olat/modules/video/_spring/videoContext.xml"/>
 	
 	
 	
diff --git a/src/main/java/org/olat/modules/video/VideoModule.java b/src/main/java/org/olat/modules/video/VideoModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..15095212ae984d9fa49bbdd9db7edb9d7a8211ed
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/VideoModule.java
@@ -0,0 +1,107 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.video;
+
+import org.olat.core.configuration.AbstractSpringModule;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.coordinate.CoordinatorManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * Initial date: 23.2.2016<br>
+ * @author dfakae, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class VideoModule extends AbstractSpringModule {
+
+	private static final String VIDEO_ENABLED = "video.enabled";
+	private static final String VIDEOCOURSENODE_ENABLED = "video.coursenode.enabled";
+	private static final String VIDEOTRANSCODING_ENABLED = "video.transcoding.enabled";
+
+	@Value("${video.enabled:true}")
+	private boolean enabled;
+	@Value("${video.coursenode.enabled:true}")
+	private boolean coursenodeEnabled;
+	@Value("${video.transcoding.enabled:false}")
+	private boolean transcodingEnabled;
+
+
+	@Autowired
+	public VideoModule(CoordinatorManager coordinatorManager) {
+		super(coordinatorManager);
+	}
+
+	@Override
+	public void init() {
+		String enabledObj = getStringPropertyValue(VIDEO_ENABLED, true);
+		if(StringHelper.containsNonWhitespace(enabledObj)) {
+			enabled = "true".equals(enabledObj);
+		}
+
+		String enabledCoursenodeObj = getStringPropertyValue(VIDEOCOURSENODE_ENABLED, true);
+		if(StringHelper.containsNonWhitespace(enabledCoursenodeObj)) {
+			coursenodeEnabled = "true".equals(enabledCoursenodeObj);
+		}
+
+		String enabledTranscodingObj = getStringPropertyValue(VIDEOTRANSCODING_ENABLED, true);
+		if(StringHelper.containsNonWhitespace(enabledTranscodingObj)) {
+			transcodingEnabled = "true".equals(enabledTranscodingObj);
+		}
+
+	}
+	@Override
+	protected void initFromChangedProperties() {
+		init();
+	}
+
+	public boolean isEnabled() {
+		return enabled;
+	}
+
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+		setStringProperty(VIDEO_ENABLED, Boolean.toString(enabled), true);
+	}
+
+
+	public boolean isCoursenodeEnabled() {
+		return (coursenodeEnabled && enabled);
+
+	}
+
+
+	public void setCoursenodeEnabled(boolean coursenodeEnabled) {
+		this.coursenodeEnabled = coursenodeEnabled;
+		setStringProperty(VIDEOCOURSENODE_ENABLED, Boolean.toString(this.coursenodeEnabled), true);
+	}
+
+
+	public boolean isTranscodingEnabled() {
+		return (transcodingEnabled && enabled);
+	}
+
+	public void setTranscodingEnabled(boolean transcodingEnabled) {
+		this.transcodingEnabled = transcodingEnabled;
+		setStringProperty(VIDEOTRANSCODING_ENABLED, Boolean.toString(transcodingEnabled), true);
+	}
+}
diff --git a/src/main/java/org/olat/modules/video/_spring/videoContext.xml b/src/main/java/org/olat/modules/video/_spring/videoContext.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea8badeec0336981595ec61c1320c7f4e7c6f7bd
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/_spring/videoContext.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+  http://www.springframework.org/schema/beans
+  http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+<bean id="videoManager" class="org.olat.modules.video.managers.VideoManagerImpl">
+</bean>
+
+<bean id="transcodingService" class="org.olat.modules.video.service.TranscoderService">
+</bean>
+
+
+<bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints">
+		<property name="order" value="7210" />
+		<property name="actionController">
+			<bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype">
+				<property name="className" value="org.olat.modules.video.ui.VideoAdminController"/>
+			</bean>
+		</property>
+		<property name="navigationKey" value="video" />
+		<property name="parentTreeNodeIdentifier" value="modulesParent" />
+		<property name="i18nActionKey" value="admin.menu.title"/>
+		<property name="i18nDescriptionKey" value="admin.menu.video.alt"/>
+		<property name="translationPackage" value="org.olat.modules.video.ui"/>
+		<property name="extensionPoints">
+			<list>
+				<value>org.olat.admin.SystemAdminMainController</value>
+			</list>
+		</property>
+	</bean>
+
+</beans>
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/managers/MediaMapper.java b/src/main/java/org/olat/modules/video/managers/MediaMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..aeb285412fd86b57c4728e518251018573f28f15
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/managers/MediaMapper.java
@@ -0,0 +1,30 @@
+package org.olat.modules.video.managers;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.olat.core.dispatcher.mapper.Mapper;
+import org.olat.core.gui.media.MediaResource;
+import org.olat.core.gui.media.NotFoundMediaResource;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSItem;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.core.util.vfs.VFSMediaResource;
+
+public class MediaMapper implements Mapper {
+	
+	private final VFSContainer mediaBase;
+	
+	public MediaMapper(VFSContainer mediaBase) {
+		this.mediaBase = mediaBase;
+	}
+
+	@Override
+	public MediaResource handle(String relPath, HttpServletRequest request) {
+		VFSItem mediaFile = mediaBase.resolve(relPath);
+		if (mediaFile instanceof VFSLeaf){
+			return new VFSMediaResource((VFSLeaf)mediaFile);
+		} else {
+ 			return new NotFoundMediaResource(relPath);
+		}
+	}
+}
diff --git a/src/main/java/org/olat/modules/video/managers/VideoManager.java b/src/main/java/org/olat/modules/video/managers/VideoManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..a19f47d8fea7c994d512c8354f7d0f27a61577e7
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/managers/VideoManager.java
@@ -0,0 +1,80 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.video.managers;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.manager.BasicManager;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.resource.OLATResource;
+
+/**
+ * The <code>VideoManager</code> singleton is responsible for dealing with video
+ * resources.
+ *
+ * Initial date: 01.04.2015<br>
+ * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
+ */
+public abstract class VideoManager extends BasicManager {
+
+	protected static VideoManager INSTANCE;
+
+	public abstract File getVideoFile(OLATResource video);
+
+	public abstract Size getVideoSize(OLATResource video);
+
+	public abstract void setVideoSize(OLATResource video, Size size);
+
+	public abstract VFSLeaf getPosterframe(OLATResource video);
+
+	public abstract void setPosterframe(OLATResource video, VFSLeaf posterframe);
+
+	public abstract void setTitle(OLATResource video, String title);
+
+	public abstract String getTitle(OLATResource video);
+
+	public abstract HashMap<String, VFSLeaf> getAllTracks(OLATResource video);
+
+	public abstract void addTrack(OLATResource video, String lang, VFSLeaf trackFile);
+
+	public abstract VFSLeaf getTrack(OLATResource video, String lang);
+
+	public abstract void removeTrack(OLATResource video, String lang);
+
+	public abstract void setCommentsEnabled(OLATResource video, boolean isEnabled);
+
+	public abstract boolean getCommentsEnabled(OLATResource video);
+
+	public abstract void setRatingEnabled(OLATResource video, boolean isEnabled);
+
+	public abstract boolean getRatingEnabled(OLATResource video);
+
+	public abstract boolean getFrame(OLATResource video, int frameNumber, VFSLeaf frame) throws IOException;
+
+	public abstract void setDescription(OLATResource video, String text);
+
+	public abstract String getDescription(OLATResource video);
+
+	public abstract boolean optimizeVideoRessource(OLATResource video);
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/managers/VideoManagerImpl.java b/src/main/java/org/olat/modules/video/managers/VideoManagerImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b1c6481f58b5833ac9ce6d5b370529f4c2216ff
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/managers/VideoManagerImpl.java
@@ -0,0 +1,256 @@
+package org.olat.modules.video.managers;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import javax.imageio.ImageIO;
+
+import org.jcodec.api.FrameGrab;
+import org.jcodec.common.FileChannelWrapper;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.util.vfs.VFSItem;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.core.util.vfs.VFSManager;
+import org.olat.core.util.xml.XStreamHelper;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.modules.video.models.VideoMetadata;
+import org.olat.resource.OLATResource;
+import org.springframework.stereotype.Service;
+
+@Service("videoManager")
+public class VideoManagerImpl extends VideoManager {
+	private FileResourceManager fileResourceManager = FileResourceManager.getInstance();
+	private RandomAccessFile randomAccessFile;
+
+	public VideoManagerImpl() {
+		INSTANCE = this;
+	}
+
+	@Override
+	public Size getVideoSize(OLATResource video) {
+		return readVideoMetadataFile(video).getSize();
+	}
+
+	@Override
+	public void setVideoSize(OLATResource video, Size size){
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		metaData.setSize(size);
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public VFSLeaf getPosterframe(OLATResource video) {
+		String posterframePath = readVideoMetadataFile(video).getPosterframe();
+		VFSLeaf posterFrame = resolve(video,posterframePath);
+		return posterFrame;
+	}
+
+	@Override
+	public void setPosterframe(OLATResource video, VFSLeaf posterframe){
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		String oldPath = metaData.getPosterframe();
+		if(oldPath != null){
+			VFSLeaf oldPoster = resolve(video, metaData.getPosterframe());
+			if(oldPoster != null){
+				oldPoster.delete();
+			}
+		}
+
+		VFSLeaf newPoster = VFSManager.resolveOrCreateLeafFromPath(fileResourceManager.getFileResourceMedia(video), "/poster.jpg");
+
+		if(!newPoster.isSame(posterframe)){
+		VFSManager.copyContent(posterframe, newPoster);
+		}
+		metaData.setPosterframe(newPoster.getName());
+		writeVideoMetadataFile(metaData, video);
+
+	}
+
+	@Override
+	public void setTitle(OLATResource video, String title){
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		metaData.setTitle(title);
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public String getTitle(OLATResource video) {
+		return readVideoMetadataFile(video).getTitle();
+	}
+
+	@Override
+	public void addTrack(OLATResource video, String lang, VFSLeaf trackFile){
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		metaData.addTrack(lang, trackFile.getName());
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public HashMap<String, VFSLeaf> getAllTracks(OLATResource video) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		HashMap<String, VFSLeaf> tracks = new HashMap<String, VFSLeaf>();
+		for(Entry<String, String> trackEntry : metaData.getAllTracks().entrySet()){
+			tracks.put(trackEntry.getKey(), resolve(video, trackEntry.getValue()));
+		}
+		return tracks;
+	}
+
+	@Override
+	public VFSLeaf getTrack(OLATResource video, String lang) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		return resolve(video, metaData.getTrack(lang));
+	}
+
+	@Override
+	public void removeTrack(OLATResource video, String lang){
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		resolve(video, metaData.getTrack(lang)).delete();
+		metaData.removeTrack(lang);
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public void setCommentsEnabled(OLATResource video, boolean isEnabled) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		metaData.setCommentsEnabled(isEnabled);
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public boolean getCommentsEnabled(OLATResource video) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		return metaData.getCommentsEnabled();
+	}
+
+	@Override
+	public void setRatingEnabled(OLATResource video, boolean isEnabled) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		metaData.setRatingEnabled(isEnabled);
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public boolean getRatingEnabled(OLATResource video) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		return metaData.getRatingEnabled();
+	}
+
+	@Override
+	public boolean getFrame(OLATResource video, int frameNumber, VFSLeaf frame) throws IOException{
+		File rootFolder = fileResourceManager.getFileResourceRoot(video);
+		File metaDataFile = new File(rootFolder, "media");
+		File videoFile = new File(metaDataFile, "video.mp4");
+
+		randomAccessFile = new RandomAccessFile(videoFile, "r");
+		FileChannel ch = randomAccessFile.getChannel();
+		FileChannelWrapper in = new FileChannelWrapper(ch);
+		try{
+			FrameGrab frameGrab = new FrameGrab(in).seekToFrameSloppy(frameNumber);
+			OutputStream frameOutputStream = frame.getOutputStream(true);
+
+			BufferedImage bufImg = frameGrab.getFrame();
+			ImageIO.write(bufImg, "JPG", frameOutputStream);
+
+			return true;
+		}catch(	Exception e){
+			return false;
+		}
+		//TODO: throw right exception
+	}
+
+	@Override
+	public void setDescription(OLATResource video, String text) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		metaData.setDescription(text);
+		writeVideoMetadataFile(metaData, video);
+	}
+
+	@Override
+	public String getDescription(OLATResource video) {
+		VideoMetadata metaData = readVideoMetadataFile(video);
+		return metaData.getDescription();
+	}
+
+	@Override
+	public File getVideoFile(OLATResource video) {
+		File rootFolder = fileResourceManager.getFileResourceRoot(video);
+		File metaDataFile = new File(rootFolder, "media");
+		File videoFile = new File(metaDataFile, "video.mp4");
+		return videoFile;
+	}
+
+
+	private VFSLeaf resolve(OLATResource video, String path){
+		VFSItem item = VFSManager.resolveFile(fileResourceManager.getFileResourceMedia(video), path);
+		if(item instanceof VFSLeaf){
+			return (VFSLeaf) item;
+		}else{
+			return null;
+		}
+	}
+
+	private void writeVideoMetadataFile(VideoMetadata metaData, OLATResource video){
+		File videoResourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(video).getBasefile();
+		File metaDataFile = new File(videoResourceFileroot,"video_metadata.xml");
+		XStreamHelper.writeObject(XStreamHelper.createXStreamInstance(), metaDataFile, metaData);
+	}
+
+	private VideoMetadata readVideoMetadataFile(OLATResource video){
+		File videoResourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(video).getBasefile();
+		File metaDataFile = new File(videoResourceFileroot, "video_metadata.xml");
+		return (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
+	}
+
+	@Override
+	public boolean optimizeVideoRessource(OLATResource video) {
+		File file = getVideoFile(video);
+		File videoResourceFileroot = fileResourceManager.getFileResourceRoot(video);
+		File optimizedFolder = new File(videoResourceFileroot, "optimizedVideoData");
+		optimizedFolder.mkdirs();
+
+		ArrayList<String> cmd = new ArrayList<String>();
+
+		cmd.add("HandBrakeCLI");
+		cmd.add("-i "+file.getAbsolutePath());
+		cmd.add("-o "+optimizedFolder.getAbsolutePath()+"/optimized_"+file.getName());
+		cmd.add("--optimize");
+		cmd.add("--preset Normal");
+
+		ProcessBuilder pb = new ProcessBuilder(cmd);
+		pb.directory(optimizedFolder);
+
+		pb.redirectErrorStream(true);
+		pb.inheritIO();
+
+
+		 try {
+				logInfo("+--------------------------HANDBRAKE STARTS TRANSCODING------------------------------------+");
+	            Runtime.getRuntime().exec("HandBrakeCLI "+" -i "+file.getAbsolutePath()+" -o "+optimizedFolder.getAbsolutePath()+"/optimized_"+file.getName()+" --optimize"+" --preset Normal");
+				logInfo("+---------------------------HANDBRAKE TRANSCODING DONE-------------------------------------+");
+				return true;
+		 } catch (Exception e) {
+	            System.err.println("Unable to do videotranscoding");
+				return false;
+	     }
+
+		 
+//		try {
+//			logInfo("+--------------------------HANDBRAKE STARTS TRANSCODING------------------------------------+");
+//			Process process = pb.start();
+//			process.waitFor();
+//			logInfo("+---------------------------HANDBRAKE TRANSCODING DONE-------------------------------------+");
+//			return true;
+//		} catch (Exception e) {
+//			return false;
+//		}
+
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/models/VideoMetadata.java b/src/main/java/org/olat/modules/video/models/VideoMetadata.java
new file mode 100644
index 0000000000000000000000000000000000000000..adff9b9123be37779c0ca89bc35e4b7224b00dc3
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/models/VideoMetadata.java
@@ -0,0 +1,131 @@
+/**
+* OLAT - Online Learning and Training<br>
+* http://www.olat.org
+* <p>
+* Licensed under the Apache License, Version 2.0 (the "License"); <br>
+* you may not use this file except in compliance with the License.<br>
+* You may obtain a copy of the License at
+* <p>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p>
+* Unless required by applicable law or agreed to in writing,<br>
+* software distributed under the License is distributed on an "AS IS" BASIS, <br>
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+* See the License for the specific language governing permissions and <br>
+* limitations under the License.
+* <p>
+* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
+* University of Zurich, Switzerland.
+* <hr>
+* <a href="http://www.openolat.org">
+* OpenOLAT - Online Learning and Training</a><br>
+* This file has been modified by the OpenOLAT community. Changes are licensed
+* under the Apache 2.0 license as the original file.
+*/
+
+package org.olat.modules.video.models;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.id.OLATResourceable;
+
+/**
+ * Initial Date:  Apr 9, 2015
+ *
+ * @author Dirk Furrer
+ * 
+ */
+
+public class VideoMetadata implements Serializable{
+		/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+		// Data model versioning
+		public static final int CURRENT_MODEL_VERSION = 1;
+	
+		// Properties
+		private String title;
+
+		private Size size;
+		private String posterframe;
+		private HashMap<String, String> tracks;
+		private boolean commentsEnabled;
+		private boolean ratingEnabled;
+		private String description;
+		
+		private int modelVersion = 0; 
+				
+		public VideoMetadata(OLATResourceable resource){
+			this.tracks = new HashMap<String, String>();
+			// new model constructor, set to current version
+			this.modelVersion = CURRENT_MODEL_VERSION;
+		}
+				
+		public Size getSize() {
+			return size;
+		}
+
+		public void setSize(Size size) {
+			this.size = size;
+		}
+
+		public String getTitle() {
+			return title;
+		}
+
+		public void setTitle(String title) {
+			this.title = title;
+		}
+
+		public String getPosterframe() {
+			return posterframe;
+		}
+
+		public void setPosterframe(String posterframe) {
+			this.posterframe = posterframe;
+		}
+
+		public HashMap<String, String> getAllTracks(){
+			return tracks;
+		}
+		
+		public void addTrack(String lang, String trackFile){
+			tracks.put(lang, trackFile);
+		}
+		
+		public String getTrack(String lang){
+			return tracks.get(lang);
+		}
+		
+		public void removeTrack(String lang){
+			tracks.remove(lang);
+		}
+		
+		public void setCommentsEnabled(boolean isEnabled){
+			this.commentsEnabled = isEnabled;
+		}
+		
+		public boolean getCommentsEnabled(){
+			return this.commentsEnabled;
+		}
+		
+		public void setRatingEnabled(boolean isEnabled){
+			this.ratingEnabled = isEnabled;
+		}
+		
+		public boolean getRatingEnabled(){
+			return this.ratingEnabled;
+		}
+		
+		public void setDescription(String text){
+			this.description = text;
+		}
+		
+		public String getDescription(){
+			return this.description;
+		}
+}
diff --git a/src/main/java/org/olat/modules/video/models/VideoQualityTableModel.java b/src/main/java/org/olat/modules/video/models/VideoQualityTableModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..e112724b6a713ed0fdd98ddc274fdda73da2de71
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/models/VideoQualityTableModel.java
@@ -0,0 +1,83 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+
+package org.olat.modules.video.models;
+
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.translator.Translator;
+import org.olat.modules.video.ui.QualityTableRow;
+
+/**
+ *
+ * Initial date: 01.04.2015<br>
+ * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+public class VideoQualityTableModel extends DefaultFlexiTableDataModel<QualityTableRow>{
+
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+	private Translator translator;
+	public VideoQualityTableModel(FlexiTableColumnModel columnModel, Translator translator) {
+		super(columnModel);
+		this.translator = translator;
+	}
+
+	@Override
+	public VideoQualityTableModel createCopyWithEmptyList() {
+		return new VideoQualityTableModel(getTableColumnModel(), translator);
+	}
+
+
+	@Override
+	public Object getValueAt(int row, int col) {
+		QualityTableRow video = getObject(row);
+		switch(QualityTableCols.values()[col]) {
+			case type: return video.getType();
+			case dimension: return video.getDimension();
+			case size: return video.getSize();
+			case format: return video.getFormat();
+			case view: return video.getViewLink();
+			default: return "";
+		}
+	}
+
+
+
+	public enum QualityTableCols {
+		type("quality.table.header.type"),
+		dimension("quality.table.header.dimension"),
+		size("quality.table.header.size"),
+		format("quality.table.header.format"),
+		view("quality.table.header.view");
+
+		private final String i18nKey;
+
+		private QualityTableCols(String i18nKey) {
+			this.i18nKey = i18nKey;
+		}
+
+		public String i18nKey() {
+			return i18nKey;
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/models/VideoTracksTableModel.java b/src/main/java/org/olat/modules/video/models/VideoTracksTableModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..28b058cce30a91e5953a4c6f4121559c0c70f8a7
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/models/VideoTracksTableModel.java
@@ -0,0 +1,81 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+
+package org.olat.modules.video.models;
+
+import java.util.Locale;
+
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.translator.Translator;
+import org.olat.modules.video.ui.TrackTableRow;
+
+/**
+ *
+ * Initial date: 01.04.2015<br>
+ * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+public class VideoTracksTableModel extends DefaultFlexiTableDataModel<TrackTableRow>{
+
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+	private Translator translator;
+	public VideoTracksTableModel(FlexiTableColumnModel columnModel, Translator translator) {
+		super(columnModel);
+		this.translator = translator;
+	}
+
+	@Override
+	public VideoTracksTableModel createCopyWithEmptyList() {
+		return new VideoTracksTableModel(getTableColumnModel(), translator);
+	}
+
+
+	@Override
+	public Object getValueAt(int row, int col) {
+		TrackTableRow track = getObject(row);
+		switch(TrackTableCols.values()[col]) {
+			case file: return track.getTrack();
+			case language: return new Locale(track.getLanguage()).getDisplayLanguage(this.translator.getLocale());
+			case delete: return track.getDeleteLink();
+			default: return "";
+		}
+	}
+
+
+
+	public enum TrackTableCols {
+		file("track.table.header.file"),
+		language("track.table.header.language"),
+		delete("track.table.header.delete");
+
+		private final String i18nKey;
+
+		private TrackTableCols(String i18nKey) {
+			this.i18nKey = i18nKey;
+		}
+
+		public String i18nKey() {
+			return i18nKey;
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/service/HandbrakeTranscoder.java b/src/main/java/org/olat/modules/video/service/HandbrakeTranscoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6a3d94692be7cca88bde17e0353adcf78b3faca
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/service/HandbrakeTranscoder.java
@@ -0,0 +1,70 @@
+package org.olat.modules.video.service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.resource.OLATResource;
+
+public class HandbrakeTranscoder implements Transcoder {
+	private OLog logger = Tracing.createLoggerFor(this.getClass());
+	private VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
+	private FileResourceManager fileResourceManager = FileResourceManager.getInstance();
+
+	@Override
+	public boolean transcodeVideoRessource(OLATResource video, Map<String, String> params){
+		File file = videoManager.getVideoFile(video);
+		File videoResourceFileroot = fileResourceManager.getFileResourceRoot(video);
+		File optimizedFolder = new File(videoResourceFileroot, "optimizedVideoData");
+		optimizedFolder.mkdirs();
+
+		ArrayList<String> cmd = new ArrayList<String>();
+
+		cmd.add("HandBrakeCLI");
+		cmd.add("-i "+file.getAbsolutePath());
+		cmd.add("-o "+optimizedFolder.getAbsolutePath()+"/optimized_"+file.getName());
+		cmd.add("--optimize");
+		cmd.add("--preset Normal");
+
+		ProcessBuilder pb = new ProcessBuilder(cmd);
+		pb.directory(optimizedFolder);
+
+		pb.redirectErrorStream(true);
+		pb.inheritIO();
+
+
+		 try {
+				logger.info("+--------------------------HANDBRAKE STARTS TRANSCODING------------------------------------+");
+	            Runtime.getRuntime().exec("HandBrakeCLI "+" -i "+file.getAbsolutePath()+" -o "+optimizedFolder.getAbsolutePath()+"/optimized_"+file.getName()+" --optimize"+" --preset Normal");
+				logger.info("+---------------------------HANDBRAKE TRANSCODING DONE-------------------------------------+");
+				return true;
+		 } catch (Exception e) {
+	            System.err.println("Unable to do videotranscoding");
+				return false;
+	     }
+	}
+
+
+	private boolean transcodeVideoRessourceLow(OLATResource video) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+
+	private boolean transcodeVideoRessourceMid(OLATResource video) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+
+	private boolean transcodeVideoRessourceHi(OLATResource video) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/service/Transcoder.java b/src/main/java/org/olat/modules/video/service/Transcoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..5495a140946b395043fec54f6a5ac76ddde09870
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/service/Transcoder.java
@@ -0,0 +1,9 @@
+package org.olat.modules.video.service;
+
+import java.util.Map;
+
+import org.olat.resource.OLATResource;
+
+public interface Transcoder {
+	public boolean transcodeVideoRessource(OLATResource video, Map<String, String> params);
+}
diff --git a/src/main/java/org/olat/modules/video/service/TranscoderService.java b/src/main/java/org/olat/modules/video/service/TranscoderService.java
new file mode 100644
index 0000000000000000000000000000000000000000..3983288c4c7e968d70ab6deb996f9af764ddcc6d
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/service/TranscoderService.java
@@ -0,0 +1,27 @@
+package org.olat.modules.video.service;
+
+import java.util.ServiceLoader;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TranscoderService{
+
+	@Value("${video.transcoding.provider:handbrake}")
+	private static String transcodingProvider;
+
+    private static TranscoderService service;
+    private ServiceLoader<Transcoder> loader;
+
+    private TranscoderService() {
+        loader = ServiceLoader.load(Transcoder.class);
+    }
+
+    public static synchronized TranscoderService getInstance() {
+        if (service == null) {
+            service = new TranscoderService();
+        }
+        return service;
+    }
+}
diff --git a/src/main/java/org/olat/modules/video/ui/QualityTableRow.java b/src/main/java/org/olat/modules/video/ui/QualityTableRow.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7ebd5fa26840d9305ef2c520fec3e12df7085d4
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/QualityTableRow.java
@@ -0,0 +1,90 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.video.ui;
+
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+
+/**
+ *
+ * Initial date: 07.04.2015<br>
+ * @author dfurrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+public class QualityTableRow {
+
+	String type;
+	String dimension;
+	String size;
+	String format;
+	FormLink viewLink;
+
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+
+	public QualityTableRow(String type, String dimension, String size, String format, FormLink viewLink) {
+		this.type = type;
+		this.dimension = dimension;
+		this.size = size;
+		this.format = format;
+		this.viewLink = viewLink;
+		this.viewLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
+
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public String getDimension() {
+		return dimension;
+	}
+
+	public void setDimension(String dimension) {
+		this.dimension = dimension;
+	}
+
+	public String getSize() {
+		return size;
+	}
+
+	public void setSize(String size) {
+		this.size = size;
+	}
+
+	public String getFormat() {
+		return format;
+	}
+
+	public void setFormat(String format) {
+		this.format = format;
+	}
+
+	public FormLink getViewLink() {
+		return viewLink;
+	}
+
+	public void setViewLink(FormLink viewLink) {
+		this.viewLink = viewLink;
+	}
+}
diff --git a/src/main/java/org/olat/modules/video/ui/TrackTableRow.java b/src/main/java/org/olat/modules/video/ui/TrackTableRow.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e82e914a5c06648ae0fd64aa4d2a6551bcfe3a0
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/TrackTableRow.java
@@ -0,0 +1,60 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.video.ui;
+
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.util.vfs.VFSLeaf;
+
+/**
+ *
+ * Initial date: 07.04.2015<br>
+ * @author dfurrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+public class TrackTableRow {
+
+	String language;
+	VFSLeaf track;
+	FormLink deleteLink;
+
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+
+	public TrackTableRow(String language, VFSLeaf track, FormLink deleteLink) {
+		this.language = language;
+		this.track = track;
+		this.deleteLink = deleteLink;
+		this.deleteLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item");
+
+	}
+
+	public VFSLeaf getTrack(){
+		return track;
+	}
+
+	public String getLanguage(){
+		return language;
+	}
+
+	public FormLink getDeleteLink(){
+		return deleteLink;
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/ui/VideoAdminController.java b/src/main/java/org/olat/modules/video/ui/VideoAdminController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9be57daf39841a707568e9d35717af6d36434415
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoAdminController.java
@@ -0,0 +1,77 @@
+package org.olat.modules.video.ui;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.modules.video.VideoModule;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class VideoAdminController extends FormBasicController  {
+
+	private MultipleSelectionElement enableEl;
+	private MultipleSelectionElement enableCourseNodeEl;
+	private MultipleSelectionElement enableTranscodingEl;
+
+	@Autowired
+	private VideoModule videoModule;
+
+	public VideoAdminController(UserRequest ureq, WindowControl wControl) {
+		super(ureq, wControl);
+		initForm(ureq);
+	}
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		setFormTitle("admin.config.title");
+
+		String[] enableKeys = new String[]{ "on" };
+		String[] enableValues = new String[]{ translate("on") };
+
+		enableEl = uifactory.addCheckboxesHorizontal("admin.config.enable", formLayout, enableKeys, enableValues);
+		enableEl.select("on", videoModule.isEnabled());
+		enableEl.addActionListener(FormEvent.ONCHANGE);
+
+		enableCourseNodeEl = uifactory.addCheckboxesHorizontal("admin.config.videoNode", formLayout, enableKeys, enableValues);
+		enableCourseNodeEl.select("on", videoModule.isCoursenodeEnabled());
+		enableCourseNodeEl.setVisible(enableEl.isSelected(0));
+		enableCourseNodeEl.addActionListener(FormEvent.ONCHANGE);
+
+		enableTranscodingEl = uifactory.addCheckboxesHorizontal("admin.config.transcoding", formLayout, enableKeys, enableValues);
+		enableTranscodingEl.select("on", videoModule.isTranscodingEnabled());
+		enableTranscodingEl.setVisible(enableEl.isSelected(0));
+		enableTranscodingEl.addActionListener(FormEvent.ONCHANGE);
+
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(source == enableEl){
+			videoModule.setEnabled(enableEl.isSelected(0));
+			enableCourseNodeEl.setVisible(enableEl.isSelected(0));
+			enableTranscodingEl.setVisible(enableEl.isSelected(0));
+			enableCourseNodeEl.select("on", videoModule.isCoursenodeEnabled());
+			enableTranscodingEl.select("on", videoModule.isTranscodingEnabled());
+		}
+		if(source == enableCourseNodeEl){
+			videoModule.setCoursenodeEnabled(enableCourseNodeEl.isSelected(0));
+		}
+		if(source == enableTranscodingEl){
+			videoModule.setTranscodingEnabled(enableTranscodingEl.isSelected(0));
+		}
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
new file mode 100644
index 0000000000000000000000000000000000000000..b58135da6f7537e27fe4e3d691ca6a1a4cbad176
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
@@ -0,0 +1,165 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.video.ui;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.services.commentAndRating.CommentAndRatingDefaultSecurityCallback;
+import org.olat.core.commons.services.commentAndRating.CommentAndRatingSecurityCallback;
+import org.olat.core.commons.services.commentAndRating.ui.UserCommentsAndRatingsController;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.commons.services.video.MovieService;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSComponent;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.gui.render.Renderer;
+import org.olat.core.gui.render.StringOutput;
+import org.olat.core.gui.util.CSSHelper;
+import org.olat.core.util.FileUtils;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSItem;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.modules.video.managers.MediaMapper;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.repository.RepositoryEntry;
+import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ *
+ * Initial date: 01.04.2015<br>
+ * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+public class VideoDisplayController extends BasicController {
+
+	@Autowired
+	private MovieService movieService;
+
+	private UserCommentsAndRatingsController commentsAndRatingCtr;
+	private VelocityContainer mainVC;
+	public static final Event ENDED_EVENT = new Event("videoEnded");
+
+
+	public VideoDisplayController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry) {
+		this(ureq, wControl, entry, false, false, false, null, false, null);
+	}
+
+	public VideoDisplayController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry, Boolean autoplay, Boolean showComments, Boolean showRating, String OresSubPath, boolean customDescription, String descriptionText) {
+		super(ureq, wControl);
+
+		mainVC = createVelocityContainer("video_run");
+		mainVC.contextPut("displayName", entry.getDisplayname());
+		StringOutput sb = new StringOutput(50);
+		Renderer.renderStaticURI(sb, "movie/mediaelementplayer.min.css");
+		String cssPath = sb.toString();
+		JSAndCSSComponent mediaelementjs = new JSAndCSSComponent("mediaelementjs", new String[] { "movie/mediaelement-and-player.min.js" },new String[] {cssPath});
+		mainVC.put("mediaelementjs", mediaelementjs);
+		putInitialPanel(mainVC);
+
+		VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
+
+		VFSLeaf video = getVideo(entry);
+		if(video != null) {
+			String filename = video.getName();
+			mainVC.contextPut("filename", filename);
+			String lowerFilename = filename.toLowerCase();
+			String cssClass = CSSHelper.createFiletypeIconCssClassFor(lowerFilename);
+			mainVC.contextPut("cssClass", cssClass);
+
+			String extension = FileUtils.getFileSuffix(filename);
+			String mediaUrl = registerMapper(ureq, new MediaMapper(video.getParentContainer()));
+			mainVC.contextPut("movie", filename);
+			mainVC.contextPut("mediaUrl", mediaUrl);
+			Size realSize = movieService.getSize(video, extension);
+			if(realSize != null) {
+				mainVC.contextPut("height", realSize.getHeight());
+				mainVC.contextPut("width", realSize.getWidth());
+			} else {
+				mainVC.contextPut("height", 480);
+				mainVC.contextPut("width", 640);
+			}
+
+			HashMap<String, String> trackfiles = new HashMap<String, String>();
+			for(String lang : Locale.getISOLanguages()){
+				VFSLeaf track = videoManager.getTrack(entry.getOlatResource(), lang);
+				if(track != null){
+					trackfiles.put(lang, track.getName());
+				}
+			}
+			mainVC.contextPut("trackfiles",trackfiles);
+
+			CommentAndRatingSecurityCallback ratingSecCallback = new CommentAndRatingDefaultSecurityCallback(getIdentity(), false, false);
+			commentsAndRatingCtr = new UserCommentsAndRatingsController(ureq, getWindowControl(),entry.getOlatResource(), OresSubPath , ratingSecCallback,showComments, showRating, true);
+			listenTo(commentsAndRatingCtr);
+
+			mainVC.put("commentsAndRating", commentsAndRatingCtr.getInitialComponent());
+
+			mainVC.contextPut("autoplay", autoplay);
+
+			if(customDescription){
+				mainVC.contextPut("description",descriptionText);
+			}else{
+				mainVC.contextPut("description",videoManager.getDescription(entry.getOlatResource()));
+			}
+		}
+	}
+
+	@Override
+	protected void doDispose() {
+
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if(source == mainVC){
+			if("ended".equals(event.getCommand())){
+				fireEvent(ureq, ENDED_EVENT);
+			}
+		}
+	}
+
+	private VFSLeaf getVideo(RepositoryEntry entry) {
+		OLATResource resource = entry.getOlatResource();
+		VFSContainer fResourceFileroot = FileResourceManager.getInstance()
+				.getFileResourceRootImpl(resource);
+
+		VFSLeaf document = null;
+		for(VFSItem item:fResourceFileroot.getItems()) {
+			if (item instanceof VFSContainer && item.getName().endsWith("media")) {
+				VFSContainer mediaFolder = (VFSContainer) item;
+				for (VFSItem video:mediaFolder.getItems()) {
+					if (video instanceof VFSLeaf && video.getName().endsWith("mp4")) {
+						document = (VFSLeaf)video;
+					}
+				}
+			}
+		}
+		return document;
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/ui/VideoMetaDataEditFormController.java b/src/main/java/org/olat/modules/video/ui/VideoMetaDataEditFormController.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec0a40d5cd799fc4a48b67088a1cb7966782e289
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoMetaDataEditFormController.java
@@ -0,0 +1,66 @@
+package org.olat.modules.video.ui;
+
+import java.text.DateFormat;
+
+import org.apache.commons.io.FileUtils;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
+import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+public class VideoMetaDataEditFormController extends FormBasicController {
+
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+	@Autowired
+	private VideoManager videoManager;
+	private OLATResource videoResource;
+	private StaticTextElement heightField, widthField;
+	private RichTextElement descriptionField;
+
+
+	public VideoMetaDataEditFormController(UserRequest ureq, WindowControl wControl, OLATResource re) {
+		super(ureq, wControl);
+		videoResource = re;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener,
+			UserRequest ureq) {
+		setFormTitle("tab.video.metaDataConfig");
+
+		Size videoSize;
+		videoSize = videoManager.getVideoSize(videoResource);
+		if(videoSize == null){
+			videoSize = new Size(0, 0, false);
+		}
+
+		widthField = uifactory.addStaticTextElement("video.config.width", String.valueOf(videoSize.getWidth()), formLayout);
+		heightField = uifactory.addStaticTextElement("video.config.height", String.valueOf(videoSize.getHeight()), formLayout);
+		uifactory.addStaticTextElement("video.config.creationDate",DateFormat.getDateInstance().format(videoResource.getCreationDate()), formLayout);
+		uifactory.addStaticTextElement("video.config.fileSize", FileUtils.byteCountToDisplaySize(videoManager.getVideoFile(videoResource).length()), formLayout);
+		descriptionField = uifactory.addRichTextElementForStringDataMinimalistic("description", "video.config.description", videoManager.getDescription(videoResource), -1, -1, formLayout, getWindowControl());
+		uifactory.addFormSubmitButton("submit", formLayout);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		videoManager.setVideoSize(videoResource, new Size(Integer.parseInt(widthField.getValue()), Integer.parseInt(heightField.getValue()), true));
+		videoManager.setDescription(videoResource, descriptionField.getValue());
+	}
+
+	@Override
+	protected void doDispose() {
+
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/ui/VideoPosterEditController.java b/src/main/java/org/olat/modules/video/ui/VideoPosterEditController.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb32293e5b08c94fc873268e1a8f066d98606758
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoPosterEditController.java
@@ -0,0 +1,133 @@
+package org.olat.modules.video.ui;
+
+import org.olat.core.commons.modules.bc.FolderEvent;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.helpers.Settings;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.modules.video.managers.MediaMapper;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class VideoPosterEditController extends FormBasicController {
+
+
+	@Autowired
+	private VideoManager videoManager;
+	private VFSLeaf posterFile;
+	private OLATResource videoResource;
+	private FormLayoutContainer displayContainer;
+	private FormLink replaceImage;
+	private FormLink uploadImage;
+	private VideoPosterSelectionForm posterSelectionForm;
+	private CloseableModalController cmc;
+	private VideoPosterUploadForm posterUploadForm;
+
+	public VideoPosterEditController(UserRequest ureq, WindowControl wControl, OLATResource videoResource) {
+		super(ureq, wControl);
+		this.videoResource = videoResource;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		setFormTitle("tab.video.posterConfig");
+
+
+		String posterPage = velocity_root + "/poster_config.html";
+		displayContainer = FormLayoutContainer.createCustomFormLayout("tasks", getTranslator(), posterPage);
+
+		displayContainer.contextPut("hint", translate("video.config.poster.hint"));
+
+		posterFile = videoManager.getPosterframe(videoResource);
+		updatePosterImage(ureq, videoResource);
+		displayContainer.setLabel("video.config.poster", null);
+		formLayout.add(displayContainer);
+
+		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonGroupLayout", getTranslator());
+		formLayout.add(buttonGroupLayout);
+
+		replaceImage = uifactory.addFormLink("replaceimg", "video.config.poster.replace", null, buttonGroupLayout, Link.BUTTON);
+		replaceImage.setIconLeftCSS("o_icon o_icon_browse o_icon-fw");
+		replaceImage.setVisible(true);
+		uploadImage = uifactory.addFormLink("uploadImage", "video.config.poster.upload", null, buttonGroupLayout, Link.BUTTON);
+		uploadImage.setIconLeftCSS("o_icon o_icon_upload o_icon-f");
+		uploadImage.setVisible(true);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if (source == replaceImage) {
+			doReplaceVideo(ureq);
+		} else if (source == uploadImage) {
+			doUploadVideo(ureq);
+		}
+	}
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void event(UserRequest ureq, Controller source, Event event) {
+		if(source == posterUploadForm|| source == posterSelectionForm){
+			if(event instanceof FolderEvent){
+				posterFile = (VFSLeaf) ((FolderEvent) event).getItem();
+				flc.setDirty(true);
+				cmc.deactivate();
+				VFSLeaf newPosterFile = posterFile;
+				videoManager.setPosterframe(videoResource, newPosterFile);
+				if(source == posterUploadForm){
+					posterFile.delete();
+				}
+				updatePosterImage(ureq, videoResource);
+			}
+		}
+	}
+
+	private void doReplaceVideo(UserRequest ureq){
+		posterSelectionForm = new VideoPosterSelectionForm(ureq, getWindowControl(), videoResource);
+		listenTo(posterSelectionForm);
+		cmc = new CloseableModalController(getWindowControl(), "close", posterSelectionForm.getInitialComponent());
+		listenTo(cmc);
+		cmc.activate();
+	}
+
+	private void doUploadVideo(UserRequest ureq){
+		posterUploadForm = new VideoPosterUploadForm(ureq, getWindowControl(), videoResource);
+		listenTo(posterUploadForm);
+		cmc = new CloseableModalController(getWindowControl(), "close", posterUploadForm.getInitialComponent());
+		listenTo(cmc);
+		cmc.activate();
+	}
+
+	private void updatePosterImage(UserRequest ureq, OLATResource video){
+		posterFile = videoManager.getPosterframe(video);
+		VFSContainer mediaBase = FileResourceManager.getInstance().getFileResourceMedia(video);
+		MediaMapper mediaMapper = new MediaMapper(mediaBase);
+		String mediaUrl = registerMapper(ureq, mediaMapper);
+		String serverUrl = Settings.createServerURI();
+		displayContainer.contextPut("serverUrl", serverUrl);
+		displayContainer.contextPut("mediaUrl", mediaUrl);
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java b/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..167d3135cf13288a250f5fa13d573cc46b0a9980
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java
@@ -0,0 +1,125 @@
+package org.olat.modules.video.ui;
+
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jcodec.common.FileChannelWrapper;
+import org.jcodec.containers.mp4.demuxer.MP4Demuxer;
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.modules.bc.FolderEvent;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.helpers.Settings;
+import org.olat.core.util.vfs.LocalFolderImpl;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.core.util.vfs.VFSManager;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.modules.video.managers.MediaMapper;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.resource.OLATResource;
+
+public class VideoPosterSelectionForm extends BasicController {
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+	long remainingSpace;
+	private VFSContainer videoResourceFileroot;
+	private VFSContainer metaDataFolder;
+	private VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
+	VelocityContainer proposalLayout = createVelocityContainer("video_poster_proposal");
+
+	private Map<String, String> generatedPosters;
+	private Map<Link, VFSLeaf> buttons = new HashMap<Link, VFSLeaf>();
+
+
+
+	public VideoPosterSelectionForm(UserRequest ureq, WindowControl wControl, OLATResource videoResource) {
+		super(ureq, wControl);
+
+		videoResourceFileroot =  new LocalFolderImpl(FileResourceManager.getInstance().getFileResourceRootImpl(videoResource).getBasefile());
+		metaDataFolder = VFSManager.getOrCreateContainer(videoResourceFileroot, "media");
+		generatedPosters = new HashMap<String, String>();
+
+
+		long duration =1000;
+
+			RandomAccessFile accessFile;
+			try {
+				accessFile = new RandomAccessFile(videoManager.getVideoFile(videoResource),"r");
+				FileChannel ch = accessFile.getChannel();
+				FileChannelWrapper in = new FileChannelWrapper(ch);
+				MP4Demuxer demuxer1 = new MP4Demuxer(in);
+				duration = demuxer1.getVideoTrack().getFrameCount();
+			} catch (FileNotFoundException e1) {
+				// TODO Auto-generated catch block
+				e1.printStackTrace();
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+
+
+		long firstThirdDuration = duration/3;
+		for(int x=0; x<=duration;x+=firstThirdDuration ){
+			try {
+
+				VFSContainer proposalContainer = VFSManager.getOrCreateContainer(metaDataFolder, "proposalPosters");
+				VFSLeaf posterProposal = proposalContainer.createChildLeaf("proposalPoster"+x+".jpg");
+				if(posterProposal == null){
+					posterProposal = (VFSLeaf) proposalContainer.resolve("/proposalPoster"+x+".jpg");
+				}else{
+				videoManager.getFrame(videoResource, x, posterProposal);
+				}
+				MediaMapper mediaMapper = new MediaMapper(proposalContainer);
+				String mediaUrl = registerMapper(ureq, mediaMapper);
+				String serverUrl = Settings.createServerURI();
+				proposalLayout.contextPut("serverUrl", serverUrl);
+
+				Link button = LinkFactory.createButton(String.valueOf(x), proposalLayout, this);
+				button.setCustomDisplayText(translate("poster.select"));
+				buttons.put(button, posterProposal);
+//				.addFormLink(posterProposal.getName(), "selectPoster", "track.delete", "track.delete", null, Link.BUTTON);
+
+				generatedPosters.put(mediaUrl+"/proposalPoster"+x+".jpg", String.valueOf(x));
+			} catch (Exception e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+
+		proposalLayout.contextPut("pics", generatedPosters);
+
+
+		putInitialPanel(proposalLayout);
+	}
+
+
+
+
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		for(Link button: buttons.keySet()){
+			if(source == button){
+				fireEvent(ureq, new FolderEvent(FolderEvent.UPLOAD_EVENT, buttons.get(button)));
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/VideoPosterUploadForm.java b/src/main/java/org/olat/modules/video/ui/VideoPosterUploadForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6452a2dd7713d1e2c1053785e1038ae6f0474cb
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoPosterUploadForm.java
@@ -0,0 +1,81 @@
+package org.olat.modules.video.ui;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.olat.core.commons.modules.bc.FolderEvent;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.vfs.LocalFolderImpl;
+import org.olat.core.util.vfs.Quota;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSManager;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.resource.OLATResource;
+
+public class VideoPosterUploadForm extends FormBasicController {
+	private OLATResource videoResource;
+	long remainingSpace;
+	private VFSContainer videoResourceFileroot;
+	private VFSContainer metaDataFolder;
+	private FileElement posterField;
+
+	private static final int picUploadlimitKB = 51200;
+
+
+	private static final Set<String> imageMimeTypes = new HashSet<String>();
+	static {
+		imageMimeTypes.add("image/jpg");
+		imageMimeTypes.add("image/jpeg");
+	}
+
+	public VideoPosterUploadForm(UserRequest ureq, WindowControl wControl, OLATResource videoResource) {
+		super(ureq, wControl);
+		this.videoResource = videoResource;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		remainingSpace = Quota.UNLIMITED;
+		videoResourceFileroot = new LocalFolderImpl(FileResourceManager.getInstance().getFileResourceRootImpl(videoResource).getBasefile());
+		metaDataFolder = VFSManager.getOrCreateContainer(videoResourceFileroot, "media");
+
+		posterField = uifactory.addFileElement(getWindowControl(), "poster", "video.config.poster", formLayout);
+		posterField.limitToMimeType(imageMimeTypes, null, null);
+		posterField.setMaxUploadSizeKB(picUploadlimitKB, null, null);
+		posterField.setPreview(ureq.getUserSession(), true);
+		posterField.addActionListener(FormEvent.ONCHANGE);
+
+		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonGroupLayout", getTranslator());
+		formLayout.add(buttonGroupLayout);
+		buttonGroupLayout.setElementCssClass("o_sel_upload_buttons");
+		uifactory.addFormSubmitButton("track.upload", buttonGroupLayout);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		if ( posterField.isUploadSuccess()) {
+			if (remainingSpace != -1) {
+				if (posterField.getUploadFile().length() / 1024 > remainingSpace) {
+					posterField.setErrorKey("QuotaExceeded", null);
+					posterField.getUploadFile().delete();
+					return;
+				}
+			}else{
+				fireEvent(ureq, new FolderEvent(FolderEvent.UPLOAD_EVENT, posterField.moveUploadFileTo(metaDataFolder)));
+			}
+		}
+	}
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/VideoQualityTableFormController.java b/src/main/java/org/olat/modules/video/ui/VideoQualityTableFormController.java
new file mode 100644
index 0000000000000000000000000000000000000000..84bf50fed3d17d1f55713a2f3f9996909ff97769
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoQualityTableFormController.java
@@ -0,0 +1,82 @@
+package org.olat.modules.video.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.modules.video.models.VideoQualityTableModel;
+import org.olat.modules.video.models.VideoQualityTableModel.QualityTableCols;
+import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+public class VideoQualityTableFormController extends FormBasicController {
+
+	private FlexiTableElement tableEl;
+	private VideoQualityTableModel tableModel;
+
+	@Autowired
+	private VideoManager videoManager;
+	private OLATResource videoResource;
+
+
+	public VideoQualityTableFormController(UserRequest ureq, WindowControl wControl, OLATResource videoResource) {
+		super(ureq, wControl, LAYOUT_VERTICAL);
+		this.videoResource = videoResource;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		FormLayoutContainer generalCont = FormLayoutContainer.createVerticalFormLayout("general", getTranslator());
+		generalCont.setFormTitle(translate("tab.video.qualityConfig"));
+		generalCont.setRootForm(mainForm);
+		generalCont.setFormContextHelp("Video Tracks");
+		formLayout.add(generalCont);
+
+		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.type.i18nKey(), QualityTableCols.type.ordinal(), true, QualityTableCols.type.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.dimension.i18nKey(), QualityTableCols.dimension.ordinal(), true, QualityTableCols.dimension.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.size.i18nKey(), QualityTableCols.size.ordinal(), true, QualityTableCols.size.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.format.i18nKey(), QualityTableCols.format.ordinal(), true, QualityTableCols.format.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.view.i18nKey(), QualityTableCols.view.ordinal(), true, QualityTableCols.view.name()));
+		tableModel = new VideoQualityTableModel(columnsModel, getTranslator());
+
+		List<QualityTableRow> rows = new ArrayList<QualityTableRow>();
+
+		Size origSize = videoManager.getVideoSize(videoResource);
+
+		FormLink viewButton = uifactory.addFormLink("view", "viewQuality", "quality.view", "qulaity.view", null, Link.LINK);
+		rows.add(new QualityTableRow("original", origSize.getWidth() +"x"+ origSize.getHeight(),  FileUtils.byteCountToDisplaySize(videoManager.getVideoFile(videoResource).length()), "mp4",viewButton));
+		tableModel.setObjects(rows);
+		tableEl = uifactory.addTableElement(getWindowControl(), "qualities", tableModel, getTranslator(), generalCont);
+		tableEl.setCustomizeColumns(false);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java b/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3f6ff5bef069697ab9e45f8eb72fdeb37d22c66
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java
@@ -0,0 +1,87 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.video.ui;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.dropdown.Dropdown;
+import org.olat.core.gui.components.dropdown.Dropdown.Spacer;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.model.RepositoryEntrySecurity;
+import org.olat.repository.ui.RepositoryEntryRuntimeController;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ *
+ * The runtime add configuration management and delivery options.
+ *
+ * Initial date: 01.04.2015<br>
+ * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+public class VideoRuntimeController extends RepositoryEntryRuntimeController {
+
+	private Link settingsLink;
+
+	@Autowired
+	private VideoManager videoManager;
+
+	public VideoRuntimeController(UserRequest ureq, WindowControl wControl,
+			RepositoryEntry re, RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator) {
+		super(ureq, wControl, re, reSecurity, runtimeControllerCreator);
+	}
+
+	@Override
+	protected void initEditionTools(Dropdown settingsDropdown) {
+		super.initEditionTools(settingsDropdown);
+		if (reSecurity.isEntryAdmin()) {
+			settingsLink = LinkFactory.createToolLink("metaDataConfig", translate("tab.video.settings"), this);
+			settingsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_quota o_icon_settings");
+			settingsDropdown.addComponent(4, settingsLink);
+
+			settingsDropdown.addComponent(new Spacer("metadata-poster"));
+		}
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if(settingsLink == source){
+			doSettingsconfig(ureq);
+		}
+		else {
+			super.event(ureq, source, event);
+		}
+	}
+
+
+	private void doSettingsconfig(UserRequest ureq) {
+		RepositoryEntry entry = getRepositoryEntry();
+		Controller configCtrl = new VideoSettingsController(ureq, getWindowControl(), entry);
+		pushController(ureq, translate("tab.video.settings"), configCtrl);
+		setActiveTool(settingsLink);
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/VideoSettingsController.java b/src/main/java/org/olat/modules/video/ui/VideoSettingsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a90b3ec685e53119c714f21ce6fd848647975e0
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoSettingsController.java
@@ -0,0 +1,109 @@
+package org.olat.modules.video.ui;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.segmentedview.SegmentViewComponent;
+import org.olat.core.gui.components.segmentedview.SegmentViewEvent;
+import org.olat.core.gui.components.segmentedview.SegmentViewFactory;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.repository.RepositoryEntry;
+
+public class VideoSettingsController extends BasicController {
+
+	private RepositoryEntry entry;
+
+	private VideoMetaDataEditFormController metaDataController;
+	private VideoPosterEditController posterEditController;
+	private VideoTrackEditController trackEditController;
+	private VideoQualityTableFormController qualityEditController;
+
+	private Link metaDataLink, posterEditLink, trackEditLink, qualityConfig;
+
+	private final VelocityContainer mainVC;
+	private final SegmentViewComponent segmentView;
+
+
+
+	public VideoSettingsController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry ) {
+		super(ureq, wControl);
+
+		this.entry = entry;
+		mainVC = createVelocityContainer("video_settings");
+
+		segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this);
+
+		metaDataLink = LinkFactory.createLink("tab.video.metaDataConfig", mainVC, this);
+		segmentView.addSegment(metaDataLink, true);
+		posterEditLink = LinkFactory.createLink("tab.video.posterConfig", mainVC, this);
+		segmentView.addSegment(posterEditLink, false);
+		trackEditLink = LinkFactory.createLink("tab.video.trackConfig", mainVC, this);
+		segmentView.addSegment(trackEditLink, false);
+		qualityConfig = LinkFactory.createLink("tab.video.qualityConfig", mainVC, this);
+		segmentView.addSegment(qualityConfig, false);
+
+		doOpenMetaDataConfig(ureq);
+
+		putInitialPanel(mainVC);
+
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if(source == segmentView) {
+			if(event instanceof SegmentViewEvent) {
+				SegmentViewEvent sve = (SegmentViewEvent)event;
+				String segmentCName = sve.getComponentName();
+				Component clickedLink = mainVC.getComponent(segmentCName);
+				if (clickedLink == metaDataLink) {
+					doOpenMetaDataConfig(ureq);
+				} else if (clickedLink == posterEditLink){
+					doOpenPosterConfig(ureq);
+				} else if (clickedLink == trackEditLink){
+					doOpenTrackConfig(ureq);
+				} else if (clickedLink == qualityConfig){
+					doOpenQualityConfig(ureq);
+				}
+			}
+		}
+	}
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+
+	}
+
+	private void doOpenMetaDataConfig(UserRequest ureq) {
+		if(metaDataController == null) {
+			metaDataController = new VideoMetaDataEditFormController(ureq, getWindowControl(), entry.getOlatResource());
+		}
+		mainVC.put("segmentCmp", metaDataController.getInitialComponent());
+	}
+
+	private void doOpenPosterConfig(UserRequest ureq) {
+		if(posterEditController == null) {
+			posterEditController = new VideoPosterEditController(ureq, getWindowControl(), entry.getOlatResource());
+		}
+		mainVC.put("segmentCmp", posterEditController.getInitialComponent());
+	}
+
+	private void doOpenTrackConfig(UserRequest ureq) {
+		if(trackEditController == null) {
+			trackEditController = new VideoTrackEditController(ureq, getWindowControl(), entry.getOlatResource());
+		}
+		mainVC.put("segmentCmp", trackEditController.getInitialComponent());
+	}
+
+	private void doOpenQualityConfig(UserRequest ureq) {
+		if(qualityEditController == null) {
+			qualityEditController = new VideoQualityTableFormController(ureq, getWindowControl(), entry.getOlatResource());
+		}
+		mainVC.put("segmentCmp", qualityEditController.getInitialComponent());
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/ui/VideoTrackEditController.java b/src/main/java/org/olat/modules/video/ui/VideoTrackEditController.java
new file mode 100644
index 0000000000000000000000000000000000000000..01b309d883d65781d725795be33b577eb6833b0e
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoTrackEditController.java
@@ -0,0 +1,141 @@
+package org.olat.modules.video.ui;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.olat.core.commons.modules.bc.FolderEvent;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.FormUIFactory;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.modules.video.models.VideoTracksTableModel;
+import org.olat.modules.video.models.VideoTracksTableModel.TrackTableCols;
+import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class VideoTrackEditController extends FormBasicController {
+	protected FormUIFactory uifactory = FormUIFactory.getInstance();
+
+	private FlexiTableElement tableEl;
+	private VideoTracksTableModel tableModel;
+	private FormLink addButton;
+	VideoTrackUploadForm trackUploadForm;
+	VideoPosterUploadForm posterUploadForm;
+	VideoPosterSelectionForm posterSelectionForm;
+	CloseableModalController cmc;
+
+	private Map<String, TrackTableRow> rows;
+
+	@Autowired
+	private VideoManager videoManager;
+	private OLATResource videoResource;
+
+	public VideoTrackEditController(UserRequest ureq, WindowControl wControl, OLATResource videoResource) {
+		super(ureq, wControl, LAYOUT_BAREBONE);
+		this.videoResource = videoResource;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		FormLayoutContainer generalCont = FormLayoutContainer.createVerticalFormLayout("general", getTranslator());
+		generalCont.setFormTitle(translate("tab.video.trackConfig"));
+		generalCont.setRootForm(mainForm);
+		generalCont.setFormContextHelp("Video Tracks");
+		formLayout.add(generalCont);
+
+		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, TrackTableCols.file.i18nKey(), TrackTableCols.file.ordinal(), true, TrackTableCols.file.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TrackTableCols.language.i18nKey(), TrackTableCols.language.ordinal(), true, TrackTableCols.language.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, TrackTableCols.delete.i18nKey(), TrackTableCols.delete.ordinal(),false, TrackTableCols.delete.name()));
+		tableModel = new VideoTracksTableModel(columnsModel, getTranslator());
+
+		tableEl = uifactory.addTableElement(getWindowControl(), "tracks", tableModel, getTranslator(), generalCont);
+		tableEl.setCustomizeColumns(false);
+		HashMap<String, VFSLeaf> tracks = videoManager.getAllTracks(videoResource);
+		rows = new HashMap<String,TrackTableRow>(tracks.size());
+		if (!tracks.isEmpty()) {
+			for (Map.Entry<String, VFSLeaf> entry : tracks.entrySet()) {
+				FormLink delButton = uifactory.addFormLink(entry.getKey(), "deleteTrack", "track.delete", "track.delete", null, Link.BUTTON);
+				rows.put(entry.getKey(), new TrackTableRow(entry.getKey(), entry.getValue(), delButton));
+
+			}
+			tableModel.setObjects(new ArrayList<TrackTableRow>(rows.values()));
+		}
+//		tableEl.setVisible(!videoManager.getAllTracks(videoResource).isEmpty());
+		tableEl.setVisible(true);
+
+		addButton = uifactory.addFormLink("add.track", generalCont, Link.BUTTON);
+	}
+
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+
+		return true;
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if (addButton == source) {
+			doAddTrack(ureq);
+		}else if (source.getComponent() instanceof Link){
+			String lang = rows.get(source.getName()).getLanguage();
+			videoManager.removeTrack(videoResource, lang);
+			rows.remove(rows.get(source.getName()).getLanguage());
+			tableModel.setObjects(new ArrayList<TrackTableRow>(rows.values()));
+			tableEl.reset();
+		}
+	}
+
+	@Override
+	public void event(UserRequest ureq, Controller source, Event event) {
+		if(source == trackUploadForm){
+			videoManager.addTrack(videoResource, trackUploadForm.getLang(),(VFSLeaf) ((FolderEvent) event).getItem());
+			rows.put(trackUploadForm.getLang(), new TrackTableRow(trackUploadForm.getLang(), (VFSLeaf) ((FolderEvent) event).getItem(), uifactory.addFormLink(trackUploadForm.getLang(),"deleteTrack", "track.delete", "track.delete", null, Link.BUTTON)));
+			tableModel.setObjects(new ArrayList<TrackTableRow>(rows.values()));
+			tableEl.reset();
+			tableEl.setVisible(true);
+			tableEl.setEnabled(true);
+			cmc.deactivate();
+		}
+		else if(event.getCommand() == "CLOSE_MODAL_EVENT"){
+			cmc.deactivate();
+		}
+	}
+
+
+	private void doAddTrack(UserRequest ureq) {
+		trackUploadForm = new VideoTrackUploadForm(ureq, getWindowControl(), videoResource);
+		listenTo(trackUploadForm);
+		cmc = new CloseableModalController(getWindowControl(), "close", trackUploadForm.getInitialComponent());
+		listenTo(cmc);
+		cmc.activate();
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java b/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..d431c546262909847b3d1462047f40c6e0388d57
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java
@@ -0,0 +1,112 @@
+package org.olat.modules.video.ui;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.olat.core.commons.modules.bc.FolderEvent;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.vfs.LocalFolderImpl;
+import org.olat.core.util.vfs.Quota;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSManager;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.resource.OLATResource;
+
+/**
+ *
+ * Initial date: 01.04.2015<br>
+ * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
+ *
+ */
+
+public class VideoTrackUploadForm extends FormBasicController {
+	private OLATResource videoResource;
+	private FileElement fileEl;
+	SingleSelection langsItem;
+	long remainingSpace;
+	private VFSContainer videoResourceFileroot;
+	private VFSContainer metaDataFolder;
+
+	private static final Set<String> trackMimeTypes = new HashSet<String>();
+	static {
+		trackMimeTypes.add("text/plain");
+	}
+
+	public VideoTrackUploadForm(UserRequest ureq, WindowControl wControl, OLATResource videoResource) {
+		super(ureq, wControl);
+		this.videoResource = videoResource;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		remainingSpace = Quota.UNLIMITED;
+		videoResourceFileroot = new LocalFolderImpl(FileResourceManager.getInstance().getFileResourceRootImpl(videoResource).getBasefile());
+		metaDataFolder = VFSManager.getOrCreateContainer(videoResourceFileroot, "media");
+		List<String> langs = new ArrayList<String>();
+		List<String> dispLangs = new ArrayList<String>();
+
+
+		for(Locale locale : SimpleDateFormat.getAvailableLocales()){
+			if(locale.hashCode()!=0){
+				langs.add(locale.getLanguage());
+				dispLangs.add(locale.getDisplayLanguage(getTranslator().getLocale()));
+			}
+		}
+
+		List<String> langsWithoutDup = langs.parallelStream().distinct().collect(Collectors.toList());
+		List<String> dispLangsWithoutDup = dispLangs.parallelStream().distinct().collect(Collectors.toList());
+
+		langsItem = uifactory.addDropdownSingleselect("track.langs", formLayout, langsWithoutDup.toArray(new String[langsWithoutDup.size()]), dispLangsWithoutDup.toArray(new String[dispLangsWithoutDup.size()]), null);
+		fileEl = uifactory.addFileElement(getWindowControl(), "track.upload", formLayout);
+//		fileEl.limitToMimeType(trackMimeTypes, "video.config.track.error.type", null);
+		langsItem.setMandatory(true);
+
+		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonGroupLayout", getTranslator());
+		formLayout.add(buttonGroupLayout);
+		buttonGroupLayout.setElementCssClass("o_sel_upload_buttons");
+		uifactory.addFormSubmitButton("track.upload", buttonGroupLayout);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		if ( fileEl.isUploadSuccess()) {
+			if (remainingSpace != -1) {
+				if (fileEl.getUploadFile().length() / 1024 > remainingSpace) {
+					fileEl.setErrorKey("QuotaExceeded", null);
+					fileEl.getUploadFile().delete();
+					return;
+				}
+			}else{
+				fireEvent(ureq, new FolderEvent(FolderEvent.UPLOAD_EVENT, fileEl.moveUploadFileTo(metaDataFolder)));
+			}
+		}else{
+			fileEl.setErrorKey("track.upload.error.nofile", null);
+		}
+
+	}
+
+
+	protected String getLang(){
+		return langsItem.getSelectedKey();
+	}
+
+
+	@Override
+	protected void doDispose() {
+		// TODO Auto-generated method stub
+
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/_content/poster_config.html b/src/main/java/org/olat/modules/video/ui/_content/poster_config.html
new file mode 100644
index 0000000000000000000000000000000000000000..0ab46e994b4da953cc771470ad5705b3290eb513
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/_content/poster_config.html
@@ -0,0 +1,2 @@
+<div class="o_note">$hint</div>
+<img src="$mediaUrl/poster.jpg" height="400px" width="400px" />
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/_content/video_poster_proposal.html b/src/main/java/org/olat/modules/video/ui/_content/video_poster_proposal.html
new file mode 100644
index 0000000000000000000000000000000000000000..60ee404e7d5cf2fd4bb5d3e550cd129d40ad5ee1
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/_content/video_poster_proposal.html
@@ -0,0 +1,5 @@
+#foreach( $poster in $pics.entrySet())
+<div>
+<img src="$poster.key" height="400px" width="400px" />$r.render($poster.value)
+</div>
+#end
diff --git a/src/main/java/org/olat/modules/video/ui/_content/video_run.html b/src/main/java/org/olat/modules/video/ui/_content/video_run.html
new file mode 100644
index 0000000000000000000000000000000000000000..d5e9c59e1fe9e06bcc68ead53c7bbfe8fc0ebc0d
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/_content/video_run.html
@@ -0,0 +1,43 @@
+
+#if($image)
+	<img src="$mediaUrl/$filename" />
+#elseif($movie)
+	<div class="olatFlashMovieViewer">
+		<video id="$r.getId("o_vid")" width="$width" height="$height" poster="$mediaUrl/poster.jpg" controls  #if( $autoplay ) autoplay #end>
+	    	<source type="video/mp4" src="$mediaUrl/$filename" />
+	  		#if( $trackfiles )
+		  		#foreach( $track in $trackfiles.keySet())
+		  		<track kind="subtitles" src="$mediaUrl/$trackfiles.get($track)" srclang="$track" />
+		  		#end
+		  	#end
+		</video>
+
+
+		<script defer="defer" type="text/javascript">
+		// <![CDATA[
+		// using jQuery
+		jQuery('#$r.getId("o_vid")').mediaelementplayer({
+			success: function (mediaElement, domObject) {
+		        // add event listener
+		        mediaElement.addEventListener('ended', function(e) {
+		        	if (!o_info.linkbusy) {
+						window.suppressOlatOnUnloadOnce = true;
+						o_beforeserver();
+						$r.javaScriptBgCommand("ended");
+					}
+
+		        }, false);
+		    }
+
+
+		});
+		// ]]>
+		</script>
+	</div>
+#elseif($r.available("content"))
+	<div class="o_content clearfix">$r.render("content")</div>
+#end
+$r.render("commentsAndRating")
+#if($description)
+$description
+#end
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/_content/video_settings.html b/src/main/java/org/olat/modules/video/ui/_content/video_settings.html
new file mode 100644
index 0000000000000000000000000000000000000000..03e5a4e314f4850964d2e4a85ad3a7d47f7be95f
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/_content/video_settings.html
@@ -0,0 +1,7 @@
+<div class="clearfix">
+	$r.render("segments") <br/>
+
+	#if($r.available("segmentCmp"))
+		$r.render("segmentCmp")
+	#end
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5019e430cb75cdb043eaf4609ef52966d64b521c
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties
@@ -0,0 +1,46 @@
+tab.video.posterConfig=Poster konfigurieren
+tab.video.metaDataConfig=Metadaten konfigurieren
+tab.video.trackConfig=Untertitel konfigurieren
+tab.video.settings=Videokonfiguration
+tab.video.qualityConfig=Qualit\u00E4t konfigurieren
+video.config.width=Breite in pixel
+video.config.height=H\u00F6he in pixel
+video.config.filename=Dateinamen
+video.config.creationDate=Erstellungs Datum
+video.config.fileSize=Gr\u00F6sse der Videodatei
+video.config.description=Beschreibung
+video.config.poster.hint=Hier k\u00F6nnen Sie das Titelbild konfigurieren welches vor dem Video angezeigt wird sowie in der Kursnode \u00FCbersicht.
+video.config.poster=Poster
+video.config.poster.replace=Ersetzte poster
+video.config.poster.upload=Upload poster
+video.config.tracks=Verf\u00FCgbare Untertiteldateien
+video.config.tracks.table.add=hinzuf\u00FCgen
+video.config.tracks.table.delete=l\u00F6schen
+video.config.tracks.table.lang=Sprache
+video.config.track.table.file=Untertitel Datei
+add.track=Untertitel hinzuf\u00FCgen
+track.table.label=Untertitel
+track.table.header.file=Datei
+track.table.header.language=Sprache
+track.table.header.delete=l\u00F6schen
+track.upload=Untertitel Datei
+track.langs=Sprache
+track.upload=Upload
+track.delete=L\u00F6schen
+track.upload.error.nolang=Bitte w\u00E4hlen Sie eine Sprache aus dieser Liste aus
+track.upload.error.nofile=Bitte w\u00E4hlen Sie eine Datei aus.
+poster.select=ausw\u00E4hlen
+admin.menu.title=Video
+admin.menu.title.alt=Konfiguration der Video-Resource
+admin.config.title=Video Konfiguration
+admin.config.enable=Videoresource einschalten
+admin.config.videoNode=Video Kursbaustein aktivieren
+admin.config.transcoding=Transcoding aktivieren
+tab.video.qualityConfig=Videoqualit\u00E4ten
+
+quality.table.header.type=Typ
+quality.table.header.dimension=Dimension
+quality.table.header.size=Gr\u00F6sse
+quality.table.header.format=Format
+quality.table.header.view=ansehen
+quality.view=vorschau
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..fe26db9a1e175d666fcdd98e628eeddad601272d
--- /dev/null
+++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties
@@ -0,0 +1,37 @@
+tab.video.posterConfig=Poster configuration
+tab.video.metaDataConfig=Metadata configuration
+tab.video.trackConfig=Subtitle configuration
+tab.video.settings=Video settings
+video.config.width=Width in px
+video.config.height=Height in px
+video.config.filename=Filename
+video.config.creationDate=Creation Date
+video.config.fileSize=Size of videofile
+video.config.description=Description
+video.config.poster.hint=Here you can configure the posterframe which will be visible in the videoplayer before the video start playing aswell as in course overview
+video.config.poster=Poster frame
+video.config.poster.replace=Replace poster
+video.config.poster.upload=Upload poster
+video.config.tracks=Available Trackfiles
+video.config.tracks.table.add=add
+video.config.tracks.table.delete=delete
+video.config.tracks.table.lang=language
+video.config.track.table.file=track file
+video.config.track.error.type=only *.vtt and *.srt files are permitted
+add.track=Add Subtitle
+table.label=Subtitles
+table.header.file=File
+table.header.language=Language
+table.header.delete=Delete
+track.upload=track file
+track.langs=Language
+track.upload=Upload
+track.delete=Delete
+track.upload.error.nolang=Please select a language form the list
+poster.select=select
+admin.menu.title=Video
+admin.menu.title.alt=Configuration of the Video-Resource
+admin.config.title=Video Configuration
+admin.config.enable=enable videoresource
+admin.config.videoNode=enable video coursenode
+admin.config.transcoding=enable video transcoding
\ No newline at end of file
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
index fadfdfa0ae584ae008572986c9873c842de7ecdb..870ba1dd56ee5bbf6e02157fc0f50779736c564b 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
@@ -10,6 +10,7 @@ FileResource.GLOSSARY=Glossar
 FileResource.IMAGE=Bild
 FileResource.IMSCP=CP-Lerninhalt
 FileResource.MOVIE=Film
+FileResource.VIDEO=Video
 FileResource.PDF=PDF
 FileResource.PODCAST=Podcast
 FileResource.PPT=PowerPoint
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
index 37499632484716f3935296abcd39d37888b4a5ad..c498d1de24a8b1c613c669c22cc8cf35c8e986f7 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
@@ -10,6 +10,7 @@ FileResource.GLOSSARY=Glossary
 FileResource.IMAGE=Image
 FileResource.IMSCP=CP learning content
 FileResource.MOVIE=Movie
+FileResource.VIDEO=Video
 FileResource.PDF=PDF
 FileResource.PODCAST=Podcast
 FileResource.PPT=PowerPoint
diff --git a/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java b/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java
index fd7299640a66e25536c92ba28a995247a042b717..88cd42bd6c340a070487d8b44e171e94b858b7f3 100644
--- a/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java
+++ b/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java
@@ -49,6 +49,7 @@ import org.olat.fileresource.types.BlogFileResource;
 import org.olat.fileresource.types.ImsCPFileResource;
 import org.olat.fileresource.types.PodcastFileResource;
 import org.olat.fileresource.types.ScormCPFileResource;
+import org.olat.fileresource.types.VideoFileResource;
 import org.olat.fileresource.types.WikiResource;
 import org.olat.group.BusinessGroupModule;
 import org.olat.ims.qti.fileresource.SurveyFileResource;
@@ -231,7 +232,8 @@ public class ReferencableEntriesSearchController extends BasicController {
 				ScormCPFileResource.TYPE_NAME,
 				SurveyFileResource.TYPE_NAME,
 				BlogFileResource.TYPE_NAME,
-				PodcastFileResource.TYPE_NAME
+				PodcastFileResource.TYPE_NAME,
+				VideoFileResource.TYPE_NAME
 		};
 		
 		if (Collections.indexOfSubList(Arrays.asList(importAllowed), limitTypeList) != -1) { return true; }
diff --git a/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java b/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java
index 2a994e41cbc6abcf16697346ad733a2524133348..56a8932c47b7d7ec0cf161fdc92faa4598a2db1e 100644
--- a/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java
+++ b/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java
@@ -78,6 +78,7 @@ public class RepositoryHandlerFactory {
 		registerHandler(new SharedFolderHandler(), 40);
 		registerHandler(new GlossaryHandler(), 41);
 		registerHandler(new PortfolioHandler(), 42);
+		registerHandler(new VideoHandler(), 43);
 		
 		registerHandler(new WebDocumentHandler(DocFileResource.TYPE_NAME), 10001);
 		registerHandler(new WebDocumentHandler(XlsFileResource.TYPE_NAME), 10002);
diff --git a/src/main/java/org/olat/repository/handlers/VideoHandler.java b/src/main/java/org/olat/repository/handlers/VideoHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6465e105fd0a6d17bab9b11bdea365a2da67779
--- /dev/null
+++ b/src/main/java/org/olat/repository/handlers/VideoHandler.java
@@ -0,0 +1,259 @@
+/**
+* OLAT - Online Learning and Training<br>
+* http://www.olat.org
+* <p>
+* Licensed under the Apache License, Version 2.0 (the "License"); <br>
+* you may not use this file except in compliance with the License.<br>
+* You may obtain a copy of the License at
+* <p>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p>
+* Unless required by applicable law or agreed to in writing,<br>
+* software distributed under the License is distributed on an "AS IS" BASIS, <br>
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+* See the License for the specific language governing permissions and <br>
+* limitations under the License.
+* <p>
+* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
+* University of Zurich, Switzerland.
+* <hr>
+* <a href="http://www.openolat.org">
+* OpenOLAT - Online Learning and Training</a><br>
+* This file has been modified by the OpenOLAT community. Changes are licensed
+* under the Apache 2.0 license as the original file.
+*/
+
+package org.olat.repository.handlers;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.Locale;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.persistence.DBFactory;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.commons.services.video.MovieServiceImpl;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.stack.TooledStackedPanel;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.layout.MainLayoutController;
+import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
+import org.olat.core.gui.media.MediaResource;
+import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.logging.AssertException;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+import org.olat.core.util.FileUtils;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.coordinate.LockResult;
+import org.olat.core.util.vfs.LocalFileImpl;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.core.util.vfs.VFSManager;
+import org.olat.core.util.xml.XStreamHelper;
+import org.olat.course.assessment.AssessmentMode;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.fileresource.types.FileResource;
+import org.olat.fileresource.types.ResourceEvaluation;
+import org.olat.fileresource.types.VideoFileResource;
+import org.olat.modules.video.VideoModule;
+import org.olat.modules.video.managers.VideoManager;
+import org.olat.modules.video.models.VideoMetadata;
+import org.olat.modules.video.ui.VideoDisplayController;
+import org.olat.modules.video.ui.VideoRuntimeController;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.model.RepositoryEntrySecurity;
+import org.olat.repository.ui.RepositoryEntryRuntimeController.RuntimeControllerCreator;
+import org.olat.resource.OLATResource;
+import org.olat.resource.OLATResourceManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+/**
+ * Initial Date:  Mar 27, 2015
+ *
+ * @author Dirk Furrer
+ *
+ *
+ */
+public class VideoHandler extends FileHandler {
+
+	private static final OLog log = Tracing.createLoggerFor(VideoHandler.class);
+	@Autowired
+	private RepositoryManager repositoryManager;
+
+	private VideoManager videoManager;
+	private VideoModule videomodule ;
+
+	@Override
+	public boolean isCreate() {
+		return false;
+	}
+
+	@Override
+	public String getCreateLabelI18nKey() {
+		return null;
+	}
+
+	@Override
+	public RepositoryEntry createResource(Identity initialAuthor, String displayname, String description, Object createObject, Locale locale) {
+		return null;
+	}
+
+	@Override
+	public boolean isPostCreateWizardAvailable() {
+		return false;
+	}
+
+	@Override
+	public ResourceEvaluation acceptImport(File file, String filename) {
+		if(!StringHelper.containsNonWhitespace(filename)) {
+			filename = file.getName();
+		}
+
+		ResourceEvaluation eval = new ResourceEvaluation(false);
+		String extension = FileUtils.getFileSuffix(filename);
+		if(StringHelper.containsNonWhitespace(extension)) {
+			if (VideoFileResource.validate(filename)) {
+				eval.setValid(true);
+			}
+		}
+		return eval;
+	}
+
+	@Override
+	public RepositoryEntry importResource(Identity initialAuthor, String initialAuthorAlt, String displayname, String description,
+			boolean withReferences, Locale locale, File file, String filename) {
+
+		FileResource ores;
+		if (VideoFileResource.validate(filename)) {
+			ores = new VideoFileResource();
+		} else {
+			return null;
+		}
+
+		OLATResource resource = OLATResourceManager.getInstance().createAndPersistOLATResourceInstance(ores);
+		File videoResourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(resource).getBasefile();
+		File mediaFolder = new File(videoResourceFileroot, "media");
+		if(!mediaFolder.exists()) mediaFolder.mkdir();
+
+		File target = new File(mediaFolder, "video.mp4");
+
+
+		try {
+			Files.move(file.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
+		} catch (IOException e) {
+			log.error("", e);
+		}
+
+		RepositoryEntry re = CoreSpringFactory.getImpl(RepositoryService.class)
+				.create(initialAuthor, null, "", displayname, description, resource, RepositoryEntry.ACC_OWNERS);
+		DBFactory.getInstance().commit();
+
+		// generate Metadata
+		videoManager = CoreSpringFactory.getImpl(VideoManager.class);
+		videomodule = CoreSpringFactory.getImpl(VideoModule.class);
+		File metaDataFile = new File(videoResourceFileroot, "video_metadata.xml");
+		try{
+		XStreamHelper.writeObject(XStreamHelper.createXStreamInstance(), metaDataFile, new VideoMetadata(resource));
+		videoManager.setTitle(resource, displayname);
+		Size videoSize = CoreSpringFactory.getImpl(MovieServiceImpl.class).getSize(new LocalFileImpl(target), "mp4");
+		videoManager.setVideoSize(resource, videoSize);
+		VFSLeaf posterResource = VFSManager.resolveOrCreateLeafFromPath(FileResourceManager.getInstance().getFileResourceMedia(resource), "/poster.jpg");
+
+		videoManager.getFrame(resource, 20, posterResource);
+
+		videoManager.setPosterframe(resource, posterResource);
+		}catch(IOException e){
+			log.warn("wasnt able to create poster for video"+filename);
+		}
+
+		if(videomodule.isTranscodingEnabled()){
+			videoManager.optimizeVideoRessource(resource);
+		}
+
+		videoManager.setRatingEnabled(resource, false);
+		videoManager.setCommentsEnabled(resource, false);
+		return re;
+	}
+
+
+
+	@Override
+	public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) {
+		return FileResourceManager.getInstance().getAsDownloadeableMediaResource(res);
+	}
+
+	@Override
+	public String getSupportedType() {
+		return VideoFileResource.TYPE_NAME;
+	}
+
+	@Override
+	public boolean supportsDownload() {
+		return true;
+	}
+
+	@Override
+	public EditionSupport supportsEdit(OLATResourceable resource) {
+		return EditionSupport.no;
+	}
+
+	@Override
+	public StepsMainRunController createWizardController(OLATResourceable res, UserRequest ureq, WindowControl wControl) {
+		throw new AssertException("Trying to get wizard where no creation wizard is provided for this type.");
+	}
+
+	@Override
+	public MainLayoutController createLaunchController(RepositoryEntry re,  RepositoryEntrySecurity reSecurity, UserRequest ureq, WindowControl wControl) {
+		return new VideoRuntimeController(ureq, wControl, re, reSecurity, new RuntimeControllerCreator() {
+			@Override
+			public Controller create(UserRequest uureq, WindowControl wwControl, TooledStackedPanel toolbarPanel,
+					RepositoryEntry entry, RepositoryEntrySecurity rereSecurity, AssessmentMode assessmentMode) {
+				return new VideoDisplayController(uureq, wwControl, entry);
+			}
+		});
+	}
+
+	@Override
+	public Controller createEditorController(RepositoryEntry re, UserRequest ureq, WindowControl wControl, TooledStackedPanel toolbar) {
+		throw new AssertException("a web document is not editable!!! res-id:"+re.getResourceableId());
+	}
+
+	protected String getDeletedFilePrefix() {
+		return "del_video_";
+	}
+
+	@Override
+	public LockResult acquireLock(OLATResourceable ores, Identity identity) {
+    //nothing to do
+		return null;
+	}
+
+	@Override
+	public void releaseLock(LockResult lockResult) {
+		//nothing to do since nothing locked
+	}
+
+	@Override
+	public boolean isLocked(OLATResourceable ores) {
+		return false;
+	}
+
+	@Override
+	public RepositoryEntry copy(Identity author, RepositoryEntry source,
+			RepositoryEntry target) {
+		OLATResource sourceResource = source.getOlatResource();
+		OLATResource targetResource = target.getOlatResource();
+		File sourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(sourceResource).getBasefile();
+		File targetFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(targetResource).getBasefile();
+		FileUtils.copyDirContentsToDir(sourceFileroot, targetFileroot, false, "copy");
+		return target;
+	}
+
+}
diff --git a/src/main/java/org/olat/repository/ui/WebDocumentRunController.java b/src/main/java/org/olat/repository/ui/WebDocumentRunController.java
index 8d72259672836340f374ab8d6a045e7109919e50..b2e13db9c6da79c244746ff1d6f05297866b1e1f 100644
--- a/src/main/java/org/olat/repository/ui/WebDocumentRunController.java
+++ b/src/main/java/org/olat/repository/ui/WebDocumentRunController.java
@@ -21,7 +21,6 @@ package org.olat.repository.ui;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.services.image.Size;
 import org.olat.core.commons.services.video.MovieService;
 import org.olat.core.dispatcher.mapper.Mapper;
@@ -45,6 +44,7 @@ import org.olat.core.util.vfs.VFSMediaResource;
 import org.olat.fileresource.FileResourceManager;
 import org.olat.repository.RepositoryEntry;
 import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -54,6 +54,9 @@ import org.olat.resource.OLATResource;
  */
 public class WebDocumentRunController extends BasicController {
 
+	@Autowired
+	private MovieService movieService;
+
 	public WebDocumentRunController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry) {
 		super(ureq, wControl);
 
@@ -78,7 +81,7 @@ public class WebDocumentRunController extends BasicController {
 				String mediaUrl = registerMapper(ureq, new MediaMapper(document));
 				mainVC.contextPut("movie", filename);
 				mainVC.contextPut("mediaUrl", Settings.createServerURI() + mediaUrl);
-				Size realSize = CoreSpringFactory.getImpl(MovieService.class).getSize(document, extension);
+				Size realSize = movieService.getSize(document, extension);
 				if(realSize != null) {
 					mainVC.contextPut("height", realSize.getHeight());
 					mainVC.contextPut("width", realSize.getWidth());