引入依賴
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.3.1-1.5.4</version>
</dependency>
程式碼示例
文字水印實現
import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* 影片新增文字水印
*
* @author alin
*/
public class VideoWatermark {
public static void main(String[] args) throws Exception {
// 影片檔案
String inputFile = "D:\\test\\video.mp4";
// 輸出檔案
String outputFile = "D:\\test\\output.mp4";
// 初始化FFmpegFrameGrabber以讀取輸入影片檔案
try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile)) {
grabber.start();
// 初始化FFmpegFrameRecorder以寫入輸出影片檔案
try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels())) {
recorder.setFormat("mp4");
recorder.setSampleRate(grabber.getSampleRate());
recorder.setFrameRate(grabber.getFrameRate());
recorder.setTimestamp(grabber.getTimestamp());
recorder.setVideoBitrate(grabber.getVideoBitrate());
recorder.setVideoCodec(grabber.getVideoCodec());
recorder.start();
// 處理每一幀
Frame frame;
Java2DFrameConverter converter = new Java2DFrameConverter();
while ((frame = grabber.grab()) != null) {
if (frame.image != null) {
// 將Frame轉換為BufferedImage
BufferedImage bufferedImage = converter.getBufferedImage(frame);
// 在BufferedImage上繪製文字水印
Graphics2D g = bufferedImage.createGraphics();
// 啟用抗鋸齒
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 啟用文字抗鋸齒
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
// 使用支援中文的字型
g.setFont(new Font("Microsoft YaHei", Font.BOLD, 30));
g.setColor(Color.gray);
String watermarkText = "測試水印文字";
// 計算水印文字的位置 右下角
//FontMetrics fontMetrics = g.getFontMetrics();
//int textWidth = fontMetrics.stringWidth(watermarkText);
//int textHeight = fontMetrics.getHeight();
//int x = bufferedImage.getWidth() - textWidth - 10; // 右邊距10畫素
//int y = bufferedImage.getHeight() - textHeight + fontMetrics.getAscent() - 10; // 下邊距10畫素
// 計算水印文字的位置 左上角
int x = 10; // 左邊距10畫素
int y = 30; // 上邊距30畫素
g.drawString(watermarkText, x, y);
g.dispose();
// 將BufferedImage轉換回Frame
frame = converter.convert(bufferedImage);
}
// 記錄幀
recorder.record(frame);
}
// 關閉grabber和recorder
recorder.stop();
recorder.release();
grabber.stop();
}
}
}
}
圖片水印實現
import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* 影片新增圖片水印
*
* @author alin
*/
public class VideoWatermark {
public static void main(String[] args) throws Exception {
// 影片檔案
String inputFile = "D:\\test\\video.mp4";
// 輸出檔案
String outputFile = "D:\\test\\output.mp4";
// 水印照片
String watermarkImageUrl = "D:\\test\\test.png";
try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile)) {
grabber.start();
try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels())) {
recorder.setFormat("mp4");
recorder.setSampleRate(grabber.getSampleRate());
recorder.setFrameRate(grabber.getFrameRate());
recorder.setTimestamp(grabber.getTimestamp());
recorder.setVideoBitrate(grabber.getVideoBitrate());
recorder.setVideoCodec(grabber.getVideoCodec());
recorder.start();
BufferedImage watermarkImage = loadWatermarkImage(watermarkImageUrl);
Frame frame;
while ((frame = grabber.grab()) != null) {
if (frame.image != null) {
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bufferedImage = converter.getBufferedImage(frame);
// 在BufferedImage上繪製圖片水印
Graphics2D g = bufferedImage.createGraphics();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
int x = 10; // 左邊距10畫素
int y = 30; // 上邊距30畫素
g.drawImage(watermarkImage, x, y, null);
g.dispose();
frame = converter.convert(bufferedImage);
}
recorder.record(frame);
}
recorder.stop();
recorder.release();
grabber.stop();
}
}
}
/**
* 載入水印圖片
*
* @param imagePath 水印圖片路徑
* @return 水印圖片
* @throws IOException
*/
private static BufferedImage loadWatermarkImage(String imagePath) throws IOException {
//return ImageIO.read(new URL(imagePath));
return ImageIO.read(new File(imagePath));
}
}