Overview
So in my recent project, I need to manage video uploads and I think having a default placeholder for videos is quite boring. The right way would be having thumbnails for the videos.
It’s quite simple to create a thumbnail from a video with java.
There are a few choices when it comes to libraries. You can use javacv (huge) or use ffmpeg with net.bramp.ffmpeg.
I’ll go with the second option since it does the job without occupying 500MB to my final jar.
How to create thumbnail for video (jpg/base64)
<dependency> <groupId>net.bramp.ffmpeg</groupId> <artifactId>ffmpeg</artifactId> <version>0.8.0</version> </dependency>
public static String convertToBase64(String videoPath, FFmpeg ffmpeg) throws IOException { var tempFile = File.createTempFile("temp_image",".jpg"); var tempImagePath = tempFile.getAbsolutePath(); try { // Build FFmpeg command to extract a frame FFmpegBuilder builder = new FFmpegBuilder() .setInput(videoPath) .overrideOutputFiles(true) .addOutput(tempImagePath) .setFrames(1) // Extract only 1 frame .done(); // Execute the FFmpeg command FFmpegExecutor executor = new FFmpegExecutor(ffmpeg); executor.createJob(builder).run(); return convertToBase64(tempImagePath, 80); } catch (IOException e) { log.error("error rendering image ", e); } finally { tempFile.delete(); } return Constants.StaticImages.DEFAULT_VIDEO_PLACEHOLDER; } public static String convertToBase64(String imagePath, double scalePercent) throws IOException { // Read the original image from the file BufferedImage originalImage = ImageIO.read(new File(imagePath)); // Calculate the new dimensions based on the scaling percentage int targetWidth = (int) (originalImage.getWidth() * scalePercent / 100); int targetHeight = (int) (originalImage.getHeight() * scalePercent / 100); // Resize the image BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = resizedImage.createGraphics(); graphics.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); graphics.dispose(); // Convert the resized image to a ByteArrayOutputStream in JPEG format ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageIO.write(resizedImage, "jpeg", outputStream); // Encode to Base64 String base64Image = Base64.getEncoder().encodeToString(outputStream.toByteArray()); // Close the stream outputStream.close(); return "data:image/jpeg;base64," + base64Image; }
With this two methods, you can create a base64 text that represents the video quite efficiently.
Here is what I have on my project:

Conclusion
With the code above, you can create thumbnail for your videos. I’ve only tested the code with mp4 h264 codec.

I build softwares that solve problems. I also love writing/documenting things I learn/want to learn.