Last updated: February 5, 2025

<span aria-hidden="true" id="processing-videos-in-java-transcode-resize-and-watermark"></span>

# Processing videos in Java: transcode, resize, and watermark

![Tim Koschützki](/assets/images/teammates/avatar-tim-kos-1.jpg?dpl=dpl_AkBKiiEcd5MPUBn4NARw15mr6FeE)

**Tim Koschützki**

Co-founder · Berlin, Germany · Show bio

[](https://x.com/tim%5Fkos)[](https://github.com/tim-kos)

In today's digital landscape, video content is crucial. Whether you're developing a media application or managing a video platform, efficiently processing videos is essential. This guide walks you through transcoding, resizing, and watermarking videos in Java using the open source library JavaCV, which provides Java wrappers for FFmpeg.

<span aria-hidden="true" id="prerequisites"></span>

## Prerequisites

Before we begin, ensure you have the following installed:

* Java Development Kit (JDK): Version 11 or higher
* Maven: For managing project dependencies
* FFmpeg: Installed and accessible in your system's PATH

For Ubuntu/Linux systems, install the required packages:

```bash
sudo apt-get update
sudo apt-get install ffmpeg build-essential

```

Add the following dependency to your `pom.xml` to use JavaCV:

```xml
<dependencies>
    <dependency>
        <groupId>org.bytedeco</groupId>
        <artifactId>javacv-platform</artifactId>
        <version>1.5.11</version>
    </dependency>
</dependencies>

```

<span aria-hidden="true" id="transcoding-videos-in-java"></span>

## Transcoding videos in Java

Below is an example of how to transcode a video from one format to another using JavaCV. The code emphasizes robust error handling and resource management.

```java
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

public class VideoTranscoder {
    public static void transcode(String inputFile, String outputFile) throws Exception {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;

        try {
            grabber = new FFmpegFrameGrabber(inputFile);
            grabber.start();

            recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight());
            recorder.setVideoCodec(grabber.getVideoCodec());
            recorder.setFormat("mp4");
            recorder.setFrameRate(grabber.getFrameRate());
            recorder.setPixelFormat(grabber.getPixelFormat());

            if (grabber.getAudioChannels() > 0) {
                recorder.setAudioChannels(grabber.getAudioChannels());
                recorder.setAudioCodec(grabber.getAudioCodec());
                recorder.setSampleRate(grabber.getSampleRate());
            }

            recorder.start();

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                recorder.record(frame);
            }
        } catch (FFmpegFrameGrabber.Exception e) {
            if (e.getMessage().contains("No such file")) {
                throw new IllegalArgumentException("Video file not found", e);
            } else if (e.getMessage().contains("codec not found")) {
                throw new UnsupportedOperationException("Video codec not supported", e);
            }
            throw e;
        } finally {
            if (recorder != null) {
                try {
                    recorder.stop();
                } catch (FFmpegFrameRecorder.Exception e) {
                    // Log error but continue cleanup
                } finally {
                    recorder.release();
                }
            }
            if (grabber != null) {
                try {
                    grabber.release();
                } catch (FFmpegFrameGrabber.Exception e) {
                    // Log error but continue cleanup
                }
            }
        }
    }
}

```

<span aria-hidden="true" id="resizing-videos-using-javacv"></span>

## Resizing videos using JavaCV

To resize videos, process each frame and adjust its dimensions. This example uses OpenCV with JavaCV to resize video frames while ensuring resources are properly released.

```java
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size;
import static org.bytedeco.opencv.global.opencv_imgproc.resize;

public class VideoResizer {
    public static void resizeVideo(String inputFile, String outputFile, int width, int height) throws Exception {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();

        try {
            grabber = new FFmpegFrameGrabber(inputFile);
            grabber.start();

            recorder = new FFmpegFrameRecorder(outputFile, width, height);
            recorder.setVideoCodec(grabber.getVideoCodec());
            recorder.setFormat("mp4");
            recorder.setFrameRate(grabber.getFrameRate());
            recorder.setVideoBitrate(grabber.getVideoBitrate());
            recorder.setPixelFormat(grabber.getPixelFormat());

            if (grabber.getAudioChannels() > 0) {
                recorder.setAudioChannels(grabber.getAudioChannels());
                recorder.setAudioCodec(grabber.getAudioCodec());
                recorder.setSampleRate(grabber.getSampleRate());
            }

            recorder.start();

            Frame frame;
            while ((frame = grabber.grabImage()) != null) {
                Mat mat = converter.convert(frame);
                Mat resizedMat = new Mat();
                resize(mat, resizedMat, new Size(width, height));
                Frame resizedFrame = converter.convert(resizedMat);
                recorder.record(resizedFrame);

                mat.release();
                resizedMat.release();
            }
        } finally {
            if (recorder != null) {
                try {
                    recorder.stop();
                } catch (FFmpegFrameRecorder.Exception e) {
                    // Log error but continue cleanup
                } finally {
                    recorder.release();
                }
            }
            if (grabber != null) {
                try {
                    grabber.release();
                } catch (FFmpegFrameGrabber.Exception e) {
                    // Log error but continue cleanup
                }
            }
        }
    }
}

```

<span aria-hidden="true" id="adding-watermarks-to-videos"></span>

## Adding watermarks to videos

Overlaying a text watermark onto each frame can be achieved by drawing with OpenCV's functions. The example below demonstrates how to add a simple text watermark to a video using JavaCV.

```java
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

public class VideoWatermarker {
    public static void addWatermark(String inputFile, String outputFile, String watermarkText) throws Exception {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();

        try {
            grabber = new FFmpegFrameGrabber(inputFile);
            grabber.start();

            recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight());
            recorder.setVideoCodec(grabber.getVideoCodec());
            recorder.setFormat("mp4");
            recorder.setFrameRate(grabber.getFrameRate());
            recorder.setPixelFormat(grabber.getPixelFormat());

            if (grabber.getAudioChannels() > 0) {
                recorder.setAudioChannels(grabber.getAudioChannels());
                recorder.setAudioCodec(grabber.getAudioCodec());
                recorder.setSampleRate(grabber.getSampleRate());
            }

            recorder.start();

            Scalar color = new Scalar(255, 255, 255, 0);
            int font = FONT_HERSHEY_SIMPLEX;

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                if (frame.image != null) {
                    Mat mat = converter.convert(frame);
                    putText(mat, watermarkText, new Point(50, 50), font, 1.0, color, 2, LINE_AA, false);
                    Frame watermarkedFrame = converter.convert(mat);
                    recorder.record(watermarkedFrame);
                    mat.release();
                } else {
                    recorder.record(frame);
                }
            }
        } finally {
            if (recorder != null) {
                try {
                    recorder.stop();
                } catch (FFmpegFrameRecorder.Exception e) {
                    // Log error but continue cleanup
                } finally {
                    recorder.release();
                }
            }
            if (grabber != null) {
                try {
                    grabber.release();
                } catch (FFmpegFrameGrabber.Exception e) {
                    // Log error but continue cleanup
                }
            }
        }
    }
}

```

<span aria-hidden="true" id="memory-management-and-performance-optimization"></span>

## Memory management and performance optimization

Efficient video processing requires both optimized performance and effective memory management. In the example below, we use Java's ExecutorService to process multiple videos concurrently, taking advantage of all available processor cores.

```java
import java.util.*;
import java.util.concurrent.*;

public class VideoProcessingService {
    private static final int NUM_THREADS = Runtime.getRuntime().availableProcessors();
    private final ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);

    public void processVideosInParallel(List<String> videoFiles) {
        List<Future<?>> futures = new ArrayList<>();

        for (String file : videoFiles) {
            futures.add(executor.submit(() -> {
                try {
                    processVideo(file);
                } catch (Exception e) {
                    throw new RuntimeException("Failed to process video: " + file, e);
                }
            }));
        }

        // Wait for each task to complete
        for (Future<?> future : futures) {
            try {
                future.get();
            } catch (Exception e) {
                // Handle or log errors as needed
            }
        }
    }

    private void processVideo(String file) {
        // Implement your video processing logic here
    }

    public void shutdown() {
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

```

<span aria-hidden="true" id="testing-video-processing"></span>

## Testing video processing

Implement tests to verify your video processing code functions as expected. The following JUnit tests check that a video is transcoded without errors and that proper exceptions are thrown for invalid input files.

```java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.io.File;

public class VideoProcessingTest {
    @Test
    public void testVideoTranscoding() {
        File input = new File("test.mp4");
        File output = new File("output.mp4");

        assertDoesNotThrow(() -> {
            VideoTranscoder.transcode(input.getPath(), output.getPath());
            assertTrue(output.exists());
            assertTrue(output.length() > 0);
        });
    }

    @Test
    public void testInvalidVideoFile() {
        assertThrows(IllegalArgumentException.class, () -> {
            VideoTranscoder.transcode("nonexistent.mp4", "output.mp4");
        });
    }
}

```

<span aria-hidden="true" id="conclusion"></span>

## Conclusion

Processing videos in Java with JavaCV provides powerful capabilities for transcoding, resizing, and watermarking. The examples above demonstrate essential techniques such as proper resource management, error handling, and performance optimization. For high-volume or enterprise-scale video processing, consider exploring Transloadit's[Video Encoding](/services/video-encoding.md) service, which offers scalable and efficient solutions.

\#java#video-processing#ffmpeg#javacv#video-encoding-service

### 👩‍💻 Join 20k+ developers

Sign up for our [monthly newsletter](/newsletters.md) to receive direct links to 3 exclusive tech — and 2 product updates. No less, no more.

Your email:

Get access

## File uploading and encoding. Made simple.

Transloadit streamlines file handling for developers, trusted by brands like Coursera and The New York Times. We’re known for a reliable API, top-notch support, and a strong commitment to open source, with projects like [Uppy⁠](https://uppy.io) and [Tus⁠](https://tus.io) setting standards in file processing.

[Sign up](/c/)[Book a Demo](https://survey.typeform.com/to/kRg47Xi5)

No credit card needed

Cancel anytime
