diff --git a/src/main/java/org/olat/core/commons/services/video/JCodecHelper.java b/src/main/java/org/olat/core/commons/services/video/JCodecHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..46029699c5ca3988e598cc5ca149d07231896977
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/services/video/JCodecHelper.java
@@ -0,0 +1,63 @@
+/**
+ * <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.core.commons.services.video;
+
+import java.awt.image.BufferedImage;
+
+import org.apache.logging.log4j.Logger;
+import org.jcodec.api.transcode.PixelStore;
+import org.jcodec.api.transcode.PixelStore.LoanerPicture;
+import org.jcodec.api.transcode.PixelStoreImpl;
+import org.jcodec.api.transcode.filters.ScaleFilter;
+import org.jcodec.common.model.Picture;
+import org.jcodec.scale.AWTUtil;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.logging.Tracing;
+
+/**
+ * 
+ * Initial date: 7 mars 2021<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class JCodecHelper {
+	
+	private static final Logger log = Tracing.createLoggerFor(JCodecHelper.class);
+	
+	private JCodecHelper() {
+		//
+	}
+	
+	public static BufferedImage scale(Size movieSize, Picture picture, BufferedImage bufImg) {
+		if(movieSize != null && picture != null && bufImg != null
+				&& (bufImg.getWidth() != movieSize.getWidth() || bufImg.getHeight() != movieSize.getHeight())) {
+			try {
+				ScaleFilter filter = new ScaleFilter(movieSize.getWidth(), movieSize.getHeight());
+				PixelStore store = new PixelStoreImpl();
+				LoanerPicture lPicture = filter.filter(picture, store);
+				bufImg = AWTUtil.toBufferedImage(lPicture.getPicture());
+			} catch (Exception e) {
+				log.error("", e);
+			}
+		}
+		return bufImg;
+	}
+
+}
diff --git a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java
index 6d85c13da70a3f62b8064bb009b02a131b3821da..54f31594aa5b9d51d0a92fce394a2743791f7415 100644
--- a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java
+++ b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java
@@ -33,6 +33,7 @@ import org.jcodec.api.FrameGrab;
 import org.jcodec.common.Codec;
 import org.jcodec.common.VideoCodecMeta;
 import org.jcodec.common.io.FileChannelWrapper;
+import org.jcodec.common.model.Picture;
 import org.jcodec.containers.mp4.boxes.MovieBox;
 import org.jcodec.containers.mp4.demuxer.MP4Demuxer;
 import org.jcodec.scale.AWTUtil;
@@ -102,11 +103,12 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 					FileChannelWrapper in = new FileChannelWrapper(ch);
 					MP4Demuxer demuxer1 = MP4Demuxer.createMP4Demuxer(in)) {
 				
-				
-				org.jcodec.common.model.Size size = demuxer1.getMovie().getDisplaySize();
+				MovieBox movieBox = demuxer1.getMovie();
+				org.jcodec.common.model.Size size = movieBox.getDisplaySize();
 				// Case 1: standard case, get dimension from movie
 				int w = size.getWidth();
 				int h = size.getHeight();
+				
 				// Case 2: landscape movie from iOS: width and height is negative, no dunny why
 				if (w < 0 && h < 0) {
 					w = 0 - w;
@@ -131,7 +133,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 				}
 				return new Size(w, h, false);
 			} catch (Exception | AssertionError e) {
-				log.error("Cannot extract size of: " + media, e);
+				log.error("Cannot extract size of: {}", media, e);
 			}
 		} else if(suffix.equals("flv")) {
 			try(InputStream stream = new FileInputStream(file)) {
@@ -143,7 +145,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 					return new Size(w, h, false);
 				}
 			} catch (Exception e) {
-				log.error("Cannot extract size of: " + media, e);
+				log.error("Cannot extract size of: {}", media, e);
 			}
 		}
 
@@ -178,7 +180,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 				// Simple calculation. Ignore NTSC and other issues for now
 				return duration / timescale * 1000l;
 			} catch (Exception | AssertionError e) {
-				log.error("Cannot extract duration of: " + media, e);
+				log.error("Cannot extract duration of: {}", media, e);
 			}
 		}
 
@@ -205,7 +207,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 					MP4Demuxer demuxer1 = MP4Demuxer.createMP4Demuxer(in)) {
 				return demuxer1.getVideoTrack().getMeta().getTotalFrames();
 			} catch (Exception | AssertionError e) {
-				log.error("Cannot extract num. of frames of: " + media, e);
+				log.error("Cannot extract num. of frames of: {}", media, e);
 			}
 		}
 
@@ -252,9 +254,12 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 				WorkThreadInformations.setInfoFiles(null, file);
 				WorkThreadInformations.set("Generate thumbnail (video) VFSLeaf=" + file);
 				
-				File baseFile = ((LocalFileImpl)file).getBasefile();
+				File movieFile = ((LocalFileImpl)file).getBasefile();
+				Size movieSize = getSize(file, "mp4");
 				File scaledImage = ((LocalFileImpl)thumbnailFile).getBasefile();
-				BufferedImage frame = AWTUtil.toBufferedImage(FrameGrab.getFrameFromFile(baseFile, 20));
+				Picture picture = FrameGrab.getFrameFromFile(movieFile, 20);
+				BufferedImage frame = AWTUtil.toBufferedImage(picture);
+				frame = JCodecHelper.scale(movieSize, picture, frame);
 				Size scaledSize = ImageHelperImpl.calcScaledSize(frame, maxWidth, maxHeight);
 				if(ImageHelperImpl.writeTo(frame, scaledImage, scaledSize, "jpeg")) {
 					size = new FinalSize(scaledSize.getWidth(), scaledSize.getHeight());
@@ -269,4 +274,6 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 		}
 		return size;
 	}
+	
+
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/VideoManager.java b/src/main/java/org/olat/modules/video/VideoManager.java
index fb721458d0a82082f5cb245b1c2c54324f9bf92a..236855fd15831c9ec3c3e3ab0e03d6e45d669cda 100644
--- a/src/main/java/org/olat/modules/video/VideoManager.java
+++ b/src/main/java/org/olat/modules/video/VideoManager.java
@@ -522,6 +522,6 @@ public interface VideoManager {
 	 * @param frame resource
 	 * @return true if image proposal is mostly black
 	 */
-	public boolean getFrameWithFilter(VFSLeaf video, int frameNumber, long duration, VFSLeaf frame);
+	public boolean getFrameWithFilter(VFSLeaf video, Size movieSize, int frameNumber, long duration, VFSLeaf frame);
 
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
index e840fbb31ad66e0a820cee515779fbc0e7eb83ee..8fda24a363f2ce3ad2f237a35ad1d0103efd747d 100644
--- a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
+++ b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
@@ -51,6 +51,7 @@ import org.apache.logging.log4j.Logger;
 import org.jcodec.api.FrameGrab;
 import org.jcodec.common.io.FileChannelWrapper;
 import org.jcodec.common.io.NIOUtils;
+import org.jcodec.common.model.Picture;
 import org.jcodec.scale.AWTUtil;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.image.Crop;
@@ -58,6 +59,7 @@ import org.olat.core.commons.services.image.ImageService;
 import org.olat.core.commons.services.image.Size;
 import org.olat.core.commons.services.vfs.VFSMetadata;
 import org.olat.core.commons.services.vfs.VFSRepositoryService;
+import org.olat.core.commons.services.video.JCodecHelper;
 import org.olat.core.commons.services.video.MovieService;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
@@ -289,11 +291,15 @@ public class VideoManagerImpl implements VideoManager {
 	public boolean getFrame(VFSLeaf video, int frameNumber, VFSLeaf frame) {
 		File videoFile = ((LocalFileImpl)video).getBasefile();
 		
+		Size movieSize = movieService.getSize(video, FILETYPE_MP4);
+
 		try (FileChannelWrapper in = NIOUtils.readableChannel(videoFile)) {
 			FrameGrab frameGrab = FrameGrab.createFrameGrab(in).seekToFrameSloppy(frameNumber);
 			OutputStream frameOutputStream = frame.getOutputStream(false);
 
-			BufferedImage bufImg = AWTUtil.toBufferedImage(frameGrab.getNativeFrame());
+			Picture picture = frameGrab.getNativeFrame();
+			BufferedImage bufImg = AWTUtil.toBufferedImage(picture);
+			bufImg = JCodecHelper.scale(movieSize, picture, bufImg);
 			ImageIO.write(bufImg, "JPG", frameOutputStream);
 
 			// close everything to prevent resource leaks
@@ -301,22 +307,24 @@ public class VideoManagerImpl implements VideoManager {
 
 			return true;
 		} catch (Exception | AssertionError e) {
-			log.error("Could not get frame::" + frameNumber + " for video::" + videoFile.getAbsolutePath(), e);
+			log.error("Could not get frame::{} for video::{}", frameNumber, videoFile.getAbsolutePath(), e);
 			return false;
 		} 
 	}
 	
 	@Override
-	public boolean getFrameWithFilter(VFSLeaf video, int frameNumber, long duration, VFSLeaf frame) {
+	public boolean getFrameWithFilter(VFSLeaf video, Size movieSize, int frameNumber, long duration, VFSLeaf frame) {
 		File videoFile = ((LocalFileImpl)video).getBasefile();
 		BufferedImage bufImg = null;
 		boolean imgBlack = true;
 		int countBlack = 0;
+		
 		try (FileChannelWrapper in = NIOUtils.readableChannel(videoFile)) {
 			OutputStream frameOutputStream = frame.getOutputStream(false);
 			FrameGrab frameGrab = FrameGrab.createFrameGrab(in).seekToFrameSloppy(frameNumber);
 
-			bufImg = AWTUtil.toBufferedImage(frameGrab.getNativeFrame());
+			Picture picture = frameGrab.getNativeFrame();
+			bufImg = AWTUtil.toBufferedImage(picture);
 
 			int xmin = bufImg.getMinX();
 			int ymin = bufImg.getMinY();
@@ -340,6 +348,7 @@ public class VideoManagerImpl implements VideoManager {
 				imgBlack = true;
 			} else {
 				imgBlack = false;
+				bufImg = JCodecHelper.scale(movieSize, picture, bufImg);
 				ImageIO.write(bufImg, "JPG", frameOutputStream);
 			}
 			// avoid endless loop
@@ -351,7 +360,7 @@ public class VideoManagerImpl implements VideoManager {
 
 			return imgBlack;
 		} catch (Exception | AssertionError e) {
-			log.error("Could not get frame::" + frameNumber + " for video::" + videoFile.getAbsolutePath(), e);
+			log.error("Could not get frame: {} for video: {}", frameNumber, videoFile.getAbsolutePath(), e);
 			return false;
 		}
 	}
@@ -404,7 +413,7 @@ public class VideoManagerImpl implements VideoManager {
 		try {
 			return (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
 		} catch (Exception e) {
-			log.error("Error while parsing XStream file for videoResource::" + videoResource, e);
+			log.error("Error while parsing XStream file for videoResource::{}", videoResource, e);
 			// return an empty, so at least it displays something and not an error
 			VideoMetadata meta =  new VideoMetadataImpl();
 			meta.setWidth(800);
@@ -534,7 +543,7 @@ public class VideoManagerImpl implements VideoManager {
 		DecimalFormat df = new DecimalFormat("#.##");
 		df.setRoundingMode(RoundingMode.FLOOR);
 		String ratioCalculated = df.format(width / (height + 1.0));
-		String ratioString = "unknown";
+		String ratioString;
 		
 		switch (ratioCalculated) {
 		case "1.2": 
@@ -1079,7 +1088,7 @@ public class VideoManagerImpl implements VideoManager {
 		try(OutputStream bos = new BufferedOutputStream(webvtt.getOutputStream(false))) {
 			FileUtils.save(bos, vttString.toString(), ENCODING);
 		} catch (IOException e) {
-			log.error("chapter.vtt could not be saved for videoResource::" + videoResource, e);
+			log.error("chapter.vtt could not be saved for videoResource::{}", videoResource, e);
 		}
 	}
 	
diff --git a/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java b/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java
index 0e7e18b7c9578ce97418e41b7dee9ce13b8e2b4f..ad18fd5d47fcc3711967752a6abeea3ff7033a95 100644
--- a/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java
+++ b/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java
@@ -107,14 +107,14 @@ public class VideoTranscodingJob extends JobWithDB {
 		for (VideoTranscoding videoTrans : videoTranscodings) {
 			String transcoder = videoTrans.getTranscoder();
 			if (transcoder == null) { 
-				log.info("Start transcoding video with resolution::" + videoTrans.getResolution()
-					+ " for video resource::" + videoTrans.getVideoResource().getResourceableId());
+				log.info("Start transcoding video with resolution: {} for video resource: {}",
+						videoTrans.getResolution(), videoTrans.getVideoResource().getResourceableId());
 				videoTrans.setTranscoder(VideoTranscoding.TRANSCODER_LOCAL);
 				videoTranscoding = videoManager.updateVideoTranscoding(videoTrans);				
 				break;
 			} else if (transcoder.equals(VideoTranscoding.TRANSCODER_LOCAL)) {
-				log.info("Continue with transcoding video with resolution::" + videoTrans.getResolution()
-					+ " for video resource::" + videoTrans.getVideoResource().getResourceableId());
+				log.info("Continue with transcoding video with resolution: {} for video resource: {}",
+						videoTrans.getResolution(), videoTrans.getVideoResource().getResourceableId());
 				videoTranscoding = videoTrans;								
 				break;
 			}
@@ -238,7 +238,7 @@ public class VideoTranscodingJob extends JobWithDB {
 		if(exitCode == 0) {
 			videoTranscoding.setStatus(VideoTranscoding.TRANSCODING_STATUS_DONE);
 		} else {
-			log.error("Exit code " + videoTranscoding + ":" + exitCode);
+			log.error("Exit code {}:{}", videoTranscoding, exitCode);
 			videoTranscoding.setStatus(VideoTranscoding.TRANSCODING_STATUS_ERROR);
 		}
 		videoTranscoding = videoManager.updateVideoTranscoding(videoTranscoding);
@@ -269,7 +269,7 @@ public class VideoTranscodingJob extends JobWithDB {
 					int end = line.indexOf(".");
 					if (end != -1 && end < 5) {
 						String percent = line.substring(2, end);
-						log.debug("Output: " + percent);		
+						log.debug("Output: {}", percent);		
 						// update version file for UI
 						try {
 							videoTranscoding.setStatus(Integer.parseInt(percent));
@@ -303,7 +303,7 @@ public class VideoTranscodingJob extends JobWithDB {
 			
 			String line = null;
 			while ((line = berr.readLine()) != null) {
-				log.debug("Error: " + line);
+				log.debug("Error: {}", line);
 			}
 		} catch (IOException e) {
 			log.error("", e);
diff --git a/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java b/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java
index 33c37a40f01ec19204816343c0bea752097ac5e7..f0547e0d496d9bfe5bf854d2789daedeb5b85f6e 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoPosterSelectionForm.java
@@ -28,6 +28,8 @@ import java.util.UUID;
 import javax.servlet.http.HttpServletRequest;
 
 import org.olat.core.commons.modules.bc.FolderEvent;
+import org.olat.core.commons.services.image.Size;
+import org.olat.core.commons.services.video.MovieService;
 import org.olat.core.dispatcher.mapper.Mapper;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -47,6 +49,7 @@ 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;
+import org.olat.modules.video.VideoFormat;
 import org.olat.modules.video.VideoManager;
 import org.olat.modules.video.VideoMeta;
 import org.olat.resource.OLATResource;
@@ -64,12 +67,16 @@ public class VideoPosterSelectionForm extends BasicController {
 	private VFSLeaf tmpFile;
 	private VFSContainer tmpContainer;
 
-	@Autowired
-	private VideoManager videoManager;
 	private final VelocityContainer proposalLayout;
 
+	private Size movieSize;
 	private static final int STEP = 24;
 	private final boolean hasProposals;
+	
+	@Autowired
+	private MovieService movieService;
+	@Autowired
+	private VideoManager videoManager;
 
 	public VideoPosterSelectionForm(UserRequest ureq, WindowControl wControl,
 			OLATResource videoResource, VideoMeta videoMetadata) {
@@ -83,8 +90,14 @@ public class VideoPosterSelectionForm extends BasicController {
 		if(StringHelper.containsNonWhitespace(videoMetadata.getUrl())) {
 			videoFile = videoManager.downloadTmpVideo(videoResource, videoMetadata);
 			tmpFile = videoFile;// delete temporary file
+			if(videoMetadata.getVideoFormat() == VideoFormat.m3u8) {
+				movieSize = movieService.getSize(videoFile, VideoFormat.mp4.name());
+			}
 		} else {
 			videoFile = videoManager.getMasterVideoFile(videoResource);
+			if(videoMetadata.getVideoFormat() == VideoFormat.mp4) {
+				movieSize = movieService.getSize(videoFile, VideoFormat.mp4.name());
+			}
 		}
 		
 		List<String> proposals = generatePosterProposals(videoFile);
@@ -116,7 +129,7 @@ public class VideoPosterSelectionForm extends BasicController {
 	
 	private List<String> generatePosterProposals(VFSLeaf videoFile) {
 		long frames = videoManager.getVideoFrameCount(videoFile);
-
+		
 		long framesStepping = frames / 7;
 		if(framesStepping == 0) {
 			framesStepping = 256;
@@ -135,7 +148,7 @@ public class VideoPosterSelectionForm extends BasicController {
 
 				boolean imgBlack = true;
 				for(int i=0; i<maxAdjust && imgBlack; i++) {
-					imgBlack = videoManager.getFrameWithFilter(videoFile, (currentFrame+adjust), frames, posterProposal);
+					imgBlack = videoManager.getFrameWithFilter(videoFile, movieSize, (currentFrame+adjust), frames, posterProposal);
 					
 					if (currentFrame + STEP <= frames) {
 						adjust += STEP;